aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/CMakeLists.txt1
-rw-r--r--tests/auto/cmake/CMakeLists.txt23
-rw-r--r--tests/auto/cmake/empty_qmldir/enemy.cpp2
-rw-r--r--tests/auto/cmake/empty_qmldir/enemy.h2
-rw-r--r--tests/auto/cmake/empty_qmldir/main.cpp2
-rw-r--r--tests/auto/cmake/qmlimportscanner/main.cpp2
-rw-r--r--tests/auto/cmake/qmlquery/CMakeLists.txt1
-rw-r--r--tests/auto/cmake/qmlquery/My/OtherThings/CMakeLists.txt28
-rw-r--r--tests/auto/cmake/qmlquery/My/OtherThings/test.cpp3
-rw-r--r--tests/auto/cmake/qmlquery/My/OtherThings/test.h18
-rw-r--r--tests/auto/cmake/qtquickcompiler/main.cpp2
-rw-r--r--tests/auto/cmake/shared_qml_module/CMakeLists.txt14
-rw-r--r--tests/auto/cmake/shared_qml_module/Scheduler/CMakeLists.txt33
-rw-r--r--tests/auto/cmake/shared_qml_module/Scheduler/MainScreen.qml5
-rw-r--r--tests/auto/cmake/shared_qml_module/Scheduler/schedulerglobal.h15
-rw-r--r--tests/auto/cmake/shared_qml_module/Scheduler/task.cpp47
-rw-r--r--tests/auto/cmake/shared_qml_module/Scheduler/task.h34
-rw-r--r--tests/auto/cmake/shared_qml_module/SchedulerApp/CMakeLists.txt44
-rw-r--r--tests/auto/cmake/shared_qml_module/SchedulerApp/Main.qml12
-rw-r--r--tests/auto/cmake/shared_qml_module/SchedulerApp/main.cpp21
-rw-r--r--tests/auto/cmake/shared_qml_module/external/CMakeLists.txt1
-rw-r--r--tests/auto/cmake/shared_qml_module/external/nested/module/CMakeLists.txt15
-rw-r--r--tests/auto/cmake/shared_qml_module/external/nested/module/Test.qml3
-rw-r--r--tests/auto/cmake/shared_qml_module/tests/CMakeLists.txt1
-rw-r--r--tests/auto/cmake/shared_qml_module/tests/auto/CMakeLists.txt1
-rw-r--r--tests/auto/cmake/shared_qml_module/tests/auto/unit/CMakeLists.txt40
-rw-r--r--tests/auto/cmake/shared_qml_module/tests/auto/unit/dummy.cpp1
-rw-r--r--tests/auto/cmake/shared_qml_module/tests/auto/unit/tst_models.cpp45
-rw-r--r--tests/auto/cmake/test_common_import_path/CMakeLists.txt5
-rw-r--r--tests/auto/cmake/test_common_import_path/main.cpp2
-rw-r--r--tests/auto/cmake/test_generate_qmlls_ini/CMakeLists.txt43
-rw-r--r--tests/auto/cmake/test_generate_qmlls_ini/Dotted/CMakeLists.txt4
-rw-r--r--tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/CMakeLists.txt9
-rw-r--r--tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Hello/CMakeLists.txt4
-rw-r--r--tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Hello/World/CMakeLists.txt7
-rw-r--r--tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Hello/World/Main.qml4
-rw-r--r--tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Main.qml4
-rw-r--r--tests/auto/cmake/test_generate_qmlls_ini/Main.qml5
-rw-r--r--tests/auto/cmake/test_generate_qmlls_ini/SomeSubfolder/CMakeLists.txt13
-rw-r--r--tests/auto/cmake/test_generate_qmlls_ini/SomeSubfolder/Main.qml5
-rw-r--r--tests/auto/cmake/test_generate_qmlls_ini/main.cpp98
-rw-r--r--tests/auto/cmake/test_import_static_shapes_plugin_resources/app.qml2
-rw-r--r--tests/auto/cmake/test_import_static_shapes_plugin_resources/tst_main.cpp2
-rw-r--r--tests/auto/cmake/test_internal_singleton/CMakeLists.txt23
-rw-r--r--tests/auto/cmake/test_internal_singleton/Test.qml4
-rw-r--r--tests/auto/cmake/test_link_qml_module_without_target/Base/Base.cpp10
-rw-r--r--tests/auto/cmake/test_link_qml_module_without_target/Base/Base.h16
-rw-r--r--tests/auto/cmake/test_link_qml_module_without_target/Base/CMakeLists.txt13
-rw-r--r--tests/auto/cmake/test_link_qml_module_without_target/Base/qml/Red.qml10
-rw-r--r--tests/auto/cmake/test_link_qml_module_without_target/CMakeLists.txt59
-rw-r--r--tests/auto/cmake/test_link_qml_module_without_target/Derived/CMakeLists.txt42
-rw-r--r--tests/auto/cmake/test_link_qml_module_without_target/Derived/qml/Blue.qml10
-rw-r--r--tests/auto/cmake/test_link_qml_module_without_target/Derived/qml/main.qml23
-rw-r--r--tests/auto/cmake/test_link_qml_module_without_target/main.cpp43
-rw-r--r--tests/auto/cmake/test_qml_app_deployment/Shapes/EllipseShape/ellipseitem.cpp2
-rw-r--r--tests/auto/cmake/test_qml_app_deployment/Shapes/EllipseShape/ellipseitem.h2
-rw-r--r--tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/FunkyItemQml.qml2
-rw-r--r--tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/funkyitem.cpp2
-rw-r--r--tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/funkyitem.h2
-rw-r--r--tests/auto/cmake/test_qml_app_deployment/main.cpp2
-rw-r--r--tests/auto/cmake/test_qml_app_deployment/main.qml2
-rw-r--r--tests/auto/cmake/test_static_qml_module/CMakeLists.txt38
-rw-r--r--tests/auto/cmake/test_static_qml_module/MyElement.cpp4
-rw-r--r--tests/auto/cmake/test_static_qml_module/MyElement.h20
-rw-r--r--tests/auto/cmake/test_static_qml_module/main.cpp35
-rw-r--r--tests/auto/cmake/test_static_qml_module/main.qml7
-rw-r--r--tests/auto/cmake/tooling_imports/First/Neighbor.cpp2
-rw-r--r--tests/auto/cmake/tooling_imports/First/Neighbor.h9
-rw-r--r--tests/auto/cmake/tooling_imports/main.cpp2
-rw-r--r--tests/auto/core/CMakeLists.txt4
-rw-r--r--tests/auto/core/qqmlsettings/CMakeLists.txt9
-rw-r--r--tests/auto/core/qqmlsettings/data/aliases.qml2
-rw-r--r--tests/auto/core/qqmlsettings/data/basic.qml2
-rw-r--r--tests/auto/core/qqmlsettings/data/categories.qml2
-rw-r--r--tests/auto/core/qqmlsettings/data/cpp-aliases.qml2
-rw-r--r--tests/auto/core/qqmlsettings/data/resources.qml10
-rw-r--r--tests/auto/core/qqmlsettings/data/siblings.qml2
-rw-r--r--tests/auto/core/qqmlsettings/data/types.qml2
-rw-r--r--tests/auto/core/qqmlsettings/test_settings.ini3
-rw-r--r--tests/auto/core/qqmlsettings/tst_qqmlsettings.cpp14
-rw-r--r--tests/auto/core/qqmlstandardpaths/CMakeLists.txt2
-rw-r--r--tests/auto/core/qqmlstandardpaths/data/tst_standardpaths.qml2
-rw-r--r--tests/auto/core/qqmlstandardpaths/tst_qqmlstandardpaths.cpp6
-rw-r--r--tests/auto/core/qqmlsysteminformation/CMakeLists.txt2
-rw-r--r--tests/auto/core/qqmlsysteminformation/data/tst_systeminformation.qml2
-rw-r--r--tests/auto/core/qqmlsysteminformation/tst_qqmlsysteminformation.cpp2
-rw-r--r--tests/auto/guiapplauncher/examples.txt15
-rw-r--r--tests/auto/particles/qquickage/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickage/data/jump.qml2
-rw-r--r--tests/auto/particles/qquickage/data/kill.qml2
-rw-r--r--tests/auto/particles/qquickage/data/onceoff.qml2
-rw-r--r--tests/auto/particles/qquickage/data/sustained.qml2
-rw-r--r--tests/auto/particles/qquickage/tst_qquickage.cpp2
-rw-r--r--tests/auto/particles/qquickangleddirection/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickangleddirection/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickangleddirection/tst_qquickangleddirection.cpp2
-rw-r--r--tests/auto/particles/qquickcumulativedirection/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickcumulativedirection/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickcumulativedirection/tst_qquickcumulativedirection.cpp2
-rw-r--r--tests/auto/particles/qquickcustomaffector/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickcustomaffector/data/affectedSignal.qml2
-rw-r--r--tests/auto/particles/qquickcustomaffector/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickcustomaffector/data/move.qml2
-rw-r--r--tests/auto/particles/qquickcustomaffector/tst_qquickcustomaffector.cpp2
-rw-r--r--tests/auto/particles/qquickellipseextruder/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickellipseextruder/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickellipseextruder/tst_qquickellipseextruder.cpp2
-rw-r--r--tests/auto/particles/qquickfriction/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickfriction/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickfriction/data/threshold.qml2
-rw-r--r--tests/auto/particles/qquickfriction/tst_qquickfriction.cpp2
-rw-r--r--tests/auto/particles/qquickgravity/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickgravity/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickgravity/tst_qquickgravity.cpp2
-rw-r--r--tests/auto/particles/qquickgroupgoal/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickgroupgoal/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickgroupgoal/tst_qquickgroupgoal.cpp2
-rw-r--r--tests/auto/particles/qquickimageparticle/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickimageparticle/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickimageparticle/data/colorVariance.qml2
-rw-r--r--tests/auto/particles/qquickimageparticle/data/colored.qml2
-rw-r--r--tests/auto/particles/qquickimageparticle/data/deformed.qml2
-rw-r--r--tests/auto/particles/qquickimageparticle/data/sprite.qml2
-rw-r--r--tests/auto/particles/qquickimageparticle/data/tabled.qml2
-rw-r--r--tests/auto/particles/qquickimageparticle/tst_qquickimageparticle.cpp2
-rw-r--r--tests/auto/particles/qquickitemparticle/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickitemparticle/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickitemparticle/data/loader.qml2
-rw-r--r--tests/auto/particles/qquickitemparticle/data/managed.qml2
-rw-r--r--tests/auto/particles/qquickitemparticle/data/takeGive.qml2
-rw-r--r--tests/auto/particles/qquickitemparticle/data/unmanaged.qml2
-rw-r--r--tests/auto/particles/qquickitemparticle/tst_qquickitemparticle.cpp2
-rw-r--r--tests/auto/particles/qquicklineextruder/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquicklineextruder/data/basic.qml2
-rw-r--r--tests/auto/particles/qquicklineextruder/tst_qquicklineextruder.cpp2
-rw-r--r--tests/auto/particles/qquickmaskextruder/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickmaskextruder/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickmaskextruder/tst_qquickmaskextruder.cpp2
-rw-r--r--tests/auto/particles/qquickparticlegroup/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickparticlegroup/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickparticlegroup/tst_qquickparticlegroup.cpp2
-rw-r--r--tests/auto/particles/qquickparticlesystem/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickparticlesystem/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickparticlesystem/data/crashaffectors.qml2
-rw-r--r--tests/auto/particles/qquickparticlesystem/tst_qquickparticlesystem.cpp2
-rw-r--r--tests/auto/particles/qquickpointattractor/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickpointattractor/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickpointattractor/tst_qquickpointattractor.cpp2
-rw-r--r--tests/auto/particles/qquickpointdirection/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickpointdirection/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickpointdirection/tst_qquickpointdirection.cpp2
-rw-r--r--tests/auto/particles/qquickrectangleextruder/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickrectangleextruder/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickrectangleextruder/tst_qquickrectangleextruder.cpp2
-rw-r--r--tests/auto/particles/qquickspritegoal/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickspritegoal/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickspritegoal/tst_qquickspritegoal.cpp2
-rw-r--r--tests/auto/particles/qquicktargetdirection/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquicktargetdirection/data/basic.qml2
-rw-r--r--tests/auto/particles/qquicktargetdirection/tst_qquicktargetdirection.cpp2
-rw-r--r--tests/auto/particles/qquicktrailemitter/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquicktrailemitter/data/basic.qml2
-rw-r--r--tests/auto/particles/qquicktrailemitter/tst_qquicktrailemitter.cpp2
-rw-r--r--tests/auto/particles/qquickturbulence/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickturbulence/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickturbulence/tst_qquickturbulence.cpp2
-rw-r--r--tests/auto/particles/qquickwander/CMakeLists.txt6
-rw-r--r--tests/auto/particles/qquickwander/data/basic.qml2
-rw-r--r--tests/auto/particles/qquickwander/tst_qquickwander.cpp2
-rw-r--r--tests/auto/particles/shared/particlestestsshared.h2
-rw-r--r--tests/auto/qml/CMakeLists.txt21
-rw-r--r--tests/auto/qml/animation/qabstractanimationjob/CMakeLists.txt6
-rw-r--r--tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp5
-rw-r--r--tests/auto/qml/animation/qanimationgroupjob/CMakeLists.txt6
-rw-r--r--tests/auto/qml/animation/qanimationgroupjob/tst_qanimationgroupjob.cpp5
-rw-r--r--tests/auto/qml/animation/qparallelanimationgroupjob/CMakeLists.txt6
-rw-r--r--tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp44
-rw-r--r--tests/auto/qml/animation/qpauseanimationjob/CMakeLists.txt6
-rw-r--r--tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp2
-rw-r--r--tests/auto/qml/animation/qsequentialanimationgroupjob/CMakeLists.txt6
-rw-r--r--tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp10
-rw-r--r--tests/auto/qml/bindingdependencyapi/CMakeLists.txt6
-rw-r--r--tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp34
-rw-r--r--tests/auto/qml/common/CMakeLists.txt11
-rw-r--r--tests/auto/qml/common/tst_qml_common.cpp168
-rw-r--r--tests/auto/qml/common/tst_qml_common.h35
-rw-r--r--tests/auto/qml/debugger/qdebugmessageservice/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qdebugmessageservice/data/test.qml2
-rw-r--r--tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp2
-rw-r--r--tests/auto/qml/debugger/qpacketprotocol/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp36
-rw-r--r--tests/auto/qml/debugger/qqmldebugclient/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp13
-rw-r--r--tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/data/test.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp16
-rw-r--r--tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenablerserver/qqmldebuggingenablerserver.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/breakOnAnchor.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/changeBreakpoint.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/condition.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/createComponent.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/exception.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/loadjsfile.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/quit.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/quitInJS.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/stepAction.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/test.js2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/test.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/timer.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp74
-rw-r--r--tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebuglocal/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocessprocess/qqmldebugprocessprocess.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebugservice/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebugservice/data/test.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp56
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationclient/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationclient/data/test.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationclient/tst_qqmldebugtranslationclient.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationservice/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmlenginecontrol/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp26
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/complexItem.qml4
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/customTypes.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/debuggerCrashOnAttach.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/emptyItem.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/fetchValueType.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/itemWithFunctions.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/jsonTest.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/rectangleWithTransitions.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp59
-rw-r--r--tests/auto/qml/debugger/qqmlinspector/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmlnativeconnector/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmlnativeconnector/tst_qqmlnativeconnector.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/broken.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/qtquick2.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/window.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/window1.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/window2.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/zoom.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/quit.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp14
-rw-r--r--tests/auto/qml/debugger/qv4debugger/CMakeLists.txt9
-rw-r--r--tests/auto/qml/debugger/qv4debugger/commontypes.h4
-rw-r--r--tests/auto/qml/debugger/qv4debugger/data/breakPointInJSModule.qml4
-rw-r--r--tests/auto/qml/debugger/qv4debugger/data/module1.js5
-rw-r--r--tests/auto/qml/debugger/qv4debugger/data/module2.mjs7
-rw-r--r--tests/auto/qml/debugger/qv4debugger/data/module3.mjs0
-rw-r--r--tests/auto/qml/debugger/qv4debugger/data/module4.mjs0
-rw-r--r--tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp81
-rw-r--r--tests/auto/qml/debugger/shared/debugutil.cpp2
-rw-r--r--tests/auto/qml/debugger/shared/debugutil_p.h2
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugprocess.cpp4
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugprocess_p.h2
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp2
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugtestservice.h2
-rw-r--r--tests/auto/qml/ecmascripttests/CMakeLists.txt13
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations10
-rw-r--r--tests/auto/qml/ecmascripttests/qjstest/CMakeLists.txt28
-rw-r--r--tests/auto/qml/ecmascripttests/qjstest/main.cpp90
-rwxr-xr-xtests/auto/qml/ecmascripttests/test262.py611
-rw-r--r--tests/auto/qml/ecmascripttests/test262runner.cpp (renamed from tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp)529
-rw-r--r--tests/auto/qml/ecmascripttests/test262runner.h (renamed from tests/auto/qml/ecmascripttests/qjstest/test262runner.h)54
-rw-r--r--tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp94
-rw-r--r--tests/auto/qml/linebylinelex/BLACKLIST5
-rw-r--r--tests/auto/qml/linebylinelex/CMakeLists.txt28
-rw-r--r--tests/auto/qml/linebylinelex/tst_linebylinelex.cpp17
-rw-r--r--tests/auto/qml/parserstress/CMakeLists.txt6
-rw-r--r--tests/auto/qml/parserstress/tst_parserstress.cpp6
-rw-r--r--tests/auto/qml/qjsengine/CMakeLists.txt7
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp464
-rw-r--r--tests/auto/qml/qjsmanagedvalue/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.cpp23
-rw-r--r--tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.h2
-rw-r--r--tests/auto/qml/qjsonbinding/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qjsonbinding/tst_qjsonbinding.cpp11
-rw-r--r--tests/auto/qml/qjsprimitivevalue/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qjsprimitivevalue/tst_qjsprimitivevalue.cpp34
-rw-r--r--tests/auto/qml/qjsvalue/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.cpp42
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.h9
-rw-r--r--tests/auto/qml/qjsvalueiterator/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp6
-rw-r--r--tests/auto/qml/qml/CMakeLists.txt8
-rw-r--r--tests/auto/qml/qml/data/resizeItem.qml28
-rw-r--r--tests/auto/qml/qml/data/sizedItem.qml19
-rw-r--r--tests/auto/qml/qml/data/unsizedItem.qml18
-rw-r--r--tests/auto/qml/qml/tst_qml.cpp127
-rw-r--r--tests/auto/qml/qmlbasicapp/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.cpp2
-rw-r--r--tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.h2
-rw-r--r--tests/auto/qml/qmlbasicapp/main.qml2
-rw-r--r--tests/auto/qml/qmlbasicapp/manual_imports.cpp2
-rw-r--r--tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp2
-rw-r--r--tests/auto/qml/qmlcachegen/CMakeLists.txt7
-rw-r--r--tests/auto/qml/qmlcachegen/data/aotstats/AotstatsClean.qml11
-rw-r--r--tests/auto/qml/qmlcachegen/data/aotstats/AotstatsMixed.qml7
-rw-r--r--tests/auto/qml/qmlcachegen/data/aotstats/cachegentest.qrc5
-rw-r--r--tests/auto/qml/qmlcachegen/data/aotstats/qmldir3
-rw-r--r--tests/auto/qml/qmlcachegen/data/truncateTest.qml764
-rw-r--r--tests/auto/qml/qmlcachegen/scriptstringprops.h2
-rw-r--r--tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp159
-rw-r--r--tests/auto/qml/qmlcppcodegen/CMakeLists.txt18
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/Action.qml7
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/B.qml5
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/BaseConstraint.qml9
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt279
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/CppMethodListReturnType.qml12
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/Dummy2.qml18
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/EditConstraint.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupOnQJSValueNonStrict.qml7
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupShadowed.qml19
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/NotificationItem.qml7
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/NotificationsUtils.js3
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/Panel.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/Planner.qml50
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ProgressBar/ProgressBar.ui.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ProgressBar/Root.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ProgressBar/TimelineAnimation.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/Satisfaction.qml10
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ShadowedObjectName.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ShadowedObjectNameDerived.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/StoreMetaEnum.qml12
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/Variable.qml22
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ambiguous.h2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ambiguousAs.qml15
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/arrayCtor.qml11
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/asCast.qml10
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump.qml33
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump_infinite.qml13
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/basicDTZ.qml40
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/birthdayparty.cpp19
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/birthdayparty.h8
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/boolCoercions.qml45
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/boolPointerMerge.qml15
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/childobject.qml13
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/compareOriginals.qml39
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/comparisonTypes.qml54
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/consoleTrace.qml8
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/conversionInDeadCode.qml32
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/conversions2.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/convertPrimitiveToVar.qml18
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.h34
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.qml13
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/convertToOriginalReadAcumulatorForUnaryOperators.qml13
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/cppbaseclass.h2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/dateConstruction.qml20
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/dateConversions.qml10
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/dialogButtonBox.qml8
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/dummyobjekt.h29
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h41
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enforceSignature.qml11
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enumConversion.qml5
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enumFromBadSingleton.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enumMarkedAsFlag.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enumProblems.qml5
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enumProperty.h71
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enumproblems.h68
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/equalityQUrl.qml16
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/equalityTestsWithNullOrUndefined.qml14
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/exceptionFromInner.qml10
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/extra/extra.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/extra2/extra.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/failures.qml60
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/fallbackresettable.qml23
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/fileDialog.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/flagEnum.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/gadgetwithenum.h38
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.h42
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.qml34
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/idAccess.qml5
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ignoredFunctionReturn.qml14
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/indirectlyShadowable.qml39
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/intToEnum.qml7
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/interactive.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/internalConversion.qml16
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/invisible.h36
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/iteration.qml20
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/jsArrayMethods.qml28
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsUntyped.qml17
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParams.qml26
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParamsUntyped.qml18
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/listConversion.qml17
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/listOfInvisible.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/listToString.qml25
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/listprovider.h24
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/math.qml1
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/mathMinMax.qml59
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/mathStaticProperties.qml17
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/mergedObjectRead.qml14
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/mergedObjectWrite.qml15
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/methodOnListLookup.qml16
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/methods.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/multiforeign.h2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/multipleCtors.qml13
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/nullAccessInsideSignalHandler.qml33
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/nullComparison.qml11
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/nullishCoalescing.qml37
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml42
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/objectLookupOnListElement.qml34
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/objectWithStringListMethod.qml7
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h53
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/optionalComparison.qml77
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/person.cpp20
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/person.h44
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/qtbug113150.qml13
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/readEnumFromInstance.qml16
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/readonlyListProperty.qml17
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/reduceWithNullThis.qml18
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/renameAdjust.qml19
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/resettable.h39
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/resettable.qml23
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/returnAfterReject.qml15
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/scopeIdLookup.qml20
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml19
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.h56
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.qml20
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/setLookupConversion.qml17
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/setLookupOriginalScope.qml17
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/shadowedAsCasts.qml31
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/shadowedMethod.qml35
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/shadowedPrimitiveCmpEqNull.qml16
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/shared/Slider.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/signalsWithLists.qml18
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/state.h2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/structuredValueType.qml8
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/theme.cpp2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/theme.h2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/thisObject.qml11
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/timelinetheme.cpp2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/timelinetheme.h2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/topLevelComponent.qml14
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/trigraphs.qml5
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/tst_qmlcppcodegen_verify.cpp47
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/undefinedToDouble.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/urlString.qml7
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/valueTypeCast.qml43
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/valueTypeCopy.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/valueTypeDefault.qml34
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/valueTypeReference.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/variantMap.qml27
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/variantMapLookup.h17
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/variantMapLookup.qml11
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/variantReturn.qml15
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/variantreturn.h63
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/voidConversion.qml10
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/weathermoduleurl.h61
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/withlength.h28
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/wrapwithvariant.h2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/writableVariantMap.h31
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/writeVariantMap.qml10
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/writeback.qml43
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp5745
-rw-r--r--tests/auto/qml/qmldiskcache/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp404
-rw-r--r--tests/auto/qml/qmlformat/CMakeLists.txt9
-rw-r--r--tests/auto/qml/qmlformat/data/Annotations.formatted.qml17
-rw-r--r--tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml10
-rw-r--r--tests/auto/qml/qmlformat/data/Example1.formatted.qml10
-rw-r--r--tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml10
-rw-r--r--tests/auto/qml/qmlformat/data/Example1.formatted2.qml10
-rw-r--r--tests/auto/qml/qmlformat/data/FrontInline.formatted.qml3
-rw-r--r--tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml4
-rw-r--r--tests/auto/qml/qmlformat/data/arrayEndComma.qml8
-rw-r--r--tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.formatted.qml10
-rw-r--r--tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.qml8
-rw-r--r--tests/auto/qml/qmlformat/data/blanklinesAfterComment.formatted.qml12
-rw-r--r--tests/auto/qml/qmlformat/data/blanklinesAfterComment.qml15
-rw-r--r--tests/auto/qml/qmlformat/data/class.formatted.js5
-rw-r--r--tests/auto/qml/qmlformat/data/class.js1
-rw-r--r--tests/auto/qml/qmlformat/data/commentInEnum.formatted.qml11
-rw-r--r--tests/auto/qml/qmlformat/data/commentInEnum.qml12
-rw-r--r--tests/auto/qml/qmlformat/data/commentInQmlObject.formatted.qml4
-rw-r--r--tests/auto/qml/qmlformat/data/commentInQmlObject.qml5
-rw-r--r--tests/auto/qml/qmlformat/data/destructuringFunctionParameter.formatted.qml24
-rw-r--r--tests/auto/qml/qmlformat/data/destructuringFunctionParameter.qml9
-rw-r--r--tests/auto/qml/qmlformat/data/directives.formatted.js8
-rw-r--r--tests/auto/qml/qmlformat/data/directives.js9
-rw-r--r--tests/auto/qml/qmlformat/data/directivesWithComments.formatted.js6
-rw-r--r--tests/auto/qml/qmlformat/data/directivesWithComments.js8
-rw-r--r--tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml12
-rw-r--r--tests/auto/qml/qmlformat/data/dontRemoveComments.qml8
-rw-r--r--tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml2
-rw-r--r--tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.formatted.qml13
-rw-r--r--tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.qml11
-rw-r--r--tests/auto/qml/qmlformat/data/enumWithValues.formatted.qml12
-rw-r--r--tests/auto/qml/qmlformat/data/enumWithValues.qml12
-rw-r--r--tests/auto/qml/qmlformat/data/escapeChars.formatted.qml16
-rw-r--r--tests/auto/qml/qmlformat/data/escapeChars.qml16
-rw-r--r--tests/auto/qml/qmlformat/data/esm.formatted.mjs44
-rw-r--r--tests/auto/qml/qmlformat/data/esm.mjs33
-rw-r--r--tests/auto/qml/qmlformat/data/filesOption/valid1.formatted.qml10
-rw-r--r--tests/auto/qml/qmlformat/data/filesOption/valid1.qml9
-rw-r--r--tests/auto/qml/qmlformat/data/filesOption/valid2.formatted.qml10
-rw-r--r--tests/auto/qml/qmlformat/data/filesOption/valid2.qml9
-rw-r--r--tests/auto/qml/qmlformat/data/forOf.formatted.qml1
-rw-r--r--tests/auto/qml/qmlformat/data/functionsSpacing.formatted.qml3
-rw-r--r--tests/auto/qml/qmlformat/data/importStatements.formatted.qml8
-rw-r--r--tests/auto/qml/qmlformat/data/importStatements.qml12
-rw-r--r--tests/auto/qml/qmlformat/data/javascriptBlock.formatted.qml6
-rw-r--r--tests/auto/qml/qmlformat/data/javascriptBlock.qml5
-rw-r--r--tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.formatted.js6
-rw-r--r--tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.js1
-rw-r--r--tests/auto/qml/qmlformat/data/lambdaWithIfElse.formatted.js7
-rw-r--r--tests/auto/qml/qmlformat/data/lambdaWithIfElse.js1
-rw-r--r--tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.formatted.js9
-rw-r--r--tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.js1
-rw-r--r--tests/auto/qml/qmlformat/data/messyIfStatement.formatted.js4
-rw-r--r--tests/auto/qml/qmlformat/data/messyIfStatement.js2
-rw-r--r--tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs20
-rw-r--r--tests/auto/qml/qmlformat/data/mini_esm.mjs3
-rw-r--r--tests/auto/qml/qmlformat/data/multilineComment.formatted.qml6
-rw-r--r--tests/auto/qml/qmlformat/data/nestedFunctions.formatted.qml2
-rw-r--r--tests/auto/qml/qmlformat/data/nestedIf.formatted.qml1
-rw-r--r--tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml137
-rw-r--r--tests/auto/qml/qmlformat/data/objectDestructuring.qml77
-rw-r--r--tests/auto/qml/qmlformat/data/objectsSpacing.formatted.qml3
-rw-r--r--tests/auto/qml/qmlformat/data/objectsSpacing.qml4
-rw-r--r--tests/auto/qml/qmlformat/data/pragma.formatted.js4
-rw-r--r--tests/auto/qml/qmlformat/data/pragma.formatted.qml8
-rw-r--r--tests/auto/qml/qmlformat/data/pragma.js1
-rw-r--r--tests/auto/qml/qmlformat/data/pragma.qml8
-rw-r--r--tests/auto/qml/qmlformat/data/propertyNames.formatted.qml6
-rw-r--r--tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml2
-rw-r--r--tests/auto/qml/qmlformat/data/simpleJSStatement.formatted.js1
-rw-r--r--tests/auto/qml/qmlformat/data/simpleJSStatement.js1
-rw-r--r--tests/auto/qml/qmlformat/data/simpleLoop.formatted.js4
-rw-r--r--tests/auto/qml/qmlformat/data/simpleLoop.js1
-rw-r--r--tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.formatted.js4
-rw-r--r--tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.js1
-rw-r--r--tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml9
-rw-r--r--tests/auto/qml/qmlformat/data/threeFunctions.formattedFuncSpacing.js11
-rw-r--r--tests/auto/qml/qmlformat/data/threeFunctions.formattedTabs.js9
-rw-r--r--tests/auto/qml/qmlformat/data/threeFunctions.formattedW2.js9
-rw-r--r--tests/auto/qml/qmlformat/data/threeFunctionsOneLine.js1
-rw-r--r--tests/auto/qml/qmlformat/data/twoFunctions.formatted.js12
-rw-r--r--tests/auto/qml/qmlformat/data/twoFunctions.js3
-rw-r--r--tests/auto/qml/qmlformat/tst_qmlformat.cpp311
-rw-r--r--tests/auto/qml/qmlimportscanner/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json30
-rw-r--r--tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Drawer.qml.json30
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Imports.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json46
-rw-r--r--tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Simple.qml.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Singleton.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Things.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json36
-rw-r--r--tests/auto/qml/qmlimportscanner/data/localImport.qml.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json30
-rw-r--r--tests/auto/qml/qmlimportscanner/data/rootPath.json40
-rw-r--r--tests/auto/qml/qmlimportscanner/tst_qmlimportscanner.cpp4
-rw-r--r--tests/auto/qml/qmllint/CMakeLists.txt12
-rw-r--r--tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/A.qml5
-rw-r--r--tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/qmldir2
-rw-r--r--tests/auto/qml/qmllint/data/IsNotAnEntryOfEnum.qml14
-rw-r--r--tests/auto/qml/qmllint/data/LocaleTest/localeTest.qmltypes31
-rw-r--r--tests/auto/qml/qmllint/data/LocaleTest/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/Outer.qml5
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/multi.qrc10
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qml/Inner.qml5
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/Page.qml5
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/qmldir1
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qml/qmldir1
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qmldir5
-rw-r--r--tests/auto/qml/qmllint/data/MyStyle/MyStyle.qmltypes112
-rw-r--r--tests/auto/qml/qmllint/data/MyStyle/ToolBar.qml12
-rw-r--r--tests/auto/qml/qmllint/data/MyStyle/qmldir4
-rw-r--r--tests/auto/qml/qmllint/data/NeedImportPath.qml5
-rw-r--r--tests/auto/qml/qmllint/data/Qtbug111015/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/Qtbug111015/qtbug111015.qmltypes20
-rw-r--r--tests/auto/qml/qmllint/data/SharedFunctions.js5
-rw-r--r--tests/auto/qml/qmllint/data/StringToDateTime/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/StringToDateTime/stringToDateTime.qmltypes14
-rw-r--r--tests/auto/qml/qmllint/data/TestTypes/testtypes.qmltypes20
-rw-r--r--tests/auto/qml/qmllint/data/Things/plugins.qmltypes20
-rw-r--r--tests/auto/qml/qmllint/data/UnqualifiedInStoreSloppy.qml12
-rw-r--r--tests/auto/qml/qmllint/data/UnqualifiedInStoreStrict.qml12
-rw-r--r--tests/auto/qml/qmllint/data/addressableValue.qml8
-rw-r--r--tests/auto/qml/qmllint/data/attachedImportUse.qml7
-rw-r--r--tests/auto/qml/qmllint/data/badAliasNotAnExpression.qml8
-rw-r--r--tests/auto/qml/qmllint/data/bad_builtins/builtins.qmltypes513
-rw-r--r--tests/auto/qml/qmllint/data/coercetovoid.qml8
-rw-r--r--tests/auto/qml/qmllint/data/customParser.qml4
-rw-r--r--tests/auto/qml/qmllint/data/dontCheckJSTypes.qml11
-rw-r--r--tests/auto/qml/qmllint/data/findMemberPrint.qml13
-rw-r--r--tests/auto/qml/qmllint/data/generalizedGroupHint.qml23
-rw-r--r--tests/auto/qml/qmllint/data/groupedAttachedLayout.qml20
-rw-r--r--tests/auto/qml/qmllint/data/hidden/moduleWithQrc/main.qml11
-rw-r--r--tests/auto/qml/qmllint/data/hidden/moduleWithQrc/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/hidden/moduleWithQrc_raw_qml_0.qrc6
-rw-r--r--tests/auto/qml/qmllint/data/hidden/qmake_moduleWithQrc.qrc6
-rw-r--r--tests/auto/qml/qmllint/data/importNonexistentFile.qml3
-rw-r--r--tests/auto/qml/qmllint/data/importNullDevice.qml3
-rw-r--r--tests/auto/qml/qmllint/data/initReadonly.qml1
-rw-r--r--tests/auto/qml/qmllint/data/inlineComponent.qml1
-rw-r--r--tests/auto/qml/qmllint/data/invalidIdLookup.qml10
-rw-r--r--tests/auto/qml/qmllint/data/jsonArrayIsRecognized.qml8
-rw-r--r--tests/auto/qml/qmllint/data/jsonObjectIsRecognized.qml8
-rw-r--r--tests/auto/qml/qmllint/data/locale.qml6
-rw-r--r--tests/auto/qml/qmllint/data/lowerCaseQualifiedImport.qml9
-rw-r--r--tests/auto/qml/qmllint/data/lowerCaseQualifiedImport2.qml9
-rw-r--r--tests/auto/qml/qmllint/data/multifix.fixed.qml14
-rw-r--r--tests/auto/qml/qmllint/data/multifix.qml13
-rw-r--r--tests/auto/qml/qmllint/data/notQmlRootMethods.qml8
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_anchorsUndefined.qml1
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_propertyChangesInvalidTarget.qml8
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_propertyChangesParsed.qml19
-rw-r--r--tests/auto/qml/qmllint/data/qEventPoint.qml9
-rw-r--r--tests/auto/qml/qmllint/data/qmlRootMethods.qml12
-rw-r--r--tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml2
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml9
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml5
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml6
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml7
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml5
-rw-r--r--tests/auto/qml/qmllint/data/scriptInTemplate.qml6
-rw-r--r--tests/auto/qml/qmllint/data/scripts/Foo.js6
-rw-r--r--tests/auto/qml/qmllint/data/scripts/qmldir4
-rw-r--r--tests/auto/qml/qmllint/data/scripts/scripts.qmltypes22
-rw-r--r--tests/auto/qml/qmllint/data/scriptstring.qml73
-rw-r--r--tests/auto/qml/qmllint/data/settings/plugin/.qmllint.ini2
-rw-r--r--tests/auto/qml/qmllint/data/settings/plugin/elemenpass_pluginSettingTest.qml7
-rw-r--r--tests/auto/qml/qmllint/data/something.qml2
-rw-r--r--tests/auto/qml/qmllint/data/storeNameMethod.qml12
-rw-r--r--tests/auto/qml/qmllint/data/stringToDateTime.qml7
-rw-r--r--tests/auto/qml/qmllint/data/untitled/components/Foo.qml5
-rw-r--r--tests/auto/qml/qmllint/data/untitled/main.qml9
-rw-r--r--tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc6
-rw-r--r--tests/auto/qml/qmllint/data/useConstInvokable.qml5
-rw-r--r--tests/auto/qml/qmllint/data/validLiterals.qml6
-rw-r--r--tests/auto/qml/qmllint/data/valueTypesFromString.qml7
-rw-r--r--tests/auto/qml/qmllint/data/variantMapLookup.qml13
-rw-r--r--tests/auto/qml/qmllint/data/writeListProperty.qml7
-rw-r--r--tests/auto/qml/qmllint/lintplugin.cpp48
-rw-r--r--tests/auto/qml/qmllint/lintplugin.h4
-rw-r--r--tests/auto/qml/qmllint/tst_qmllint.cpp532
-rw-r--r--tests/auto/qml/qmlplugindump/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.cpp2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.cpp2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.cpp2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/types.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.cpp2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.cpp2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.cpp2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.cpp2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.h2
-rw-r--r--tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp6
-rw-r--r--tests/auto/qml/qmlsplitlib/CMakeLists.txt24
-rw-r--r--tests/auto/qml/qmlsplitlib/lib.h2
-rw-r--r--tests/auto/qml/qmlsplitlib/lib2.cpp5
-rw-r--r--tests/auto/qml/qmlsplitlib/lib2.h30
-rw-r--r--tests/auto/qml/qmlsplitlib/main.qml2
-rw-r--r--tests/auto/qml/qmlsplitlib/main2.qml8
-rw-r--r--tests/auto/qml/qmlsplitlib/manual_imports.cpp2
-rw-r--r--tests/auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp15
-rw-r--r--tests/auto/qml/qmltc/BLACKLIST5
-rw-r--r--tests/auto/qml/qmltc/CMakeLists.txt15
-rw-r--r--tests/auto/qml/qmltc/NamespaceTest/Subfolder/CMakeLists.txt3
-rw-r--r--tests/auto/qml/qmltc/NamespaceTest/Subfolder/Type.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/CMakeLists.txt28
-rw-r--r--tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/HelloExportedWorldNoFileName.qml5
-rw-r--r--tests/auto/qml/qmltc/QmltcExportedTests/CMakeLists.txt31
-rw-r--r--tests/auto/qml/qmltc/QmltcExportedTests/HelloExportedWorld.qml5
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt21
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/Connections.qml12
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/InlineComponentProvider.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/QmlTableModel.qml62
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/aliases.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/appendToQQmlListProperty.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/custominitialization.h64
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.cpp2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.cpp2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/private/testprivateproperty_p.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/singletontype.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.cpp2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.cpp2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.cpp2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithmanyproperties.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.cpp2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.cpp2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithrequiredproperties.h75
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithsignal.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithspecialproperties.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/generalizedGroupedProperty.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/inlineComponents.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/myCheckBox.qml5
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/mySignals.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/properties.qml14
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/propertyAliasAttributes.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/qtbug120700_main.qml25
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/qtbug123476.qml9
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/repeaterCrash.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/requiredProperties.qml61
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/signalConnections.qml46
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/singletons.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/stringToUrl.qml12
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/subfolder/code.js2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/translations.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/translationsById.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/valueTypeListProperty.qml2
-rw-r--r--tests/auto/qml/qmltc/nameconflict.cpp2
-rw-r--r--tests/auto/qml/qmltc/nameconflict.h2
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.cpp198
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.h14
-rw-r--r--tests/auto/qml/qmltc_manual/CMakeLists.txt9
-rw-r--r--tests/auto/qml/qmltc_manual/testclasses.h2
-rw-r--r--tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp2
-rw-r--r--tests/auto/qml/qmltc_qprocess/CMakeLists.txt17
-rw-r--r--tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h2
-rw-r--r--tests/auto/qml/qmltc_qprocess/cpptypes/typewithrequiredproperty.h27
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/QmlBaseFromAnotherModule.qml13
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredProperty.qml18
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredPropertyFromOutside.qml18
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/constructFromString.qml7
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/innerLevelRequiredProperty.qml10
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/invalidAliasRevision.qml2
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/invalidTypeAnnotation.qml20
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/unboundRequiredPropertyInInlineComponent.qml10
-rw-r--r--tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp128
-rw-r--r--tests/auto/qml/qmltyperegistrar/CMakeLists.txt28
-rw-r--r--tests/auto/qml/qmltyperegistrar/UnregisteredTypes/CMakeLists.txt4
-rw-r--r--tests/auto/qml/qmltyperegistrar/UnregisteredTypes/uncreatable.h51
-rw-r--r--tests/auto/qml/qmltyperegistrar/VersionZero/version_zero_type.h2
-rw-r--r--tests/auto/qml/qmltyperegistrar/duplicatedExports.h2
-rw-r--r--tests/auto/qml/qmltyperegistrar/enum.cpp5
-rw-r--r--tests/auto/qml/qmltyperegistrar/enum.h40
-rw-r--r--tests/auto/qml/qmltyperegistrar/foo.cpp2
-rw-r--r--tests/auto/qml/qmltyperegistrar/foo.h2
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/CMakeLists.txt3
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp2
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/foreign.h2
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/private/foreign_p.h (renamed from tests/auto/qml/qmltyperegistrar/foreign/foreign_p.h)3
-rw-r--r--tests/auto/qml/qmltyperegistrar/hppheader.hpp2
-rw-r--r--tests/auto/qml/qmltyperegistrar/missingTypes.json167
-rw-r--r--tests/auto/qml/qmltyperegistrar/noextheader2
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp651
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h388
-rw-r--r--tests/auto/qml/qqmlanybinding/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlanybinding/tst_qqmlanybinding.cpp4
-rw-r--r--tests/auto/qml/qqmlanybinding/withbindable.h2
-rw-r--r--tests/auto/qml/qqmlapplicationengine/CMakeLists.txt13
-rw-r--r--tests/auto/qml/qqmlapplicationengine/androidassets/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlapplicationengine/androidassets/tst_androidassets.cpp2
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/CMakeLists.txt30
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/Main.qml5
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.qmbin0 -> 92 bytes
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.ts12
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/main.cpp26
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/CMakeLists.txt30
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/Main.qml13
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.qmbin0 -> 91 bytes
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.ts12
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/main.cpp23
-rw-r--r--tests/auto/qml/qqmlapplicationengine/testapp/main.cpp2
-rw-r--r--tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp59
-rw-r--r--tests/auto/qml/qqmlbinding/CMakeLists.txt42
-rw-r--r--tests/auto/qml/qqmlbinding/WithBindableProperties.h2
-rw-r--r--tests/auto/qml/qqmlbinding/data/bindingOverwriting2.qml21
-rw-r--r--tests/auto/qml/qqmlbinding/data/propertiesAttachedToBindingItself.qml18
-rw-r--r--tests/auto/qml/qqmlbinding/data/restoreBinding2.qml2
-rw-r--r--tests/auto/qml/qqmlbinding/data/restoreBinding3.qml2
-rw-r--r--tests/auto/qml/qqmlbinding/data/restoreBinding4.qml2
-rw-r--r--tests/auto/qml/qqmlbinding/data/toggleEnableProperlyRemembersValues.qml13
-rw-r--r--tests/auto/qml/qqmlbinding/data/whenEvaluatedEarlyEnough.qml23
-rw-r--r--tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp85
-rw-r--r--tests/auto/qml/qqmlchangeset/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp39
-rw-r--r--tests/auto/qml/qqmlcomponent/CMakeLists.txt11
-rw-r--r--tests/auto/qml/qqmlcomponent/data/complexObjectArgument.qml28
-rw-r--r--tests/auto/qml/qqmlcomponent/data/createObject.qml3
-rw-r--r--tests/auto/qml/qqmlcomponent/data/createObjectWithScript.qml14
-rw-r--r--tests/auto/qml/qqmlcomponent/data/createQmlObject.qml21
-rw-r--r--tests/auto/qml/qqmlcomponent/data/dynamic.qml6
-rw-r--r--tests/auto/qml/qqmlcomponent/data/removeBinding.qml32
-rw-r--r--tests/auto/qml/qqmlcomponent/lifecyclewatcher.h24
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp186
-rw-r--r--tests/auto/qml/qqmlconnections/CMakeLists.txt7
-rw-r--r--tests/auto/qml/qqmlconnections/data/badSignalHandlerName.qml15
-rw-r--r--tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp83
-rw-r--r--tests/auto/qml/qqmlconsole/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlconsole/data/assert.qml2
-rw-r--r--tests/auto/qml/qqmlconsole/data/categorized_logging.qml2
-rw-r--r--tests/auto/qml/qqmlconsole/data/exception.qml2
-rw-r--r--tests/auto/qml/qqmlconsole/data/logging.qml2
-rw-r--r--tests/auto/qml/qqmlconsole/data/profiling.qml2
-rw-r--r--tests/auto/qml/qqmlconsole/data/tracing.qml2
-rw-r--r--tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp35
-rw-r--r--tests/auto/qml/qqmlcontext/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlcontext/data/A.qml6
-rw-r--r--tests/auto/qml/qqmlcontext/data/B.qml6
-rw-r--r--tests/auto/qml/qqmlcontext/data/C.qml6
-rw-r--r--tests/auto/qml/qqmlcontext/data/destroyContextObject.qml5
-rw-r--r--tests/auto/qml/qqmlcontext/data/gcDeletesContextObject.qml5
-rw-r--r--tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp229
-rw-r--r--tests/auto/qml/qqmlcpputils/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp21
-rw-r--r--tests/auto/qml/qqmldelegatemodel/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml2
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/clearCacheDuringInsertion.qml138
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml50
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/integerModel.qml2
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/listModel.qml2
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/modifyObjectUnderConstruction.qml18
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/overriddenModelData.qml55
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/persistedItemsCache.qml62
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/requiredModelData.qml50
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/resetModelData.qml16
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/typedModelData.qml64
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/universalModelData.qml72
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/viewUpdatedOnDelegateChoiceAffectingRoleChange.qml93
-rw-r--r--tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp411
-rw-r--r--tests/auto/qml/qqmldirparser/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmldirparser/data/versioned-internal/qmldir3
-rw-r--r--tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp24
-rw-r--r--tests/auto/qml/qqmlecmascript/CMakeLists.txt7
-rw-r--r--tests/auto/qml/qqmlecmascript/data/AssignListPropertyByIndexOnGadget.qml20
-rw-r--r--tests/auto/qml/qqmlecmascript/data/PropertyVarCircularComponent4.qml1
-rw-r--r--tests/auto/qml/qqmlecmascript/data/PropertyVarOwnershipComponent.qml1
-rw-r--r--tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.3.qml12
-rw-r--r--tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.4.qml12
-rw-r--r--tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlots.qml13
-rw-r--r--tests/auto/qml/qqmlecmascript/data/date.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/frozenQObject3.qml30
-rw-r--r--tests/auto/qml/qqmlecmascript/data/getThis.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/lookupsDoNotBypassProxy.qml29
-rw-r--r--tests/auto/qml/qqmlecmascript/data/methodCallOnDerivedSingleton.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/propertyVar.reparent.qml1
-rw-r--r--tests/auto/qml/qqmlecmascript/data/propertyVarImplicitOwnership.qml1
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs3.qml12
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qpropertyResetCorrectlyLinked.qml8
-rw-r--r--tests/auto/qml/qqmlecmascript/data/resetGadget.qml9
-rw-r--r--tests/auto/qml/qqmlecmascript/data/restoreObserverAfterReset.qml20
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnect.8.qml21
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnect.9.qml30
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnect.deletion.qml36
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnectSingleton.qml21
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptDisconnect.5.qml19
-rw-r--r--tests/auto/qml/qqmlecmascript/data/singletonTest.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/singletonTest2.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.cpp59
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h217
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp409
-rw-r--r--tests/auto/qml/qqmlengine/CMakeLists.txt7
-rw-r--r--tests/auto/qml/qqmlengine/data/bindingInstallUseAfterFree.qml19
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/Main.qml5
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonA.qml11
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonB.qml11
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/TestItem.qml5
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/qmldir3
-rw-r--r--tests/auto/qml/qqmlengine/data/markCurrentFunctionAsTranslationBinding.qml7
-rw-r--r--tests/auto/qml/qqmlengine/data/nativeModuleImport.mjs2
-rw-r--r--tests/auto/qml/qqmlengine/data/nativeModuleImport.qml2
-rw-r--r--tests/auto/qml/qqmlengine/data/variantListQJsonConversion.qml18
-rw-r--r--tests/auto/qml/qqmlengine/declarativelyregistered.cpp2
-rw-r--r--tests/auto/qml/qqmlengine/declarativelyregistered.h2
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp146
-rw-r--r--tests/auto/qml/qqmlengine/variantlistQJsonConversion.h53
-rw-r--r--tests/auto/qml/qqmlenginecleanup/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlenginecleanup/CustomModuleImport/ModuleType.qml2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.cpp2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/data/TestType.qml2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/data/testFile1.qml2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/data/testFile2.qml2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/data/testFile3.qml2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/data/types.qml2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp29
-rw-r--r--tests/auto/qml/qqmlerror/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlerror/tst_qqmlerror.cpp2
-rw-r--r--tests/auto/qml/qqmlexpression/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp38
-rw-r--r--tests/auto/qml/qqmlextensionplugin/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlextensionplugin/data/dummy.qml2
-rw-r--r--tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp4
-rw-r--r--tests/auto/qml/qqmlfile/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlfile/tst_qqmlfile.cpp2
-rw-r--r--tests/auto/qml/qqmlfileselector/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest/main.qml6
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+linux/Name.js1
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+macos/Name.js1
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/Name.js1
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest/qmldir3
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/MyButton.qml7
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/Name.js1
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/MyButton.qml7
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/Name.js1
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/MyButton.qml7
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/Name.js1
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/main.qml9
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/qmldir5
-rw-r--r--tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp45
-rw-r--r--tests/auto/qml/qqmlglobal/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp2
-rw-r--r--tests/auto/qml/qqmlimport/CMakeLists.txt22
-rw-r--r--tests/auto/qml/qqmlimport/MyPluginSupported/MyItem.qml2
-rw-r--r--tests/auto/qml/qqmlimport/MyPluginUnsupported/MyItem.qml2
-rw-r--r--tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/Preferred.qml5
-rw-r--r--tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/qmldir3
-rw-r--r--tests/auto/qml/qqmlimport/data/MyModuleName/Font.js4
-rw-r--r--tests/auto/qml/qqmlimport/data/MyModuleName/qmldir2
-rw-r--r--tests/auto/qml/qqmlimport/data/fileDotSlashImport.qml6
-rw-r--r--tests/auto/qml/qqmlimport/data/noimport/Main.qml5
-rw-r--r--tests/auto/qml/qqmlimport/data/noimport/qmldir3
-rw-r--r--tests/auto/qml/qqmlimport/data/prefer2.qml3
-rw-r--r--tests/auto/qml/qqmlimport/data/qualifiedScriptImport.qml8
-rw-r--r--tests/auto/qml/qqmlimport/data/testfile_supported.qml2
-rw-r--r--tests/auto/qml/qqmlimport/data/testfile_unsupported.qml2
-rw-r--r--tests/auto/qml/qqmlimport/qmldir2
-rw-r--r--tests/auto/qml/qqmlimport/qmlimports.qt.conf3
-rw-r--r--tests/auto/qml/qqmlimport/tst_qqmlimport.cpp156
-rw-r--r--tests/auto/qml/qqmlincubator/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlincubator/data/garbageCollection2.qml12
-rw-r--r--tests/auto/qml/qqmlincubator/testtypes.cpp2
-rw-r--r--tests/auto/qml/qqmlincubator/testtypes.h2
-rw-r--r--tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp12
-rw-r--r--tests/auto/qml/qqmlinfo/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlinfo/attached.cpp2
-rw-r--r--tests/auto/qml/qqmlinfo/attached.h2
-rw-r--r--tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp4
-rw-r--r--tests/auto/qml/qqmlinstantiator/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlinstantiator/data/listDataDestruction.qml20
-rw-r--r--tests/auto/qml/qqmlinstantiator/data/removeDuringModelChange.qml10
-rw-r--r--tests/auto/qml/qqmlinstantiator/stringmodel.h2
-rw-r--r--tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp103
-rw-r--r--tests/auto/qml/qqmlitemmodels/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlitemmodels/data/modelindex.qml2
-rw-r--r--tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml2
-rw-r--r--tests/auto/qml/qqmlitemmodels/qtestmodel.h7
-rw-r--r--tests/auto/qml/qqmlitemmodels/testtypes.h2
-rw-r--r--tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp4
-rw-r--r--tests/auto/qml/qqmljsscope/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmljsscope/QQmlJSScopeTests/CMakeLists.txt3
-rw-r--r--tests/auto/qml/qqmljsscope/QQmlJSScopeTests/extensiontypes.h23
-rw-r--r--tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.cpp2
-rw-r--r--tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.h2
-rw-r--r--tests/auto/qml/qqmljsscope/QQmlJSScopeTests/typewithproperties.h2
-rw-r--r--tests/auto/qml/qqmljsscope/QualifiedNamesTests/testtypes.h2
-rw-r--r--tests/auto/qml/qqmljsscope/data/attachedTypeResolution.qml6
-rw-r--r--tests/auto/qml/qqmljsscope/data/methodAndSignalSourceLocation.qml16
-rw-r--r--tests/auto/qml/qqmljsscope/data/ownModuleName.qml10
-rw-r--r--tests/auto/qml/qqmljsscope/data/requiredAlias.qml20
-rw-r--r--tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp329
-rw-r--r--tests/auto/qml/qqmllanguage/CMakeLists.txt8
-rw-r--r--tests/auto/qml/qqmllanguage/data/AliasHolder.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnumSelfReference.qml8
-rw-r--r--tests/auto/qml/qqmllanguage/data/Comps/IconPropertiesGroup.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/Comps/OverlayDrawer.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/Comps/qmldir4
-rw-r--r--tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml27
-rw-r--r--tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired1.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired2.qml8
-rw-r--r--tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/qmldir4
-rw-r--r--tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle1.qml15
-rw-r--r--tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle2.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/UIToolBar.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/alias.16.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/aliasWriter.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/ambiguousComponents.qml16
-rw-r--r--tests/auto/qml/qqmllanguage/data/asCastToInlineComponent.qml16
-rw-r--r--tests/auto/qml/qqmllanguage/data/asValueType.qml20
-rw-r--r--tests/auto/qml/qqmllanguage/data/asValueTypeGood.qml35
-rw-r--r--tests/auto/qml/qqmllanguage/data/badICAnnotation.qml25
-rw-r--r--tests/auto/qml/qqmllanguage/data/badSingleton/SingletonTest.qml (renamed from tests/auto/qml/qqmllanguage/data/SingletonTest.qml)0
-rw-r--r--tests/auto/qml/qqmllanguage/data/badSingleton/qmldir (renamed from tests/auto/qml/qqmllanguage/data/qmldir)0
-rw-r--r--tests/auto/qml/qqmllanguage/data/badSingleton/qtbug_85932.qml (renamed from tests/auto/qml/qqmllanguage/data/qtbug_85932.qml)0
-rw-r--r--tests/auto/qml/qqmllanguage/data/corpseInQmlList.qml13
-rw-r--r--tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml9
-rw-r--r--tests/auto/qml/qqmllanguage/data/deepAliasOnReadonly.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/derivedFromUnexposedBase.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/dynamicGroupPropertyRejected.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/enumPropsManyUnderlyingTypes.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/enumScopes.qml16
-rw-r--r--tests/auto/qml/qqmllanguage/data/inlineComponentWithImplicitComponent.qml27
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.3.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/invokableCtors.qml12
-rw-r--r--tests/auto/qml/qqmllanguage/data/isNullOrUndefined_interpreter.qml22
-rw-r--r--tests/auto/qml/qqmllanguage/data/isNullOrUndefined_jit.qml22
-rw-r--r--tests/auto/qml/qqmllanguage/data/jitExceptions.qml16
-rw-r--r--tests/auto/qml/qqmllanguage/data/jsonArrayProperty.qml191
-rw-r--r--tests/auto/qml/qqmllanguage/data/longConversion.qml28
-rw-r--r--tests/auto/qml/qqmllanguage/data/manuallyCallSignalHandler.qml11
-rw-r--r--tests/auto/qml/qqmllanguage/data/nestedVectors.qml27
-rw-r--r--tests/auto/qml/qqmllanguage/data/objectDeletionNotify.1.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/objectDeletionNotify.2.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/objectDeletionNotify.3.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/objectInList.qml17
-rw-r--r--tests/auto/qml/qqmllanguage/data/objectMethodClone.qml23
-rw-r--r--tests/auto/qml/qqmllanguage/data/optimizedSequenceShift.qml14
-rw-r--r--tests/auto/qml/qqmllanguage/data/optionalChainCallOnNullProperty.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/overrideDefaultProperty.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/retainThis.qml49
-rw-r--r--tests/auto/qml/qqmllanguage/data/signatureEnforced.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/signatureIgnored.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/singleton/RegisteredCompositeSingletonType.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/singleton/js/jspragma.js2
-rw-r--r--tests/auto/qml/qqmllanguage/data/singletonTest17.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/typedObjectList.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/unregisteredValueTypeConversion.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/variantObjectList.qml17
-rw-r--r--tests/auto/qml/qqmllanguage/testhelper/CMakeLists.txt13
-rw-r--r--tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.cpp7
-rw-r--r--tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.h20
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp54
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h640
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp1216
-rw-r--r--tests/auto/qml/qqmllistcompositor/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp21
-rw-r--r--tests/auto/qml/qqmllistmodel/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmllistmodel/data/nestedLists.qml37
-rw-r--r--tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp255
-rw-r--r--tests/auto/qml/qqmllistmodelworkerscript/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp160
-rw-r--r--tests/auto/qml/qqmllistreference/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmllistreference/data/consoleLogSyntheticList.qml8
-rw-r--r--tests/auto/qml/qqmllistreference/data/listIgnoresNull.qml21
-rw-r--r--tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp62
-rw-r--r--tests/auto/qml/qqmllocale/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmllocale/tst_qqmllocale.cpp31
-rw-r--r--tests/auto/qml/qqmlmetaobject/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp2
-rw-r--r--tests/auto/qml/qqmlmetatype/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlmetatype/data/Components/App.qml2
-rw-r--r--tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp114
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/optionalPlugin/optionalPlugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp95
-rw-r--r--tests/auto/qml/qqmlnotifier/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp2
-rw-r--r--tests/auto/qml/qqmlobjectmodel/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlobjectmodel/tst_qqmlobjectmodel.cpp2
-rw-r--r--tests/auto/qml/qqmlopenmetaobject/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp2
-rw-r--r--tests/auto/qml/qqmlparser/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlparser/tst_qqmlparser.cpp88
-rw-r--r--tests/auto/qml/qqmlpromise/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-all-empty-input.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-all-invoke-then-method.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-all-noniterable-input.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-last.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-mid.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-all-resolve.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-async-reject-with-value.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-async-resolve-with-value.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-executor-function-extensible.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-executor-reject.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-executor-resolve.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-executor-throw-exception.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-get-length.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-race-empty-input.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st-in-executor-function.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-race-resolve-2nd.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-reject-catch.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-reject-with-value.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-resolve-function-length.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-resolve-is-a-function.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-resolve-with-array.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-resolve-with-empty.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-resolve-with-promise.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-resolve-with-value.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/then-fulfilled-non-callable.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/then-reject-chaining.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/then-reject-non-callable.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/then-resolve-chaining.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/then-resolve-multiple-then.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp2
-rw-r--r--tests/auto/qml/qqmlproperty/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlproperty/data/invalidateQPropertyChangeTriggers.qml50
-rw-r--r--tests/auto/qml/qqmlproperty/data/listAssignmentSignals.qml13
-rw-r--r--tests/auto/qml/qqmlproperty/data/propertyStartsWithOn.qml9
-rw-r--r--tests/auto/qml/qqmlproperty/interfaces.h2
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp91
-rw-r--r--tests/auto/qml/qqmlpropertycache/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlpropertycache/data/duplicateIdsAndGeneralizedGroupProperties.qml64
-rw-r--r--tests/auto/qml/qqmlpropertycache/data/overriddenSignal.qml36
-rw-r--r--tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal.qml8
-rw-r--r--tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal2.qml6
-rw-r--r--tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp84
-rw-r--r--tests/auto/qml/qqmlpropertymap/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp29
-rw-r--r--tests/auto/qml/qqmlqt/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlqt/data/qtbug_125495.qml5
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp34
-rw-r--r--tests/auto/qml/qqmlsettings/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlsettings/data/aliases.qml2
-rw-r--r--tests/auto/qml/qqmlsettings/data/basic.qml2
-rw-r--r--tests/auto/qml/qqmlsettings/data/categories.qml2
-rw-r--r--tests/auto/qml/qqmlsettings/data/cpp-aliases.qml2
-rw-r--r--tests/auto/qml/qqmlsettings/data/siblings.qml2
-rw-r--r--tests/auto/qml/qqmlsettings/data/types.qml2
-rw-r--r--tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp2
-rw-r--r--tests/auto/qml/qqmlsqldatabase/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlsqldatabase/data/changeVersion.qml2
-rw-r--r--tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp7
-rw-r--r--tests/auto/qml/qqmltablemodel/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmltablemodel/data/TestModel.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/TestUtils.js2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/common.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/complex.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/dataAndSetData.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/empty.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/intAndDouble.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/omitTableModelColumnIndex.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp2
-rw-r--r--tests/auto/qml/qqmltimer/CMakeLists.txt7
-rw-r--r--tests/auto/qml/qqmltimer/tst_qqmltimer.cpp97
-rw-r--r--tests/auto/qml/qqmltranslation/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmltranslation/data/jstranslation.qml1
-rw-r--r--tests/auto/qml/qqmltranslation/data/pragmacontext.qml8
-rw-r--r--tests/auto/qml/qqmltranslation/data/pragmacontextstringliteral.qml8
-rw-r--r--tests/auto/qml/qqmltranslation/data/translation.js6
-rw-r--r--tests/auto/qml/qqmltranslation/data/translation.qml4
-rw-r--r--tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp65
-rw-r--r--tests/auto/qml/qqmltreemodeltotablemodel/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmltreemodeltotablemodel/testmodel.cpp30
-rw-r--r--tests/auto/qml/qqmltreemodeltotablemodel/testmodel.h3
-rw-r--r--tests/auto/qml/qqmltreemodeltotablemodel/tst_qqmltreemodeltotablemodel.cpp2
-rw-r--r--tests/auto/qml/qqmltypeloader/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmltypeloader/SlowImport/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmltypeloader/SlowImport/plugin.h2
-rw-r--r--tests/auto/qml/qqmltypeloader/SlowImport/slow.cpp2
-rw-r--r--tests/auto/qml/qqmltypeloader/SlowImport/slow.h2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/GenericView.qml2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Intercept.qml2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/NiceView.qml2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/doesExist.qml2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/a.qml3
-rw-r--r--tests/auto/qml/qqmltypeloader/data/load_synchronous.qml2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/test_intercept.qml2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/test_load_complete.qml2
-rw-r--r--tests/auto/qml/qqmltypeloader/declarativetesttype.h2
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp68
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/data/changedSignal.qml2
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/data/recursiveWriteBack.qml5
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/data/structuredValueTypes.qml17
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp7
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/testtypes.h216
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp191
-rw-r--r--tests/auto/qml/qqmlvaluetypes/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/constructors.qml14
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/matrix4x4_invokables.qml4
-rw-r--r--tests/auto/qml/qqmlvaluetypes/testtypes.cpp2
-rw-r--r--tests/auto/qml/qqmlvaluetypes/testtypes.h2
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp543
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.expect18
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.expect16
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.collection.allprop.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.response.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.responseXML.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/abort.expect16
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/abort.qml15
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml8
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml9
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml12
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.expect12
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml19
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/noqmlcontext.js4
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/open.qml9
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/open_network.expect12
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/open_sync.qml1
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/open_user.qml9
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/open_username.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.qml20
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.reply3
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml3
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.expect14
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect14
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/responseText.qml5
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/responseURL.qml21
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml4
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.expect16
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.qml5
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.10.expect16
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.expectbin258 -> 263 bytes
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.qml5
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.2.qml6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.3.qml6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.expect16
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.qml6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.5.qml6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.expect16
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.qml5
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.7.qml6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.8.expect14
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.9.expect14
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData.qml11
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_DELETE.expect12
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_GET.expect12
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_HEAD.expect12
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_patch.expect19
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_patch.qml3
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.expect16
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.qml5
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_caseInsensitive.qml8
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_illegalName.qml10
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_sent.qml3
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/status.expect12
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/status.qml4
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml4
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/text.expect6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp107
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp18
-rw-r--r--tests/auto/qml/qquickfolderlistmodel/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp2
-rw-r--r--tests/auto/qml/qquickworkerscript/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp103
-rw-r--r--tests/auto/qml/qrcqml/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qrcqml/tst_qrcqml.cpp12
-rw-r--r--tests/auto/qml/qtqmlmodules/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qtqmlmodules/tst_qtqmlmodules.cpp20
-rw-r--r--tests/auto/qml/qv4assembler/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qv4assembler/data/crash.qml2
-rw-r--r--tests/auto/qml/qv4assembler/tst_qv4assembler.cpp2
-rw-r--r--tests/auto/qml/qv4estable/CMakeLists.txt24
-rw-r--r--tests/auto/qml/qv4estable/tst_qv4estable.cpp40
-rw-r--r--tests/auto/qml/qv4identifiertable/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp2
-rw-r--r--tests/auto/qml/qv4mm/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qv4mm/data/createdestroy.qml2
-rw-r--r--tests/auto/qml/qv4mm/data/createobjects.qml2
-rw-r--r--tests/auto/qml/qv4mm/data/simpleObject.qml3
-rw-r--r--tests/auto/qml/qv4mm/data/storeLocal.qml34
-rw-r--r--tests/auto/qml/qv4mm/tst_qv4mm.cpp544
-rw-r--r--tests/auto/qml/qv4regexp/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qv4regexp/tst_qv4regexp.cpp2
-rw-r--r--tests/auto/qml/qv4urlobject/CMakeLists.txt26
-rw-r--r--tests/auto/qml/qv4urlobject/tst_qv4urlobject.cpp153
-rw-r--r--tests/auto/qml/qwidgetsinqml/CMakeLists.txt8
-rw-r--r--tests/auto/qml/qwidgetsinqml/dummy_imports.qml7
-rw-r--r--tests/auto/qml/qwidgetsinqml/tst_qwidgetsinqml.cpp19
-rw-r--r--tests/auto/qml/registrationmacros/CMakeLists.txt6
-rw-r--r--tests/auto/qml/registrationmacros/tst_registrationmacros.cpp2
-rw-r--r--tests/auto/qml/registrationmacros/types.cpp2
-rw-r--r--tests/auto/qml/registrationmacros/types.h2
-rw-r--r--tests/auto/qml/v4misc/CMakeLists.txt6
-rw-r--r--tests/auto/qml/v4misc/tst_v4misc.cpp2
-rw-r--r--tests/auto/qmldom/CMakeLists.txt1
-rw-r--r--tests/auto/qmldom/combined/CMakeLists.txt8
-rw-r--r--tests/auto/qmldom/combined/tst_dom_all.cpp7
-rw-r--r--tests/auto/qmldom/domdata/domitem/Base.qml5
-rw-r--r--tests/auto/qmldom/domdata/domitem/Derived.qml5
-rw-r--r--tests/auto/qmldom/domdata/domitem/ImportMeImplicitly.ui.qml6
-rw-r--r--tests/auto/qmldom/domdata/domitem/WithImplicitImport.qml5
-rw-r--r--tests/auto/qmldom/domdata/domitem/Yyy.qml35
-rw-r--r--tests/auto/qmldom/domdata/domitem/aliasProperties.qml2
-rw-r--r--tests/auto/qmldom/domdata/domitem/astComments.qml12
-rw-r--r--tests/auto/qmldom/domdata/domitem/attachedOrGroupedProperties.qml34
-rw-r--r--tests/auto/qmldom/domdata/domitem/breakStatement.qml9
-rw-r--r--tests/auto/qmldom/domdata/domitem/callExpressions.qml61
-rw-r--r--tests/auto/qmldom/domdata/domitem/checkScopes.qml11
-rw-r--r--tests/auto/qmldom/domdata/domitem/commaExpression.qml8
-rw-r--r--tests/auto/qmldom/domdata/domitem/conditionalExpression.qml8
-rw-r--r--tests/auto/qmldom/domdata/domitem/continueStatement.qml9
-rw-r--r--tests/auto/qmldom/domdata/domitem/crashes/bracketsInBinding.qml5
-rw-r--r--tests/auto/qmldom/domdata/domitem/crashes/lambda.qml7
-rw-r--r--tests/auto/qmldom/domdata/domitem/crashes/templateStrings.qml10
-rw-r--r--tests/auto/qmldom/domdata/domitem/ecmaScriptClass.qml44
-rw-r--r--tests/auto/qmldom/domdata/domitem/emptyMethodBody.qml6
-rw-r--r--tests/auto/qmldom/domdata/domitem/enumDeclarations.qml7
-rw-r--r--tests/auto/qmldom/domdata/domitem/fieldMemberExpression.qml32
-rw-r--r--tests/auto/qmldom/domdata/domitem/fileLocationRegion.qml8
-rw-r--r--tests/auto/qmldom/domdata/domitem/fileLocationRegions/comments.qml12
-rw-r--r--tests/auto/qmldom/domdata/domitem/fileLocationRegions/enums.qml12
-rw-r--r--tests/auto/qmldom/domdata/domitem/fileLocationRegions/functions.qml15
-rw-r--r--tests/auto/qmldom/domdata/domitem/fileLocationRegions/imports.qml11
-rw-r--r--tests/auto/qmldom/domdata/domitem/fileLocationRegions/pragmas.qml11
-rw-r--r--tests/auto/qmldom/domdata/domitem/finalizeScriptExpressions.qml29
-rw-r--r--tests/auto/qmldom/domdata/domitem/forStatements.qml15
-rw-r--r--tests/auto/qmldom/domdata/domitem/ifStatements.qml27
-rw-r--r--tests/auto/qmldom/domdata/domitem/import.js2
-rw-r--r--tests/auto/qmldom/domdata/domitem/inactiveVisitorMarkerCrash.qml13
-rw-r--r--tests/auto/qmldom/domdata/domitem/inlineComponents.qml17
-rw-r--r--tests/auto/qmldom/domdata/domitem/inlineObject.qml7
-rw-r--r--tests/auto/qmldom/domdata/domitem/invalidAliasProperties.qml2
-rw-r--r--tests/auto/qmldom/domdata/domitem/iterationStatements.qml64
-rw-r--r--tests/auto/qmldom/domdata/domitem/lambdas.qml41
-rw-r--r--tests/auto/qmldom/domdata/domitem/module.mjs6
-rw-r--r--tests/auto/qmldom/domdata/domitem/nullStatements.qml14
-rw-r--r--tests/auto/qmldom/domdata/domitem/objectBindings.qml13
-rw-r--r--tests/auto/qmldom/domdata/domitem/propertyBindings.qml13
-rw-r--r--tests/auto/qmldom/domdata/domitem/returnStatements.qml14
-rw-r--r--tests/auto/qmldom/domdata/domitem/simplestJSStatement.js1
-rw-r--r--tests/auto/qmldom/domdata/domitem/simplestJSmodule.mjs1
-rw-r--r--tests/auto/qmldom/domdata/domitem/switchStatement.qml28
-rw-r--r--tests/auto/qmldom/domdata/domitem/tryStatements.qml10
-rw-r--r--tests/auto/qmldom/domdata/domitem/unaryExpressions/decrement.qml7
-rw-r--r--tests/auto/qmldom/domdata/domitem/unaryExpressions/delete.qml7
-rw-r--r--tests/auto/qmldom/domdata/domitem/unaryExpressions/increment.qml7
-rw-r--r--tests/auto/qmldom/domdata/domitem/unaryExpressions/not.qml7
-rw-r--r--tests/auto/qmldom/domdata/domitem/unaryExpressions/postDecrement.qml7
-rw-r--r--tests/auto/qmldom/domdata/domitem/unaryExpressions/postIncrement.qml7
-rw-r--r--tests/auto/qmldom/domdata/domitem/unaryExpressions/tilde.qml7
-rw-r--r--tests/auto/qmldom/domdata/domitem/unaryExpressions/typeof.qml7
-rw-r--r--tests/auto/qmldom/domdata/domitem/unaryExpressions/unaryMinus.qml7
-rw-r--r--tests/auto/qmldom/domdata/domitem/unaryExpressions/unaryPlus.qml7
-rw-r--r--tests/auto/qmldom/domdata/domitem/unaryExpressions/void.qml7
-rw-r--r--tests/auto/qmldom/domdata/domitem/variableDeclarations.qml23
-rw-r--r--tests/auto/qmldom/domdata/domitem/visitTreeFilter.qml4
-rw-r--r--tests/auto/qmldom/domdata/reformatter/commentedFileReformatted.qml2
-rw-r--r--tests/auto/qmldom/domdata/reformatter/commentedFileReformatted2.qml2
-rw-r--r--tests/auto/qmldom/domdata/reformatter/file1.qml2
-rw-r--r--tests/auto/qmldom/domdata/reformatter/file1Reformatted.qml5
-rw-r--r--tests/auto/qmldom/domdata/reformatter/file1Reformatted2.qml4
-rw-r--r--tests/auto/qmldom/domdata/reformatter/file1Unindented.qml2
-rw-r--r--tests/auto/qmldom/domdata/reformatter/file2Reformatted.qml2
-rw-r--r--tests/auto/qmldom/domdata/reformatter/requiredReformatted2.qml4
-rw-r--r--tests/auto/qmldom/domdata/reformatter/spreadReformatted.qml2
-rw-r--r--tests/auto/qmldom/domitem/CMakeLists.txt7
-rw-r--r--tests/auto/qmldom/domitem/tst_qmldomitem.cpp2
-rw-r--r--tests/auto/qmldom/domitem/tst_qmldomitem.h3259
-rw-r--r--tests/auto/qmldom/errormessage/CMakeLists.txt6
-rw-r--r--tests/auto/qmldom/errormessage/tst_qmldomerrormessage.cpp2
-rw-r--r--tests/auto/qmldom/errormessage/tst_qmldomerrormessage.h2
-rw-r--r--tests/auto/qmldom/merging/CMakeLists.txt7
-rw-r--r--tests/auto/qmldom/merging/tst_dommerging.cpp2
-rw-r--r--tests/auto/qmldom/merging/tst_dommerging.h15
-rw-r--r--tests/auto/qmldom/path/CMakeLists.txt6
-rw-r--r--tests/auto/qmldom/path/tst_qmldompath.cpp2
-rw-r--r--tests/auto/qmldom/path/tst_qmldompath.h18
-rw-r--r--tests/auto/qmldom/reformatter/CMakeLists.txt7
-rw-r--r--tests/auto/qmldom/reformatter/tst_reformatter.cpp2
-rw-r--r--tests/auto/qmldom/reformatter/tst_reformatter.h417
-rw-r--r--tests/auto/qmldom/standalone/CMakeLists.txt39
-rw-r--r--tests/auto/qmldom/standalone/tst_standalone.cpp5
-rw-r--r--tests/auto/qmldom/standalone/tst_standalone.h634
-rw-r--r--tests/auto/qmldom/stringdumper/CMakeLists.txt6
-rw-r--r--tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.cpp2
-rw-r--r--tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.h2
-rw-r--r--tests/auto/qmlls/CMakeLists.txt10
-rw-r--r--tests/auto/qmlls/cli/CMakeLists.txt34
-rw-r--r--tests/auto/qmlls/cli/data/ImportPath1/SomeModule/A.qml5
-rw-r--r--tests/auto/qmlls/cli/data/ImportPath1/SomeModule/qmldir2
-rw-r--r--tests/auto/qmlls/cli/data/ImportPath2/AnotherModule/B.qml5
-rw-r--r--tests/auto/qmlls/cli/data/ImportPath2/AnotherModule/qmldir2
-rw-r--r--tests/auto/qmlls/cli/data/sourceFolder/ImportFromBothPaths.qml10
-rw-r--r--tests/auto/qmlls/cli/data/sourceFolder/ImportFromImportPath1.qml5
-rw-r--r--tests/auto/qmlls/cli/tst_qmlls_cli.cpp309
-rw-r--r--tests/auto/qmlls/cli/tst_qmlls_cli.h38
-rw-r--r--tests/auto/qmlls/completions/CMakeLists.txt27
-rw-r--r--tests/auto/qmlls/completions/tst_qmllscompletions.cpp500
-rw-r--r--tests/auto/qmlls/lifecycle/CMakeLists.txt10
-rw-r--r--tests/auto/qmlls/lifecycle/qiopipe.cpp2
-rw-r--r--tests/auto/qmlls/lifecycle/qiopipe.h2
-rw-r--r--tests/auto/qmlls/lifecycle/tst_lifecycle.cpp4
-rw-r--r--tests/auto/qmlls/modules/CMakeLists.txt45
-rw-r--r--tests/auto/qmlls/modules/data/buildDir/BuildDir/BuildDirType.qml (renamed from tests/auto/qmlls/completions/data/buildDir/BuildDir/BuildDirType.qml)0
-rw-r--r--tests/auto/qmlls/modules/data/buildDir/BuildDir/qmldir (renamed from tests/auto/qmlls/completions/data/buildDir/BuildDir/qmldir)1
-rw-r--r--tests/auto/qmlls/modules/data/completions/SomeBase.qml5
-rw-r--r--tests/auto/qmlls/modules/data/completions/Yyy.qml (renamed from tests/auto/qmlls/completions/data/completions/Yyy.qml)3
-rw-r--r--tests/auto/qmlls/modules/data/completions/Zzz.qml (renamed from tests/auto/qmlls/completions/data/completions/Zzz.qml)0
-rw-r--r--tests/auto/qmlls/modules/data/completions/bindingAfterDot.qml14
-rw-r--r--tests/auto/qmlls/modules/data/completions/defaultBindingAfterDot.qml14
-rw-r--r--tests/auto/qmlls/modules/data/completions/fromBuildDir.qml (renamed from tests/auto/qmlls/completions/data/completions/fromBuildDir.qml)1
-rw-r--r--tests/auto/qmlls/modules/data/findDefinition/jsDefinitions.qml17
-rw-r--r--tests/auto/qmlls/modules/data/findUsages/jsIdentifierUsages.qml13
-rw-r--r--tests/auto/qmlls/modules/data/formatting/blanklines.formatted.qml4
-rw-r--r--tests/auto/qmlls/modules/data/formatting/blanklines.qml15
-rw-r--r--tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted1.qml23
-rw-r--r--tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted2.qml20
-rw-r--r--tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted3.qml23
-rw-r--r--tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted4.qml20
-rw-r--r--tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted5.qml20
-rw-r--r--tests/auto/qmlls/modules/data/formatting/rangeFormatting.qml23
-rw-r--r--tests/auto/qmlls/modules/data/highlighting/basic.qml11
-rw-r--r--tests/auto/qmlls/modules/data/highlighting/bigFile.qml351
-rw-r--r--tests/auto/qmlls/modules/data/hover/test.qml8
-rw-r--r--tests/auto/qmlls/modules/data/linting/SimpleItem.qml6
-rw-r--r--tests/auto/qmlls/modules/data/quickfixes/INeedAQuickFix.qml19
-rw-r--r--tests/auto/qmlls/modules/data/renameUsages/RenameMe.qml5
-rw-r--r--tests/auto/qmlls/modules/data/renameUsages/RenameMe2.ui.qml5
-rw-r--r--tests/auto/qmlls/modules/data/renameUsages/main.qml6
-rw-r--r--tests/auto/qmlls/modules/data/sourceDir/A.qml5
-rw-r--r--tests/auto/qmlls/modules/data/sourceDir/Main.qml6
-rw-r--r--tests/auto/qmlls/modules/data/sourceDir/qmldir3
-rw-r--r--tests/auto/qmlls/modules/tst_qmlls_modules.cpp1765
-rw-r--r--tests/auto/qmlls/modules/tst_qmlls_modules.h85
-rw-r--r--tests/auto/qmlls/qmlls/CMakeLists.txt12
-rw-r--r--tests/auto/qmlls/qmlls/tst_qmlls.cpp13
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/CMakeLists.txt33
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/FileA.qml5
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/FileA2.qml5
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/FileB.qml5
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/MyCppModule/Main.qml5
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/MyCppModule/mycppmodule.qmltypes36
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/MyCppModule/qmldir5
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/MyCppModule/Main.qml13
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/MyCppModule/helloworld.cpp8
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/MyCppModule/helloworld.h29
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement.cpp10
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement.h21
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement.qml8
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement2.cpp10
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement2.hpp18
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/somecppclass.cpp9
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/somecppclass.h14
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/anotherqmlelement.cpp10
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/anotherqmlelement.h18
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/myqmlelement.cpp10
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/myqmlelement.h21
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/myqmlelement.txt0
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp185
-rw-r--r--tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.h37
-rw-r--r--tests/auto/qmlls/utils/CMakeLists.txt63
-rw-r--r--tests/auto/qmlls/utils/data/BaseType.qml28
-rw-r--r--tests/auto/qmlls/utils/data/JSDefinitions.qml76
-rw-r--r--tests/auto/qmlls/utils/data/JSUsages.qml196
-rw-r--r--tests/auto/qmlls/utils/data/JSUsagesFromAnotherFile.qml16
-rw-r--r--tests/auto/qmlls/utils/data/Type.qml30
-rw-r--r--tests/auto/qmlls/utils/data/Yyy.qml143
-rw-r--r--tests/auto/qmlls/utils/data/Zzz.qml12
-rw-r--r--tests/auto/qmlls/utils/data/completions/afterDots.qml20
-rw-r--r--tests/auto/qmlls/utils/data/completions/attachedAndGroupedProperty.qml12
-rw-r--r--tests/auto/qmlls/utils/data/completions/attachedPropertyMissingRHS.qml8
-rw-r--r--tests/auto/qmlls/utils/data/completions/boundComponents.qml21
-rw-r--r--tests/auto/qmlls/utils/data/completions/commaExpression.qml7
-rw-r--r--tests/auto/qmlls/utils/data/completions/conditionalExpression.qml7
-rw-r--r--tests/auto/qmlls/utils/data/completions/continueAndBreakStatement.qml31
-rw-r--r--tests/auto/qmlls/utils/data/completions/functionBody.qml13
-rw-r--r--tests/auto/qmlls/utils/data/completions/groupedPropertyMissingRHS.qml8
-rw-r--r--tests/auto/qmlls/utils/data/completions/labelledStatement.qml20
-rw-r--r--tests/auto/qmlls/utils/data/completions/missingRHS.parserfail.qml9
-rw-r--r--tests/auto/qmlls/utils/data/completions/missingRHS.qml19
-rw-r--r--tests/auto/qmlls/utils/data/completions/parenthesizedExpression.qml10
-rw-r--r--tests/auto/qmlls/utils/data/completions/quickcontrols_and_quicktemplates/qualifiedTypesCompletion.qml11
-rw-r--r--tests/auto/qmlls/utils/data/completions/returnStatement.qml10
-rw-r--r--tests/auto/qmlls/utils/data/completions/suggestContinueAndBreak.qml54
-rw-r--r--tests/auto/qmlls/utils/data/completions/switchStatements.qml37
-rw-r--r--tests/auto/qmlls/utils/data/completions/throwStatement.qml11
-rw-r--r--tests/auto/qmlls/utils/data/completions/tryStatements.qml7
-rw-r--r--tests/auto/qmlls/utils/data/completions/unaryExpression.qml17
-rw-r--r--tests/auto/qmlls/utils/data/completions/variableDeclaration.qml36
-rw-r--r--tests/auto/qmlls/utils/data/emptyFile.qml0
-rw-r--r--tests/auto/qmlls/utils/data/file1.qml55
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/attachedPropertyUsage/attachedPropertyUsage.qml14
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/binding/binding.qml11
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/bindings/bindings.qml39
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/connections/connections.qml37
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/enums/Enums.qml27
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/enums/EnumsFromAnotherFile.qml5
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/groupPropertyUsage/fontFamilyUsage.qml6
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/groupPropertyUsage/groupPropertyUsage.qml35
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/idUsages/idUsages.qml19
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/inlineComponents/InlineComponentProvider.qml23
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/inlineComponents/inlineComponents.qml26
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/inlineComponents/inlineComponents2.qml9
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/jsIdentifier/jsIdentifier.qml16
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/parametersAndDeconstruction/parametersAndDeconstruction.qml16
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/property/PropertyFromAnotherFile.qml5
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/property/property.qml48
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/propertyChanges/propertyChanges.qml35
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile.qml6
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile2.qml6
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile3.qml6
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile4.qml6
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/propertyInNested/propertyInNested.qml56
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/recursive/RecursiveInOtherFile.qml10
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/recursive/recursive.qml28
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/signalsAndHandlers/signalAndHandlers2.qml43
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/signalsAndHandlers/signalsAndHandlers.qml40
-rw-r--r--tests/auto/qmlls/utils/data/findUsages/signalsAndHandlers/widthChangedInAnotherFile.qml6
-rw-r--r--tests/auto/qmlls/utils/data/highlights/Identifiers.qml37
-rw-r--r--tests/auto/qmlls/utils/data/highlights/bindings.qml12
-rw-r--r--tests/auto/qmlls/utils/data/highlights/comments.qml19
-rw-r--r--tests/auto/qmlls/utils/data/highlights/enums.qml11
-rw-r--r--tests/auto/qmlls/utils/data/highlights/imports.qml9
-rw-r--r--tests/auto/qmlls/utils/data/highlights/literals.qml14
-rw-r--r--tests/auto/qmlls/utils/data/highlights/methodAndSignal.qml11
-rw-r--r--tests/auto/qmlls/utils/data/highlights/objectAndComponent.qml11
-rw-r--r--tests/auto/qmlls/utils/data/highlights/pragmas.qml10
-rw-r--r--tests/auto/qmlls/utils/data/highlights/properties.qml13
-rw-r--r--tests/auto/qmlls/utils/data/highlights/scriptExpressions.qml116
-rw-r--r--tests/auto/qmlls/utils/data/pragmas.qml8
-rw-r--r--tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtqml-qtobject-qt-5.html134
-rw-r--r--tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtqml-qtobject.html129
-rw-r--r--tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtquick-item.html1486
-rw-r--r--tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtquick-mousearea.html676
-rw-r--r--tests/auto/qmlls/utils/data/qualifiedModule.qml7
-rw-r--r--tests/auto/qmlls/utils/data/renaming/RenameMe.qml5
-rw-r--r--tests/auto/qmlls/utils/data/renaming/RenameMe2.ui.qml5
-rw-r--r--tests/auto/qmlls/utils/data/renaming/RenamedByQmldir.qml4
-rw-r--r--tests/auto/qmlls/utils/data/renaming/UnrelatedFile.qml0
-rw-r--r--tests/auto/qmlls/utils/data/renaming/main.qml7
-rw-r--r--tests/auto/qmlls/utils/data/renaming/qmldir6
-rw-r--r--tests/auto/qmlls/utils/data/resolveExpressionType/BaseType.qml12
-rw-r--r--tests/auto/qmlls/utils/data/resolveExpressionType/BindingsOnDeferred.qml19
-rw-r--r--tests/auto/qmlls/utils/data/resolveExpressionType/Derived1.qml6
-rw-r--r--tests/auto/qmlls/utils/data/resolveExpressionType/Derived2.qml6
-rw-r--r--tests/auto/qmlls/utils/data/resolveExpressionType/DerivedType.qml32
-rw-r--r--tests/auto/qmlls/utils/tst_qmlls_documentationHints.cpp134
-rw-r--r--tests/auto/qmlls/utils/tst_qmlls_documentationHints.h24
-rw-r--r--tests/auto/qmlls/utils/tst_qmlls_highlighting.cpp650
-rw-r--r--tests/auto/qmlls/utils/tst_qmlls_highlighting.h37
-rw-r--r--tests/auto/qmlls/utils/tst_qmlls_utils.cpp4156
-rw-r--r--tests/auto/qmlls/utils/tst_qmlls_utils.h95
-rw-r--r--tests/auto/qmlnetwork/CMakeLists.txt8
-rw-r--r--tests/auto/qmlnetwork/qqmlnetworkinformation/CMakeLists.txt39
-rw-r--r--tests/auto/qmlnetwork/qqmlnetworkinformation/data/tst_networkinformation.qml14
-rw-r--r--tests/auto/qmlnetwork/qqmlnetworkinformation/tst_qqmlnetworkinformation.cpp51
-rw-r--r--tests/auto/qmlnetwork/qqmlsslconfiguration/CMakeLists.txt43
-rw-r--r--tests/auto/qmlnetwork/qqmlsslconfiguration/data/cert.pem34
-rw-r--r--tests/auto/qmlnetwork/qqmlsslconfiguration/data/key.pem52
-rw-r--r--tests/auto/qmlnetwork/qqmlsslconfiguration/qml/tst_sslconfiguration.qml158
-rw-r--r--tests/auto/qmlnetwork/qqmlsslconfiguration/tst_sslconfiguration_qml.cpp6
-rw-r--r--tests/auto/qmlnetwork/qqmlsslkey/CMakeLists.txt29
-rw-r--r--tests/auto/qmlnetwork/qqmlsslkey/qml/tst_sslkey.qml60
-rw-r--r--tests/auto/qmlnetwork/qqmlsslkey/tst_sslkey_qml.cpp6
-rw-r--r--tests/auto/qmltest-blacklist/animators/Box.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_behavior.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_mixed.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_mixedparallel.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_mixedsequential.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_multiwindow.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_nested.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_on.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_opacity.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_parallel.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_restart.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_rotation.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_scale.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_sequential.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_stopped.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_targetdestroyed.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_transformorigin.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_transition.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_x.qml2
-rw-r--r--tests/auto/qmltest-blacklist/animators/tst_y.qml2
-rw-r--r--tests/auto/qmltest-blacklist/item/tst_layerInPositioner.qml2
-rw-r--r--tests/auto/qmltest-blacklist/shortcut/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest-blacklist/shortcut/tst_shortcut.qml2
-rw-r--r--tests/auto/qmltest/animatedimage/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/animatedimage/tst_animatedimage.qml2
-rw-r--r--tests/auto/qmltest/animations/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/animations/tst_abstractanimationjobcrash.qml2
-rw-r--r--tests/auto/qmltest/borderimage/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/borderimage/InvalidSciFile.qml2
-rw-r--r--tests/auto/qmltest/borderimage/tst_borderimage.qml2
-rw-r--r--tests/auto/qmltest/buttonclick/Button.qml2
-rw-r--r--tests/auto/qmltest/buttonclick/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/buttonclick/tst_buttonclick.qml2
-rw-r--r--tests/auto/qmltest/createbenchmark/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/createbenchmark/item.qml2
-rw-r--r--tests/auto/qmltest/createbenchmark/tst_createbenchmark.qml2
-rw-r--r--tests/auto/qmltest/events/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/events/tst_drag.qml2
-rw-r--r--tests/auto/qmltest/events/tst_events.qml2
-rw-r--r--tests/auto/qmltest/events/tst_touch.qml2
-rw-r--r--tests/auto/qmltest/events/tst_wheel.qml2
-rw-r--r--tests/auto/qmltest/fontloader/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/fontloader/tst_fontloader.qml2
-rw-r--r--tests/auto/qmltest/fuzzycompare/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/fuzzycompare/tst_FuzzyCompare.qml2
-rw-r--r--tests/auto/qmltest/gradient/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/gradient/tst_gradient.qml2
-rw-r--r--tests/auto/qmltest/image/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/image/tst_image.qml2
-rw-r--r--tests/auto/qmltest/itemgrabber/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml2
-rw-r--r--tests/auto/qmltest/layout/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/layout/Container.qml2
-rw-r--r--tests/auto/qmltest/layout/ContainerUser.qml2
-rw-r--r--tests/auto/qmltest/layout/tst_layout.qml2
-rw-r--r--tests/auto/qmltest/listmodel/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/listmodel/tst_listmodel.qml2
-rw-r--r--tests/auto/qmltest/listview/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/listview/data/MultiDelegate.qml2
-rw-r--r--tests/auto/qmltest/listview/data/MultiDelegate2.qml2
-rw-r--r--tests/auto/qmltest/listview/data/MultiDelegate3.qml2
-rw-r--r--tests/auto/qmltest/listview/data/asynclistviewloader.qml2
-rw-r--r--tests/auto/qmltest/listview/data/asyncloadercurrentindex.qml2
-rw-r--r--tests/auto/qmltest/listview/tst_listview.qml2
-rw-r--r--tests/auto/qmltest/objectmodel/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/objectmodel/tst_objectmodel.qml2
-rw-r--r--tests/auto/qmltest/pathview/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/positioners/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/positioners/tst_positioners.qml2
-rw-r--r--tests/auto/qmltest/qqmlbinding/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/qqmlbinding/tst_binding.qml2
-rw-r--r--tests/auto/qmltest/qqmlbinding/tst_binding2.qml2
-rw-r--r--tests/auto/qmltest/qtbug46798/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/qtbug46798/tst_qtbug46798.qml2
-rw-r--r--tests/auto/qmltest/rectangle/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/rectangle/tst_rectangle.qml2
-rw-r--r--tests/auto/qmltest/selftests/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/selftests/tst_compare.qml2
-rw-r--r--tests/auto/qmltest/selftests/tst_compare_quickobjects.qml2
-rw-r--r--tests/auto/qmltest/selftests/tst_createTemporaryObject.qml2
-rw-r--r--tests/auto/qmltest/selftests/tst_datadriven.qml2
-rw-r--r--tests/auto/qmltest/selftests/tst_destroy.qml2
-rw-r--r--tests/auto/qmltest/selftests/tst_findChild.qml2
-rw-r--r--tests/auto/qmltest/selftests/tst_grabImage.qml2
-rw-r--r--tests/auto/qmltest/selftests/tst_multiTestCase.qml2
-rw-r--r--tests/auto/qmltest/selftests/tst_selftests.qml2
-rw-r--r--tests/auto/qmltest/selftests/tst_signalspy.qml53
-rw-r--r--tests/auto/qmltest/selftests/tst_stringify.qml2
-rw-r--r--tests/auto/qmltest/selftests/tst_tryVerify.qml2
-rw-r--r--tests/auto/qmltest/shadersource/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml2
-rw-r--r--tests/auto/qmltest/shadersource/tst_DynamicallyCreatedSource.qml2
-rw-r--r--tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml2
-rw-r--r--tests/auto/qmltest/shadersource/tst_SourceItem.qml2
-rw-r--r--tests/auto/qmltest/shadersource/tst_SourcedFromOtherWindow.qml2
-rw-r--r--tests/auto/qmltest/stability/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/stability/tst_unloadrepeater.qml2
-rw-r--r--tests/auto/qmltest/text/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/text/tst_text.qml2
-rw-r--r--tests/auto/qmltest/textedit/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/textedit/tst_textedit.qml2
-rw-r--r--tests/auto/qmltest/textedit/tst_textedit_editingfinished.qml2
-rw-r--r--tests/auto/qmltest/textinput/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/textinput/tst_textinput.qml5
-rw-r--r--tests/auto/qmltest/url/tst_url.qml2
-rw-r--r--tests/auto/qmltest/window/CMakeLists.txt6
-rw-r--r--tests/auto/qmltest/window/tst_clickwindow.qml2
-rw-r--r--tests/auto/quick/CMakeLists.txt11
-rw-r--r--tests/auto/quick/doc/CMakeLists.txt7
-rw-r--r--tests/auto/quick/doc/how-tos/CMakeLists.txt6
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-cpp-button/CMakeLists.txt31
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-cpp-button/Main.qml19
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-cpp-button/backend.cpp13
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-cpp-button/backend.h17
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-cpp-button/tst_how-to-cpp-button.cpp53
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/CMakeLists.txt25
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/backend.cpp36
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/backend.h29
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/script.mjs13
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/tst_how-to-cpp-enum-js.cpp47
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-qml/BLACKLIST5
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-qml/CMakeLists.txt33
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-qml/active-focus-debugging/ActiveFocusDebuggingMain.qml25
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimeComponentLabel.qml29
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePicker.qml325
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePickerDialog.qml88
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePickerLabel.qml126
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePickerMain.qml59
-rw-r--r--tests/auto/quick/doc/how-tos/how-to-qml/tst_how-to-qml.cpp369
-rw-r--r--tests/auto/quick/drawingmodes/CMakeLists.txt6
-rw-r--r--tests/auto/quick/drawingmodes/tst_drawingmodes.cpp4
-rw-r--r--tests/auto/quick/examples/CMakeLists.txt8
-rw-r--r--tests/auto/quick/examples/tst_examples.cpp36
-rw-r--r--tests/auto/quick/geometry/CMakeLists.txt6
-rw-r--r--tests/auto/quick/geometry/tst_geometry.cpp2
-rw-r--r--tests/auto/quick/nodes/CMakeLists.txt6
-rw-r--r--tests/auto/quick/nodes/tst_nodestest.cpp11
-rw-r--r--tests/auto/quick/nokeywords/CMakeLists.txt6
-rw-r--r--tests/auto/quick/nokeywords/tst_nokeywords.cpp2
-rw-r--r--tests/auto/quick/platform/CMakeLists.txt6
-rw-r--r--tests/auto/quick/platform/android/CMakeLists.txt4
-rw-r--r--tests/auto/quick/platform/android/qtandroiditemmodel/CMakeLists.txt25
-rw-r--r--tests/auto/quick/platform/android/qtandroiditemmodel/testdata/src/org/qtproject/qt/android/tests/TestModel.java120
-rw-r--r--tests/auto/quick/platform/android/qtandroiditemmodel/tst_qtandroiditemmodel.cpp182
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST6
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/CMakeLists.txt6
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnFlickable.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickable.qml49
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickableWithParentTapHandler.qml24
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnFlickable.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp247
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/CMakeLists.txt6
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/data/dragTakeOverFromSibling.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp4
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/BLACKLIST5
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/CMakeLists.txt6
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/dragParentOfMPTA.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml6
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/unloadHandlerOnPress.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp6
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/CMakeLists.txt6
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/snapMode.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp4
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST3
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/CMakeLists.txt6
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/data/changingCursor.qml37
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverDeviceCursors.qml80
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverHandler.qml17
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp85
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/CMakeLists.txt6
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/data/nullTarget.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchAndDrag.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml11
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/data/threeFingers.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/data/transformedPinchHandler.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp165
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/CMakeLists.txt6
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/data/clip.qml36
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/data/grabberSceneChange.qml78
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp112
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointhandler/CMakeLists.txt6
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointhandler/data/multiPointTracker.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointhandler/data/pointTracker.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp4
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST8
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt6
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml18
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml14
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/dragReleaseMenu.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/nested.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/nestedAndSibling.qml39
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp380
-rw-r--r--tests/auto/quick/pointerhandlers/qquickwheelhandler/CMakeLists.txt6
-rw-r--r--tests/auto/quick/pointerhandlers/qquickwheelhandler/data/nested.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickwheelhandler/data/rectWheel.qml18
-rw-r--r--tests/auto/quick/pointerhandlers/qquickwheelhandler/tst_qquickwheelhandler.cpp2
-rw-r--r--tests/auto/quick/propertyrequirements/CMakeLists.txt6
-rw-r--r--tests/auto/quick/propertyrequirements/tst_propertyrequirements.cpp13
-rw-r--r--tests/auto/quick/qquickaccessible/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickaccessible/data/hittest.qml2
-rw-r--r--tests/auto/quick/qquickaccessible/data/ignored.qml2
-rw-r--r--tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp80
-rw-r--r--tests/auto/quick/qquickanchors/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickanchors/data/centerin.qml7
-rw-r--r--tests/auto/quick/qquickanchors/tst_qquickanchors.cpp25
-rw-r--r--tests/auto/quick/qquickanimatedimage/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickanimatedimage/data/currentframe.qml1
-rw-r--r--tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp33
-rw-r--r--tests/auto/quick/qquickanimatedsprite/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickanimatedsprite/data/basic.qml2
-rw-r--r--tests/auto/quick/qquickanimatedsprite/data/frameChange.qml2
-rw-r--r--tests/auto/quick/qquickanimatedsprite/data/infiniteLoops.qml2
-rw-r--r--tests/auto/quick/qquickanimatedsprite/data/largeAnimation.qml2
-rw-r--r--tests/auto/quick/qquickanimatedsprite/data/runningChange.qml2
-rw-r--r--tests/auto/quick/qquickanimatedsprite/data/sourceSwitch.qml2
-rw-r--r--tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp2
-rw-r--r--tests/auto/quick/qquickanimationcontroller/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickanimationcontroller/tst_qquickanimationcontroller.cpp2
-rw-r--r--tests/auto/quick/qquickanimations/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickanimations/data/animationJobSelfDestructionBug.qml2
-rw-r--r--tests/auto/quick/qquickanimations/data/animatorInvalidTargetCrash.qml2
-rw-r--r--tests/auto/quick/qquickanimations/data/changePropertiesDuringAnimation.qml2
-rw-r--r--tests/auto/quick/qquickanimations/data/fastFlickingBug.qml2
-rw-r--r--tests/auto/quick/qquickanimations/data/finished.qml2
-rw-r--r--tests/auto/quick/qquickanimations/data/frameAnimation.qml2
-rw-r--r--tests/auto/quick/qquickanimations/data/infiniteAnimationWithoutFrom.qml2
-rw-r--r--tests/auto/quick/qquickanimations/data/restartAnimationGroupWhenDirty.qml92
-rw-r--r--tests/auto/quick/qquickanimations/data/restartNestedAnimationGroupWhenDirty.qml96
-rw-r--r--tests/auto/quick/qquickanimations/data/scriptActionCrash.qml2
-rw-r--r--tests/auto/quick/qquickanimations/data/targetsDeletedWithoutRemoval.qml29
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp166
-rw-r--r--tests/auto/quick/qquickanimators/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickanimators/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickanimators/data/animatorImplicitFrom.qml2
-rw-r--r--tests/auto/quick/qquickanimators/data/positionerWithAnimator.qml2
-rw-r--r--tests/auto/quick/qquickanimators/data/windowWithAnimator.qml2
-rw-r--r--tests/auto/quick/qquickanimators/tst_qquickanimators.cpp2
-rw-r--r--tests/auto/quick/qquickapplication/BLACKLIST5
-rw-r--r--tests/auto/quick/qquickapplication/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickapplication/tst_qquickapplication.cpp14
-rw-r--r--tests/auto/quick/qquickbehaviors/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickbehaviors/bindable.h2
-rw-r--r--tests/auto/quick/qquickbehaviors/data/duplicated.qml31
-rw-r--r--tests/auto/quick/qquickbehaviors/data/qtbug21549-2.qml2
-rw-r--r--tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp17
-rw-r--r--tests/auto/quick/qquickborderimage/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp18
-rw-r--r--tests/auto/quick/qquickboundaryrule/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp2
-rw-r--r--tests/auto/quick/qquickcanvasitem/BLACKLIST1
-rw-r--r--tests/auto/quick/qquickcanvasitem/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_arc.qml22
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml9
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_composite.qml7
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_fillStyle.qml8
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_fillrect.qml1
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml6
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_image.qml25
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml1
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_invalidContext.qml8
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_line.qml9
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_path.qml16
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_pattern.qml6
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_pixel.qml5
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_shadow.qml11
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_state.qml16
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml5
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_svgpath.qml1
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_text.qml6
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_transform.qml6
-rw-r--r--tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp2
-rw-r--r--tests/auto/quick/qquickcolorgroup/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickcolorgroup/tst_qquickcolorgroup.cpp2
-rw-r--r--tests/auto/quick/qquickdeliveryagent/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickdeliveryagent/data/clearItemsOnHoverLeave.qml32
-rw-r--r--tests/auto/quick/qquickdeliveryagent/data/compoundControl.qml28
-rw-r--r--tests/auto/quick/qquickdeliveryagent/data/flickableTextEdit.qml2
-rw-r--r--tests/auto/quick/qquickdeliveryagent/data/listViewDelegate.qml2
-rw-r--r--tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp163
-rw-r--r--tests/auto/quick/qquickdesignersupport/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickdesignersupport/data/RegTestComponent.qml20
-rw-r--r--tests/auto/quick/qquickdesignersupport/data/regTestProperties.qml13
-rw-r--r--tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp42
-rw-r--r--tests/auto/quick/qquickdrag/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickdrag/tst_qquickdrag.cpp2
-rw-r--r--tests/auto/quick/qquickdragattached/CMakeLists.txt27
-rw-r--r--tests/auto/quick/qquickdragattached/data/qt_logo.svg26
-rw-r--r--tests/auto/quick/qquickdragattached/tst_qquickdragattached.cpp66
-rw-r--r--tests/auto/quick/qquickdroparea/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickdroparea/data/nested1.qml2
-rw-r--r--tests/auto/quick/qquickdroparea/data/nested2.qml2
-rw-r--r--tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp2
-rw-r--r--tests/auto/quick/qquickdynamicpropertyanimation/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickdynamicpropertyanimation/tst_qquickdynamicpropertyanimation.cpp2
-rw-r--r--tests/auto/quick/qquickflickable/BLACKLIST5
-rw-r--r--tests/auto/quick/qquickflickable/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickflickable/data/endpoints.qml14
-rw-r--r--tests/auto/quick/qquickflickable/data/flickableWithTapHandler.qml24
-rw-r--r--tests/auto/quick/qquickflickable/data/nested.qml2
-rw-r--r--tests/auto/quick/qquickflickable/data/overshoot.qml2
-rw-r--r--tests/auto/quick/qquickflickable/data/overshoot_reentrant.qml2
-rw-r--r--tests/auto/quick/qquickflickable/data/parallel.qml2
-rw-r--r--tests/auto/quick/qquickflickable/data/pressDelay.qml12
-rw-r--r--tests/auto/quick/qquickflickable/data/ratios.qml2
-rw-r--r--tests/auto/quick/qquickflickable/data/visibleAreaBinding.qml2
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp393
-rw-r--r--tests/auto/quick/qquickflipable/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickflipable/data/flip-y-axis-flipable.qml32
-rw-r--r--tests/auto/quick/qquickflipable/tst_qquickflipable.cpp30
-rw-r--r--tests/auto/quick/qquickfocusscope/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp2
-rw-r--r--tests/auto/quick/qquickfontloader/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp2
-rw-r--r--tests/auto/quick/qquickfontloader_static/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickfontloader_static/tst_qquickfontloader_static.cpp2
-rw-r--r--tests/auto/quick/qquickfontmetrics/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickfontmetrics/tst_quickfontmetrics.cpp6
-rw-r--r--tests/auto/quick/qquickframebufferobject/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickframebufferobject/data/testStuff.qml2
-rw-r--r--tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp2
-rw-r--r--tests/auto/quick/qquickgraphicsinfo/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp2
-rw-r--r--tests/auto/quick/qquickgridview/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickgridview/data/attachedProperties.qml2
-rw-r--r--tests/auto/quick/qquickgridview/data/displayMargin.qml2
-rw-r--r--tests/auto/quick/qquickgridview/data/margins2.qml2
-rw-r--r--tests/auto/quick/qquickgridview/data/negativeDisplayMargin.qml2
-rw-r--r--tests/auto/quick/qquickgridview/data/qtbug49218.qml2
-rw-r--r--tests/auto/quick/qquickgridview/data/qtbug91461.qml2
-rw-r--r--tests/auto/quick/qquickgridview/data/removeAccessibleChildrenEvenIfReusingItems.qml48
-rw-r--r--tests/auto/quick/qquickgridview/tst_qquickgridview.cpp166
-rw-r--r--tests/auto/quick/qquickimage/BLACKLIST3
-rw-r--r--tests/auto/quick/qquickimage/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickimage/data/hugeImages.qml2
-rw-r--r--tests/auto/quick/qquickimage/data/multiframeAsyncRetain.qml7
-rw-r--r--tests/auto/quick/qquickimage/data/qtbug_32513.qml2
-rw-r--r--tests/auto/quick/qquickimage/data/statusChanged.qml25
-rw-r--r--tests/auto/quick/qquickimage/tst_qquickimage.cpp108
-rw-r--r--tests/auto/quick/qquickimageprovider/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp19
-rw-r--r--tests/auto/quick/qquickitem/CMakeLists.txt8
-rw-r--r--tests/auto/quick/qquickitem/data/childAtRectangle.qml2
-rw-r--r--tests/auto/quick/qquickitem/data/mainWindowQtBug60123.qml2
-rw-r--r--tests/auto/quick/qquickitem/data/shortcutOverride.qml2
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp237
-rw-r--r--tests/auto/quick/qquickitem2/CMakeLists.txt11
-rw-r--r--tests/auto/quick/qquickitem2/data/embedded.qml30
-rw-r--r--tests/auto/quick/qquickitem2/data/embedded_FocusScope.qml37
-rw-r--r--tests/auto/quick/qquickitem2/data/focusInScopeChanges.qml31
-rw-r--r--tests/auto/quick/qquickitem2/data/focusReason.qml85
-rw-r--r--tests/auto/quick/qquickitem2/data/grabToImage.qml2
-rw-r--r--tests/auto/quick/qquickitem2/data/keysforward.qml2
-rw-r--r--tests/auto/quick/qquickitem2/data/mapCoordinates.qml2
-rw-r--r--tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml2
-rw-r--r--tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml51
-rw-r--r--tests/auto/quick/qquickitem2/data/standardkeys.qml2
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp576
-rw-r--r--tests/auto/quick/qquickitemlayer/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp2
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/rhiitem.cpp352
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/rhiitem.h75
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/rhiitem_p.h60
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/testrhiitem.h61
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/tst_qquickitemrhiintegration.cpp77
-rw-r--r--tests/auto/quick/qquicklayouts/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquicklayouts/data/LayoutHelperLibrary.js42
-rw-r--r--tests/auto/quick/qquicklayouts/data/rowlayout/Container.qml2
-rw-r--r--tests/auto/quick/qquicklayouts/data/rowlayout/Container2.qml2
-rw-r--r--tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser.qml2
-rw-r--r--tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser2.qml2
-rw-r--r--tests/auto/quick/qquicklayouts/data/rowlayout/LayerEnabled.qml2
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml126
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_layoutproxy.qml687
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml477
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml142
-rw-r--r--tests/auto/quick/qquicklayouts/tst_qquicklayouts.cpp11
-rw-r--r--tests/auto/quick/qquicklistview/BLACKLIST4
-rw-r--r--tests/auto/quick/qquicklistview/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquicklistview/data/addoncompleted.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/attachedProperties.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/displayMargin.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/flickBothDirections.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/moveObjectModelItemToAnotherObjectModel.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/negativeDisplayMargin.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/objectModelCulling.qml1
-rw-r--r--tests/auto/quick/qquicklistview/data/outsideViewportChangeNotAffectingView.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/proxytest.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/qtbug34576.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/qtbug61537_modelChangesAsync.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/repositionListViewOnPopulateTransition.qml51
-rw-r--r--tests/auto/quick/qquicklistview/data/resizeAfterComponentComplete.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/reusedelegateitems.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/roundingErrors.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/setpositiononlayout.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/sizeTransitions.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/snapOneItemResize.qml1
-rw-r--r--tests/auto/quick/qquicklistview/data/stickyPositioning-both.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/stickyPositioning-footer.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/stickyPositioning-header.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/usechooserwithoutdefault.qml2
-rw-r--r--tests/auto/quick/qquicklistview/incrementalmodel.cpp2
-rw-r--r--tests/auto/quick/qquicklistview/incrementalmodel.h2
-rw-r--r--tests/auto/quick/qquicklistview/proxytestinnermodel.cpp2
-rw-r--r--tests/auto/quick/qquicklistview/proxytestinnermodel.h2
-rw-r--r--tests/auto/quick/qquicklistview/randomsortmodel.cpp2
-rw-r--r--tests/auto/quick/qquicklistview/randomsortmodel.h2
-rw-r--r--tests/auto/quick/qquicklistview/reusemodel.h2
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp172
-rw-r--r--tests/auto/quick/qquicklistview2/CMakeLists.txt9
-rw-r--r--tests/auto/quick/qquicklistview2/data/areaZeroView.qml22
-rw-r--r--tests/auto/quick/qquicklistview2/data/bindOnHeaderAndFooterXPosition.qml29
-rw-r--r--tests/auto/quick/qquicklistview2/data/bindOnHeaderAndFooterYPosition.qml29
-rw-r--r--tests/auto/quick/qquicklistview2/data/boundDelegateComponent.qml6
-rw-r--r--tests/auto/quick/qquicklistview2/data/changingOrientationWithListModel.qml47
-rw-r--r--tests/auto/quick/qquicklistview2/data/changingOrientationWithObjectModel.qml54
-rw-r--r--tests/auto/quick/qquicklistview2/data/delegateChooserEnumRole.qml2
-rw-r--r--tests/auto/quick/qquicklistview2/data/delegateContextHandling.qml75
-rw-r--r--tests/auto/quick/qquicklistview2/data/delegateModelRefresh.qml2
-rw-r--r--tests/auto/quick/qquicklistview2/data/delegateWithMouseArea.qml2
-rw-r--r--tests/auto/quick/qquicklistview2/data/fetchMore.qml21
-rw-r--r--tests/auto/quick/qquicklistview2/data/footerUpdate.qml2
-rw-r--r--tests/auto/quick/qquicklistview2/data/innerRequired.qml2
-rw-r--r--tests/auto/quick/qquicklistview2/data/maxXExtent.qml2
-rw-r--r--tests/auto/quick/qquicklistview2/data/maxYExtent.qml2
-rw-r--r--tests/auto/quick/qquicklistview2/data/metaSequenceAsModel.qml2
-rw-r--r--tests/auto/quick/qquicklistview2/data/qtbug86744.qml2
-rw-r--r--tests/auto/quick/qquicklistview2/data/qtbug98315.qml2
-rw-r--r--tests/auto/quick/qquicklistview2/data/qtbug_92809.qml2
-rw-r--r--tests/auto/quick/qquicklistview2/data/sectionBoundComponent.qml14
-rw-r--r--tests/auto/quick/qquicklistview2/data/sectionGeometryChange.qml58
-rw-r--r--tests/auto/quick/qquicklistview2/data/sectionsNoOverlap.qml2
-rw-r--r--tests/auto/quick/qquicklistview2/data/urlListModel.qml2
-rw-r--r--tests/auto/quick/qquicklistview2/data/viewportAvoidUndesiredMovementOnSetCurrentIndex.qml47
-rw-r--r--tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp378
-rw-r--r--tests/auto/quick/qquicklistview2/typerolemodel.cpp2
-rw-r--r--tests/auto/quick/qquicklistview2/typerolemodel.h2
-rw-r--r--tests/auto/quick/qquickloader/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickloader/data/Rect120x60.qml8
-rw-r--r--tests/auto/quick/qquickloader/data/bindings.qml2
-rw-r--r--tests/auto/quick/qquickloader/data/itemLoaderItemWindow.qml2
-rw-r--r--tests/auto/quick/qquickloader/data/itemLoaderWindow.qml2
-rw-r--r--tests/auto/quick/qquickloader/data/noEngine.qml2
-rw-r--r--tests/auto/quick/qquickloader/data/parentErrors.qml2
-rw-r--r--tests/auto/quick/qquickloader/data/rootContext.qml2
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp84
-rw-r--r--tests/auto/quick/qquickmousearea/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickmousearea/data/clickThrough2.qml6
-rw-r--r--tests/auto/quick/qquickmousearea/data/containsMouseAndHoverDisabled.qml15
-rw-r--r--tests/auto/quick/qquickmousearea/data/cursorUpdating.qml71
-rw-r--r--tests/auto/quick/qquickmousearea/data/hoverAfterPress.qml2
-rw-r--r--tests/auto/quick/qquickmousearea/data/ignoreBySource.qml2
-rw-r--r--tests/auto/quick/qquickmousearea/data/mask.qml2
-rw-r--r--tests/auto/quick/qquickmousearea/data/moveAndReleaseWithoutPress.qml2
-rw-r--r--tests/auto/quick/qquickmousearea/data/qtbug34368.qml4
-rw-r--r--tests/auto/quick/qquickmousearea/data/qtbug49100.qml2
-rw-r--r--tests/auto/quick/qquickmousearea/data/rejectEvent.qml2
-rw-r--r--tests/auto/quick/qquickmousearea/data/updateMousePosOnResize.qml6
-rw-r--r--tests/auto/quick/qquickmousearea/data/wheel.qml2
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp125
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/BLACKLIST4
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/cancel.qml12
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/inFlickable.qml6
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml8
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/nested.qml2
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/nestedTouchPosCheck.qml52
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/nonOverlapping.qml4
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/signalTest.qml14
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/touchOverMouseArea.qml21
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/transformedMultiPointTouchArea.qml4
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp157
-rw-r--r--tests/auto/quick/qquickpainteditem/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp22
-rw-r--r--tests/auto/quick/qquickpalette/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickpalette/data/palette-item-custom.qml2
-rw-r--r--tests/auto/quick/qquickpalette/data/palette-item-default.qml2
-rw-r--r--tests/auto/quick/qquickpalette/data/palette-window-custom.qml2
-rw-r--r--tests/auto/quick/qquickpalette/data/palette-window-default.qml2
-rw-r--r--tests/auto/quick/qquickpalette/tst_qquickpalette.cpp2
-rw-r--r--tests/auto/quick/qquickpath/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickpath/tst_qquickpath.cpp105
-rw-r--r--tests/auto/quick/qquickpathview/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickpathview/data/flickableDelegate.qml2
-rw-r--r--tests/auto/quick/qquickpathview/data/mousePressAfterFlick.qml61
-rw-r--r--tests/auto/quick/qquickpathview/data/nestedInFlickable.qml2
-rw-r--r--tests/auto/quick/qquickpathview/data/nestedmousearea2.qml2
-rw-r--r--tests/auto/quick/qquickpathview/data/objectModelMove.qml2
-rw-r--r--tests/auto/quick/qquickpathview/data/overcached.qml27
-rw-r--r--tests/auto/quick/qquickpathview/data/qtbug37815.qml2
-rw-r--r--tests/auto/quick/qquickpathview/data/qtbug46487.qml28
-rw-r--r--tests/auto/quick/qquickpathview/data/qtbug53464.qml2
-rw-r--r--tests/auto/quick/qquickpathview/data/qtbug90479.qml25
-rw-r--r--tests/auto/quick/qquickpathview/tst_qquickpathview.cpp161
-rw-r--r--tests/auto/quick/qquickpincharea/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp32
-rw-r--r--tests/auto/quick/qquickpixmapcache/BLACKLIST3
-rw-r--r--tests/auto/quick/qquickpixmapcache/CMakeLists.txt18
-rw-r--r--tests/auto/quick/qquickpixmapcache/data/slowLoading.qml13
-rw-r--r--tests/auto/quick/qquickpixmapcache/data/tableViewWithDeviceLoadingImages.qml45
-rw-r--r--tests/auto/quick/qquickpixmapcache/deviceloadingimage.cpp42
-rw-r--r--tests/auto/quick/qquickpixmapcache/deviceloadingimage.h25
-rw-r--r--tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp126
-rw-r--r--tests/auto/quick/qquickpositioners/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp19
-rw-r--r--tests/auto/quick/qquickrectangle/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickrectangle/data/multi-radius.qml27
-rw-r--r--tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp79
-rw-r--r--tests/auto/quick/qquickrendercontrol/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickrendercontrol/data/rect.qml2
-rw-r--r--tests/auto/quick/qquickrendercontrol/data/rect_depth.qml28
-rw-r--r--tests/auto/quick/qquickrendercontrol/tst_qquickrendercontrol.cpp198
-rw-r--r--tests/auto/quick/qquickrepeater/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp118
-rw-r--r--tests/auto/quick/qquickrhiitem/BLACKLIST (renamed from tests/auto/quick/qquickitemrhiintegration/BLACKLIST)0
-rw-r--r--tests/auto/quick/qquickrhiitem/CMakeLists.txt (renamed from tests/auto/quick/qquickitemrhiintegration/CMakeLists.txt)26
-rw-r--r--tests/auto/quick/qquickrhiitem/data/test.qml (renamed from tests/auto/quick/qquickitemrhiintegration/data/test.qml)15
-rw-r--r--tests/auto/quick/qquickrhiitem/testrhiitem.cpp (renamed from tests/auto/quick/qquickitemrhiintegration/testrhiitem.cpp)57
-rw-r--r--tests/auto/quick/qquickrhiitem/testrhiitem.h61
-rw-r--r--tests/auto/quick/qquickrhiitem/texture.frag (renamed from tests/auto/quick/qquickitemrhiintegration/texture.frag)0
-rw-r--r--tests/auto/quick/qquickrhiitem/texture.vert (renamed from tests/auto/quick/qquickitemrhiintegration/texture.vert)0
-rw-r--r--tests/auto/quick/qquickrhiitem/tst_qquickrhiitem.cpp150
-rw-r--r--tests/auto/quick/qquickscreen/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickscreen/tst_qquickscreen.cpp2
-rw-r--r--tests/auto/quick/qquickshadereffect/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickshadereffect/data/MyIcon.qml2
-rw-r--r--tests/auto/quick/qquickshadereffect/data/deleteShaderEffectSource.qml2
-rw-r--r--tests/auto/quick/qquickshadereffect/data/deleteSourceItem.qml2
-rw-r--r--tests/auto/quick/qquickshadereffect/data/hideParent.qml2
-rw-r--r--tests/auto/quick/qquickshadereffect/data/testProperties.qml2
-rw-r--r--tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml2
-rw-r--r--tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp2
-rw-r--r--tests/auto/quick/qquickshape/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickshape/data/filltransform.qml58
-rw-r--r--tests/auto/quick/qquickshape/data/multiline.qml2
-rw-r--r--tests/auto/quick/qquickshape/data/multilineStronglyTyped.qml2
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem7.qml2
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem8.qml2
-rw-r--r--tests/auto/quick/qquickshape/data/polyline.qml2
-rw-r--r--tests/auto/quick/qquickshape/tst_qquickshape.cpp39
-rw-r--r--tests/auto/quick/qquickshortcut/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickshortcut/data/embedded.qml20
-rw-r--r--tests/auto/quick/qquickshortcut/data/multiple.qml2
-rw-r--r--tests/auto/quick/qquickshortcut/data/shortcuts.qml2
-rw-r--r--tests/auto/quick/qquickshortcut/data/shortcutsRect.qml2
-rw-r--r--tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp89
-rw-r--r--tests/auto/quick/qquicksmoothedanimation/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp2
-rw-r--r--tests/auto/quick/qquickspringanimation/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp2
-rw-r--r--tests/auto/quick/qquickspritesequence/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickspritesequence/data/advance.qml2
-rw-r--r--tests/auto/quick/qquickspritesequence/data/basic.qml2
-rw-r--r--tests/auto/quick/qquickspritesequence/data/crashonstart.qml2
-rw-r--r--tests/auto/quick/qquickspritesequence/data/huge.qml2
-rw-r--r--tests/auto/quick/qquickspritesequence/data/spriteaftergoal.qml2
-rw-r--r--tests/auto/quick/qquickspritesequence/data/spritebeforegoal.qml2
-rw-r--r--tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp2
-rw-r--r--tests/auto/quick/qquickstates/CMakeLists.txt31
-rw-r--r--tests/auto/quick/qquickstates/data/anchorRewindSize.qml30
-rw-r--r--tests/auto/quick/qquickstates/data/broken.qml5
-rw-r--r--tests/auto/quick/qquickstates/tst_qquickstates.cpp63
-rw-r--r--tests/auto/quick/qquickstyledtext/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp3
-rw-r--r--tests/auto/quick/qquicksystempalette/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquicksystempalette/tst_qquicksystempalette.cpp8
-rw-r--r--tests/auto/quick/qquicktableview/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquicktableview/data/alternatingrowheightcolumnwidth.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/asyncloader.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/asyncplain.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/changemodelfromdelegate.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/changemodelordelegateduringupdate.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/checkalwaysemit.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/checkmodelpropertyrevision.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/checkrowandcolumnnotchanged.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/columnwidthboundtoviewwidth.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/contentwidthheight.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/countingtableview.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/delegateWithRequired.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/delegatewithRequiredUnset.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/delegatewithanchors.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/editdelegate.qml6
-rw-r--r--tests/auto/quick/qquicktableview/data/editdelegate_combobox.qml6
-rw-r--r--tests/auto/quick/qquicktableview/data/forcelayout.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/hiderowsandcolumns.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/iscolumnloaded.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/plaintableview.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/positionlast.qml52
-rw-r--r--tests/auto/quick/qquicktableview/data/qqmllistpropertymodel.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/reordertableview.qml52
-rw-r--r--tests/auto/quick/qquicktableview/data/resetJsModelData.qml19
-rw-r--r--tests/auto/quick/qquicktableview/data/resetModelData.qml25
-rw-r--r--tests/auto/quick/qquicktableview/data/setcontentpos.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/sizefromdelegate.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/syncviewsimple.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/tableviewdefaultspacing.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/tableviewfocus.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/tableviewimplicitsize.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/tableviewinteractive.qml32
-rw-r--r--tests/auto/quick/qquicktableview/data/tableviewwithselected1.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/tableviewwithselected2.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/tweakimplicitsize.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/unloadheader.qml43
-rw-r--r--tests/auto/quick/qquicktableview/data/usechooserwithoutdefault.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/usefaultyrowcolumnprovider.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/userowcolumnprovider.qml2
-rw-r--r--tests/auto/quick/qquicktableview/data/zerosizedtableview.qml10
-rw-r--r--tests/auto/quick/qquicktableview/data/zerosizedviewport.qml31
-rw-r--r--tests/auto/quick/qquicktableview/testmodel.h41
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp663
-rw-r--r--tests/auto/quick/qquicktext/BLACKLIST1
-rw-r--r--tests/auto/quick/qquicktext/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquicktext/data/elideZeroWidthWithMargins.qml27
-rw-r--r--tests/auto/quick/qquicktext/data/lineLayout.qml2
-rw-r--r--tests/auto/quick/qquicktext/data/lineLayoutFontUpdate.qml25
-rw-r--r--tests/auto/quick/qquicktext/data/lineLayoutImplicitWidth.qml4
-rw-r--r--tests/auto/quick/qquicktext/data/lineLayoutRelayout.qml2
-rw-r--r--tests/auto/quick/qquicktext/data/loaderActiveOnVisible.qml24
-rw-r--r--tests/auto/quick/qquicktext/data/long.qml7
-rw-r--r--tests/auto/quick/qquicktext/data/qtbug_106205.qml28
-rw-r--r--tests/auto/quick/qquicktext/data/tarzeau_ocr_a.ttfbin0 -> 24544 bytes
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp508
-rw-r--r--tests/auto/quick/qquicktextdocument/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquicktextdocument/data/hello-8857-7.html9
-rw-r--r--tests/auto/quick/qquicktextdocument/data/hello-utf16be.htmlbin0 -> 48 bytes
-rw-r--r--tests/auto/quick/qquicktextdocument/data/hello.html1
-rw-r--r--tests/auto/quick/qquicktextdocument/data/hello.md1
-rw-r--r--tests/auto/quick/qquicktextdocument/data/hello.txt1
-rw-r--r--tests/auto/quick/qquicktextdocument/data/initialText.qml16
-rw-r--r--tests/auto/quick/qquicktextdocument/data/sideBySideIndependent.qml21
-rw-r--r--tests/auto/quick/qquicktextdocument/data/sideBySideIndependentReverse.qml21
-rw-r--r--tests/auto/quick/qquicktextdocument/data/text.qml15
-rw-r--r--tests/auto/quick/qquicktextdocument/tst_qquicktextdocument.cpp565
-rw-r--r--tests/auto/quick/qquicktextedit/BLACKLIST15
-rw-r--r--tests/auto/quick/qquicktextedit/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquicktextedit/data/embeddedImagesLocalError.qml2
-rw-r--r--tests/auto/quick/qquicktextedit/data/embeddedImagesRemote.qml2
-rw-r--r--tests/auto/quick/qquicktextedit/data/embeddedImagesRemoteError.qml2
-rw-r--r--tests/auto/quick/qquicktextedit/data/focusByDefault.qml7
-rw-r--r--tests/auto/quick/qquicktextedit/data/hAlignVisual.qml6
-rw-r--r--tests/auto/quick/qquicktextedit/data/httpfail/warning.pngbin0 -> 10285 bytes
-rw-r--r--tests/auto/quick/qquicktextedit/data/httpslow/turtle.svg15
-rw-r--r--tests/auto/quick/qquicktextedit/data/inFlickable.qml7
-rw-r--r--tests/auto/quick/qquicktextedit/data/multipleRemoteImages.md13
-rw-r--r--tests/auto/quick/qquicktextedit/data/qtConfigureHelp.qml186
-rw-r--r--tests/auto/quick/qquicktextedit/data/qtbug-112858.qml12
-rw-r--r--tests/auto/quick/qquicktextedit/data/resizeTextEditPolish.qml42
-rw-r--r--tests/auto/quick/qquicktextedit/data/textEdit.qml6
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp1069
-rw-r--r--tests/auto/quick/qquicktextinput/BLACKLIST24
-rw-r--r--tests/auto/quick/qquicktextinput/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp52
-rw-r--r--tests/auto/quick/qquicktextmetrics/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquicktextmetrics/tst_qquicktextmetrics.cpp2
-rw-r--r--tests/auto/quick/qquicktimeline/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquicktimeline/tst_qquicktimeline.cpp2
-rw-r--r--tests/auto/quick/qquicktreeview/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquicktreeview/data/CustomDelegate.qml2
-rw-r--r--tests/auto/quick/qquicktreeview/data/normaltreeview.qml2
-rw-r--r--tests/auto/quick/qquicktreeview/testmodel.cpp32
-rw-r--r--tests/auto/quick/qquicktreeview/testmodel.h3
-rw-r--r--tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp223
-rw-r--r--tests/auto/quick/qquickview/CMakeLists.txt16
-rw-r--r--tests/auto/quick/qquickview/data/TestQml.qml3
-rw-r--r--tests/auto/quick/qquickview/data/overlay.qml17
-rw-r--r--tests/auto/quick/qquickview/tst_qquickview.cpp85
-rw-r--r--tests/auto/quick/qquickview_extra/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickview_extra/tst_qquickview_extra.cpp4
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/externalManagedModel.qml2
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp58
-rw-r--r--tests/auto/quick/qquickwindow/CMakeLists.txt6
-rw-r--r--tests/auto/quick/qquickwindow/data/conflictingVisibleFalse.qml6
-rw-r--r--tests/auto/quick/qquickwindow/data/conflictingVisibleTrue.qml6
-rw-r--r--tests/auto/quick/qquickwindow/data/eventTypes.qml20
-rw-r--r--tests/auto/quick/qquickwindow/data/maximized.qml5
-rw-r--r--tests/auto/quick/qquickwindow/data/shortcut.qml2
-rw-r--r--tests/auto/quick/qquickwindow/data/shortcutOverride.qml2
-rw-r--r--tests/auto/quick/qquickwindow/data/visibilityDoesntClobberWindowState.qml5
-rw-r--r--tests/auto/quick/qquickwindow/data/windowattached.qml4
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp214
-rw-r--r--tests/auto/quick/qquickwindowcontainer/CMakeLists.txt37
-rw-r--r--tests/auto/quick/qquickwindowcontainer/data/basicFunctionality_container.qml15
-rw-r--r--tests/auto/quick/qquickwindowcontainer/data/basicFunctionality_item.qml15
-rw-r--r--tests/auto/quick/qquickwindowcontainer/data/basicFunctionality_window.qml10
-rw-r--r--tests/auto/quick/qquickwindowcontainer/data/deferredVisibilityWithoutWindow.qml11
-rw-r--r--tests/auto/quick/qquickwindowcontainer/data/windowComponent.qml28
-rw-r--r--tests/auto/quick/qquickwindowcontainer/tst_qquickwindowcontainer.cpp200
-rw-r--r--tests/auto/quick/rendernode/CMakeLists.txt6
-rw-r--r--tests/auto/quick/rendernode/data/glsimple.qml2
-rw-r--r--tests/auto/quick/rendernode/data/simple.qml2
-rw-r--r--tests/auto/quick/rendernode/tst_rendernode.cpp4
-rw-r--r--tests/auto/quick/scenegraph/BLACKLIST3
-rw-r--r--tests/auto/quick/scenegraph/CMakeLists.txt16
-rw-r--r--tests/auto/quick/scenegraph/data/RenderTestBase.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/manyWindows_dftext.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/manyWindows_image.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/manyWindows_ntext.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/manyWindows_rects.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/renderControl_rect.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/render_AlphaOverlapRebuild.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/render_BreakOpacityBatch.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/render_DrawSets.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/render_ImageFiltering.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/render_Mipmap.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/render_MovingOverlap.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/render_OpacityThroughBatchRoot.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/render_OutOfFloatRange.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/render_Overlap.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/render_StackingOrder.qml2
-rw-r--r--tests/auto/quick/scenegraph/data/render_bug37422.frag.qsbbin686 -> 0 bytes
-rw-r--r--tests/auto/quick/scenegraph/data/render_bug37422.qml4
-rw-r--r--tests/auto/quick/scenegraph/data/simple.qml2
-rw-r--r--tests/auto/quick/scenegraph/tst_scenegraph.cpp72
-rw-r--r--tests/auto/quick/sharedimage/CMakeLists.txt6
-rw-r--r--tests/auto/quick/sharedimage/tst_sharedimage.cpp2
-rw-r--r--tests/auto/quick/softwarerenderer/CMakeLists.txt6
-rw-r--r--tests/auto/quick/softwarerenderer/tst_softwarerenderer.cpp2
-rw-r--r--tests/auto/quick/touchmouse/BLACKLIST5
-rw-r--r--tests/auto/quick/touchmouse/CMakeLists.txt6
-rw-r--r--tests/auto/quick/touchmouse/tst_touchmouse.cpp23
-rw-r--r--tests/auto/quickcontrols/CMakeLists.txt5
-rw-r--r--tests/auto/quickcontrols/accessibility/CMakeLists.txt12
-rw-r--r--tests/auto/quickcontrols/accessibility/data/actionAccessibility/button.qml12
-rw-r--r--tests/auto/quickcontrols/accessibility/tst_accessibility.cpp24
-rw-r--r--tests/auto/quickcontrols/cmake/CMakeLists.txt16
-rw-r--r--tests/auto/quickcontrols/controls/CMakeLists.txt1
-rw-r--r--tests/auto/quickcontrols/controls/basic/BLACKLIST5
-rw-r--r--tests/auto/quickcontrols/controls/basic/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/basic/tst_basic.cpp5
-rw-r--r--tests/auto/quickcontrols/controls/data/SignalSequenceSpy.qml2
-rw-r--r--tests/auto/quickcontrols/controls/data/TestItem.qml2
-rw-r--r--tests/auto/quickcontrols/controls/data/TumblerDatePicker.qml2
-rw-r--r--tests/auto/quickcontrols/controls/data/TumblerListView.qml2
-rw-r--r--tests/auto/quickcontrols/controls/data/TumblerPathView.qml2
-rw-r--r--tests/auto/quickcontrols/controls/data/combobox/shader.frag19
-rw-r--r--tests/auto/quickcontrols/controls/data/combobox/shader.frag.qsbbin0 -> 577 bytes
-rw-r--r--tests/auto/quickcontrols/controls/data/splitview/fillItemInMiddle.qml2
-rw-r--r--tests/auto/quickcontrols/controls/data/splitview/fillItemOnLeft.qml2
-rw-r--r--tests/auto/quickcontrols/controls/data/splitview/fillItemOnTop.qml2
-rw-r--r--tests/auto/quickcontrols/controls/data/stackview/Rect.qml8
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_abstractbutton.qml346
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_action.qml30
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_actiongroup.qml192
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_busyindicator.qml35
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_button.qml83
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_buttongroup.qml126
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_calendarmodel.qml37
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_checkbox.qml48
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_checkdelegate.qml30
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_combobox.qml140
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_container.qml32
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_control.qml184
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_dayofweekrow.qml10
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_delaybutton.qml30
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_dial.qml325
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_dialog.qml61
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_dialogbuttonbox.qml80
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_frame.qml14
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_groupbox.qml14
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_itemdelegate.qml20
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_label.qml40
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_menuitem.qml26
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_monthgrid.qml48
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_page.qml37
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_pageindicator.qml41
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_pane.qml141
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_popup.qml218
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_progressbar.qml18
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_radiobutton.qml58
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_radiodelegate.qml26
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_rangeslider.qml318
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_roundbutton.qml20
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_scrollbar.qml171
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_scrollindicator.qml44
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_scrollview.qml193
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml424
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_slider.qml159
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_spinbox.qml585
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_splitview.qml478
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_stackview.qml588
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_swipedelegate.qml244
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_swipeview.qml164
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_switch.qml52
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_switchdelegate.qml62
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_tabbar.qml80
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_tabbutton.qml24
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_textarea.qml155
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_textfield.qml146
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_toolbar.qml14
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_toolbutton.qml32
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_toolseparator.qml16
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_tooltip.qml65
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_tumbler.qml235
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_weeknumbercolumn.qml16
-rw-r--r--tests/auto/quickcontrols/controls/fluentwinui3/BLACKLIST14
-rw-r--r--tests/auto/quickcontrols/controls/fluentwinui3/CMakeLists.txt38
-rw-r--r--tests/auto/quickcontrols/controls/fluentwinui3/dependencies.qml6
-rw-r--r--tests/auto/quickcontrols/controls/fluentwinui3/dummy_imports.qml12
-rw-r--r--tests/auto/quickcontrols/controls/fluentwinui3/tst_fluentwinui3.cpp13
-rw-r--r--tests/auto/quickcontrols/controls/fusion/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/fusion/tst_fusion.cpp5
-rw-r--r--tests/auto/quickcontrols/controls/imagine/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/imagine/tst_imagine.cpp5
-rw-r--r--tests/auto/quickcontrols/controls/ios/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/ios/tst_ios.cpp5
-rw-r--r--tests/auto/quickcontrols/controls/macos/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/macos/tst_macos.cpp5
-rw-r--r--tests/auto/quickcontrols/controls/material/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/material/tst_material.cpp5
-rw-r--r--tests/auto/quickcontrols/controls/universal/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/universal/tst_universal.cpp5
-rw-r--r--tests/auto/quickcontrols/controls/windows/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/windows/tst_windows.cpp5
-rw-r--r--tests/auto/quickcontrols/cursor/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/cursor/data/buttons.qml2
-rw-r--r--tests/auto/quickcontrols/cursor/data/containers.qml2
-rw-r--r--tests/auto/quickcontrols/cursor/data/editable.qml2
-rw-r--r--tests/auto/quickcontrols/cursor/data/pageindicator.qml2
-rw-r--r--tests/auto/quickcontrols/cursor/data/scrollbar.qml2
-rw-r--r--tests/auto/quickcontrols/cursor/data/sliders.qml2
-rw-r--r--tests/auto/quickcontrols/cursor/tst_cursor.cpp2
-rw-r--r--tests/auto/quickcontrols/customization/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/AbstractButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/ApplicationWindow.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/BusyIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Button.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/CheckBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/CheckDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/ComboBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Container.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Control.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/DelayButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Dial.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Dialog.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/DialogButtonBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Drawer.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Frame.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/GroupBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/ItemDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Label.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Menu.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/MenuBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/MenuBarItem.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/MenuItem.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/MenuSeparator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Page.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/PageIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Pane.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Popup.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/ProgressBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/RadioButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/RadioDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/RangeSlider.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/RoundButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/ScrollBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/ScrollIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/ScrollView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Slider.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/SpinBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/StackView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/SwipeDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/SwipeView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Switch.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/SwitchDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/TabBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/TabButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/TextArea.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/TextField.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/ToolBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/ToolButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/ToolSeparator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/ToolTip.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/empty/Tumbler.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/AbstractButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/ApplicationWindow.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/BusyIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Button.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/CheckBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/CheckDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/ComboBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Container.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Control.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/DelayButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Dial.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Dialog.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/DialogButtonBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Drawer.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Frame.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/GroupBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/ItemDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Label.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Menu.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/MenuBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/MenuBarItem.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/MenuItem.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/MenuSeparator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Page.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/PageIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Pane.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Popup.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/ProgressBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/RadioButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/RadioDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/RangeSlider.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/RoundButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/ScrollBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/ScrollIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/ScrollView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Slider.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/SpinBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/StackView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/SwipeDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/SwipeView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Switch.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/SwitchDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/TabBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/TabButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/TextArea.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/TextField.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/ToolBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/ToolButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/ToolSeparator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/ToolTip.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/identified/Tumbler.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/AbstractButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/ApplicationWindow.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/BusyIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Button.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/CheckBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/CheckDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/ComboBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Container.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Control.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/DelayButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Dial.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Dialog.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/DialogButtonBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Drawer.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Frame.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/GroupBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/ItemDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Label.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Menu.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/MenuBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/MenuBarItem.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/MenuItem.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/MenuSeparator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Page.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/PageIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Pane.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Popup.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/ProgressBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/RadioButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/RadioDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/RangeSlider.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/RoundButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Slider.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/SpinBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/StackView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/SwipeDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/SwipeView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Switch.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/SwitchDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/TabBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/TabButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/TextArea.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/TextField.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/ToolBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/ToolButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/ToolSeparator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/ToolTip.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/incomplete/Tumbler.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/AbstractButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/ApplicationWindow.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/BusyIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Button.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/CheckBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/CheckDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/ComboBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Container.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Control.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/DelayButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Dial.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Dialog.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/DialogButtonBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Drawer.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Frame.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/GroupBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/ItemDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Label.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Menu.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/MenuBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/MenuBarItem.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/MenuItem.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/MenuSeparator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Page.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/PageIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Pane.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Popup.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/ProgressBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/RadioButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/RadioDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/RangeSlider.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/RoundButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/ScrollBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/ScrollIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/ScrollView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Slider.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/SpinBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/StackView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/SwipeDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/SwipeView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Switch.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/SwitchDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/TabBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/TabButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/TextArea.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/TextField.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/ToolBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/ToolButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/ToolSeparator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/ToolTip.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/override/Tumbler.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/AbstractButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/ApplicationWindow.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/BusyIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Button.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/CheckBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/CheckDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/ComboBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Container.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Control.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/DelayButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Dial.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Dialog.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/DialogButtonBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Drawer.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Frame.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/GroupBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/ItemDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Label.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Menu.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/MenuBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/MenuBarItem.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/MenuItem.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/MenuSeparator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Page.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/PageIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Pane.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Popup.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/ProgressBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/RadioButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/RadioDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/RangeSlider.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/RoundButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/ScrollBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/ScrollIndicator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/ScrollView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Slider.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/SpinBox.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/StackView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/SwipeDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/SwipeView.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Switch.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/SwitchDelegate.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/TabBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/TabButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/TextArea.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/TextField.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/ToolBar.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/ToolButton.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/ToolSeparator.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/ToolTip.qml2
-rw-r--r--tests/auto/quickcontrols/customization/data/styles/simple/Tumbler.qml2
-rw-r--r--tests/auto/quickcontrols/customization/tst_customization.cpp14
-rw-r--r--tests/auto/quickcontrols/deferred/CMakeLists.txt6
-rw-r--r--tests/auto/quickcontrols/deferred/data/abortedIncubation.qml171
-rw-r--r--tests/auto/quickcontrols/deferred/tst_qquickdeferred.cpp23
-rw-r--r--tests/auto/quickcontrols/designer/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/designer/tst_designer.cpp2
-rw-r--r--tests/auto/quickcontrols/focus/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/focus/data/activeFocusOnTab.qml2
-rw-r--r--tests/auto/quickcontrols/focus/data/keyNavigation.qml2
-rw-r--r--tests/auto/quickcontrols/focus/data/visualFocus.qml2
-rw-r--r--tests/auto/quickcontrols/focus/tst_focus.cpp47
-rw-r--r--tests/auto/quickcontrols/font/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/font/data/font-appwindow-custom.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/font-appwindow-default.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/font-control-custom.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/font-control-default.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/font-popup-custom.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/font-popup-default.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/inheritance-childcontrol.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/inheritance-childpopup.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/inheritance-control.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/inheritance-dynamicchildcontrol.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/inheritance-dynamicchildpopup.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/inheritance-dynamiccontrol.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/inheritance-dynamicpopup.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/inheritance-popup.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/listview.qml2
-rw-r--r--tests/auto/quickcontrols/font/data/resolve.qml2
-rw-r--r--tests/auto/quickcontrols/font/tst_font.cpp40
-rw-r--r--tests/auto/quickcontrols/palette/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/palette/data/bindings.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/childPopupInheritance.qml40
-rw-r--r--tests/auto/quickcontrols/palette/data/comboBoxPopupWithApplicationWindow.qml32
-rw-r--r--tests/auto/quickcontrols/palette/data/comboBoxPopupWithThemeDefault.qml17
-rw-r--r--tests/auto/quickcontrols/palette/data/comboBoxPopupWithWindow.qml33
-rw-r--r--tests/auto/quickcontrols/palette/data/inheritance-childcontrol.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/inheritance-childpopup.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/inheritance-control.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/inheritance-dynamicchildcontrol.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/inheritance-dynamicchildpopup.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/inheritance-dynamiccontrol.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/inheritance-dynamicpopup.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/inheritance-popup.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/listview.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/palette-appwindow-bindingpalette.qml15
-rw-r--r--tests/auto/quickcontrols/palette/data/palette-appwindow-custom.qml3
-rw-r--r--tests/auto/quickcontrols/palette/data/palette-appwindow-default.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/palette-control-custom.qml3
-rw-r--r--tests/auto/quickcontrols/palette/data/palette-control-default.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/palette-popup-custom.qml3
-rw-r--r--tests/auto/quickcontrols/palette/data/palette-popup-default.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/reset-color.qml52
-rw-r--r--tests/auto/quickcontrols/palette/data/resolve.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/set-palette.qml2
-rw-r--r--tests/auto/quickcontrols/palette/data/toolTipPaletteUpdate.qml19
-rw-r--r--tests/auto/quickcontrols/palette/qtquickcontrols2.conf4
-rw-r--r--tests/auto/quickcontrols/palette/tst_palette.cpp267
-rw-r--r--tests/auto/quickcontrols/platform/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/platform/data/tst_colordialog.qml2
-rw-r--r--tests/auto/quickcontrols/platform/data/tst_filedialog.qml2
-rw-r--r--tests/auto/quickcontrols/platform/data/tst_folderdialog.qml2
-rw-r--r--tests/auto/quickcontrols/platform/data/tst_fontdialog.qml2
-rw-r--r--tests/auto/quickcontrols/platform/data/tst_menu.qml2
-rw-r--r--tests/auto/quickcontrols/platform/data/tst_menubar.qml2
-rw-r--r--tests/auto/quickcontrols/platform/data/tst_menuitem.qml27
-rw-r--r--tests/auto/quickcontrols/platform/data/tst_menuitemgroup.qml2
-rw-r--r--tests/auto/quickcontrols/platform/data/tst_menuseparator.qml2
-rw-r--r--tests/auto/quickcontrols/platform/data/tst_messagedialog.qml2
-rw-r--r--tests/auto/quickcontrols/platform/data/tst_standardpaths.qml2
-rw-r--r--tests/auto/quickcontrols/platform/data/tst_systemtrayicon.qml2
-rw-r--r--tests/auto/quickcontrols/platform/tst_platform.cpp15
-rw-r--r--tests/auto/quickcontrols/pointerhandlers/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/pointerhandlers/tst_pointerhandlers.cpp4
-rw-r--r--tests/auto/quickcontrols/pressandhold/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/pressandhold/tst_pressandhold.cpp40
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/CMakeLists.txt12
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/activeFocusControl.qml2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/activefocusontab.qml2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/attachedProperties.qml2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/backgroundSize.qml16
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/basicapplicationwindow.qml2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/clearfocusondestruction.qml2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/defaultFocus.qml2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/explicitBackgroundSizeBinding.qml21
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/fill.qml2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/focusAfterPopupClosed.qml2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/font.qml2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/layout.qml2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/layoutLayout.qml2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/locale.qml2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/data/opacity.qml2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp75
-rw-r--r--tests/auto/quickcontrols/qquickcolor/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickcolor/data/tst_color.qml2
-rw-r--r--tests/auto/quickcontrols/qquickcolor/tst_qquickcolor.cpp2
-rw-r--r--tests/auto/quickcontrols/qquickcontrol/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickcontrol/data/flickable.qml2
-rw-r--r--tests/auto/quickcontrols/qquickcontrol/tst_qquickcontrol.cpp2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-button.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-hover.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-wheel.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/applicationwindow.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/dragOverModalShadow.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/flickable.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/grabber.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/header.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/multiTouch.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/multiple.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/reposition.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/slider.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/topEdgeScreenEdge.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/window-button.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/window-hover.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/window-wheel.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/data/window.qml2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/tst_qquickdrawer.cpp46
-rw-r--r--tests/auto/quickcontrols/qquickheaderview/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickheaderview/data/DefaultRoles.qml34
-rw-r--r--tests/auto/quickcontrols/qquickheaderview/data/ListModel.qml2
-rw-r--r--tests/auto/quickcontrols/qquickheaderview/data/Window.qml2
-rw-r--r--tests/auto/quickcontrols/qquickheaderview/data/headerData.qml37
-rw-r--r--tests/auto/quickcontrols/qquickheaderview/data/resizableHandlerBlockingEvents.qml29
-rw-r--r--tests/auto/quickcontrols/qquickheaderview/tst_qquickheaderview.cpp89
-rw-r--r--tests/auto/quickcontrols/qquickiconimage/BLACKLIST2
-rw-r--r--tests/auto/quickcontrols/qquickiconimage/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickiconimage/data/translucentColors.qml2
-rw-r--r--tests/auto/quickcontrols/qquickiconimage/tst_qquickiconimage.cpp53
-rw-r--r--tests/auto/quickcontrols/qquickiconlabel/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickiconlabel/data/colorChanges.qml2
-rw-r--r--tests/auto/quickcontrols/qquickiconlabel/data/iconlabel.qml2
-rw-r--r--tests/auto/quickcontrols/qquickiconlabel/data/spacingWithOnlyIcon.qml2
-rw-r--r--tests/auto/quickcontrols/qquickiconlabel/data/spacingWithOnlyText.qml2
-rw-r--r--tests/auto/quickcontrols/qquickiconlabel/tst_qquickiconlabel.cpp7
-rw-r--r--tests/auto/quickcontrols/qquickimaginestyle/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickimaginestyle/data/tst_imagine.qml2
-rw-r--r--tests/auto/quickcontrols/qquickimaginestyle/tst_qquickimaginestyle.cpp2
-rw-r--r--tests/auto/quickcontrols/qquickmaterialstyle/CMakeLists.txt11
-rw-r--r--tests/auto/quickcontrols/qquickmaterialstyle/data/tst_material.qml557
-rw-r--r--tests/auto/quickcontrols/qquickmaterialstyle/tst_qquickmaterialstyle.cpp18
-rw-r--r--tests/auto/quickcontrols/qquickmaterialstyleconf/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickmaterialstyleconf/data/applicationwindow.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmaterialstyleconf/qtquickcontrols2.conf4
-rw-r--r--tests/auto/quickcontrols/qquickmaterialstyleconf/tst_qquickmaterialstyleconf.cpp2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/actionShortcuts.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/actions.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/addItem.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/applicationWindowScrollable.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/applicationwindow.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/delegateFromSeparateComponent.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/disableWhenTriggered.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/disabledMenuItemKeyNavigation.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/giveMenuItemFocusOnButtonPress.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/invalidUrlInImgTag.qml14
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/menuItemWidths.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/menuSeparator.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/mnemonics.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/nativeDynamicSubmenus.qml53
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/nativeEmptyMenu.qml51
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/nativeMenuSeparator.qml43
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/nativeMixedItems.qml69
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/nativeStatic.qml53
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/order.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/popup.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/pressAndHold.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/removeTakeItem.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/repeater.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml27
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/scrollableWithPadding.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/subMenuDisabled.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/subMenus.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/windowScrollable.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp824
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/data/checkHighlightWhenDismissed.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/data/delegateFromSeparateComponent.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/data/empty.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/data/hoverAfterClosingWithEscape.qml46
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/data/invaliddelegate.qml40
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/data/menubarAsHeader.qml64
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/data/menubaritems.qml (renamed from tests/auto/quickcontrols/qquickmenubar/data/menubar.qml)13
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/data/menus.qml85
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/data/mixed.qml55
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/data/nodelegate.qml40
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/data/showandhide.qml40
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/data/touch.qml20
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp1097
-rw-r--r--tests/auto/quickcontrols/qquickninepatchimage/CMakeLists.txt8
-rw-r--r--tests/auto/quickcontrols/qquickninepatchimage/data/logo.pkmbin0 -> 32784 bytes
-rw-r--r--tests/auto/quickcontrols/qquickninepatchimage/data/o1_bc1.ktxbin0 -> 2116 bytes
-rw-r--r--tests/auto/quickcontrols/qquickninepatchimage/data/qt4.astcbin0 -> 12816 bytes
-rw-r--r--tests/auto/quickcontrols/qquickninepatchimage/tst_qquickninepatchimage.cpp72
-rw-r--r--tests/auto/quickcontrols/qquickoverlay/CMakeLists.txt43
-rw-r--r--tests/auto/quickcontrols/qquickoverlay/tst_qquickoverlay.cpp223
-rw-r--r--tests/auto/quickcontrols/qquickpopup/BLACKLIST15
-rw-r--r--tests/auto/quickcontrols/qquickpopup/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterExit.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterWindowInactive.qml27
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose1.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose2.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose3.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClosingSeveralPopups.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/activeFocusOnDelayedEnter.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/applicationwindow-hover.qml18
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/applicationwindow-wheel.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/applicationwindow.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/centerInOverlayWithinStackViewItem.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/closeOnEscapeWithNestedPopups.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/countChanged.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/cursor.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/destroyDuringExitTransition.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/dialog.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/dimmerContainmentMask.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/disabledPalette.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/doubleClickInMouseArea.qml23
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/fadeDimmer.qml39
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/grabber.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/mirroredCombobox.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/modelessOnModalOnModeless.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/multiplepopup.qml82
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/nested-wheel-overlay-parent.qml39
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/nested.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/noDimmer.qml22
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/orientation.qml24
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/popupCenterIn.qml22
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/popupWindowFocusHandling.qml28
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/popupWithButtonInBackground.qml28
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/releaseAfterExitTransition.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/reparentingPopup.qml48
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/rotatedCombobox.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowHeight.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowWidth.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/simplepopup.qml22
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/tabFence.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/toolTipCrashOnClose.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/window-hover.qml17
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/window-wheel.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/window.qml2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp840
-rw-r--r--tests/auto/quickcontrols/qquickstyle/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickstyle/tst_qquickstyle.cpp2
-rw-r--r--tests/auto/quickcontrols/qquicktextarea/CMakeLists.txt4
-rw-r--r--tests/auto/quickcontrols/qquicktextarea/tst_qquicktextarea.cpp20
-rw-r--r--tests/auto/quickcontrols/qquicktextfield/CMakeLists.txt4
-rw-r--r--tests/auto/quickcontrols/qquicktextfield/tst_qquicktextfield.cpp8
-rw-r--r--tests/auto/quickcontrols/qquicktreeviewdelegate/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquicktreeviewdelegate/data/unmodified.qml2
-rw-r--r--tests/auto/quickcontrols/qquicktreeviewdelegate/testmodel.cpp2
-rw-r--r--tests/auto/quickcontrols/qquicktreeviewdelegate/testmodel.h2
-rw-r--r--tests/auto/quickcontrols/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp24
-rw-r--r--tests/auto/quickcontrols/qquickuniversalstyle/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickuniversalstyle/data/tst_universal.qml2
-rw-r--r--tests/auto/quickcontrols/qquickuniversalstyle/tst_qquickuniversalstyle.cpp18
-rw-r--r--tests/auto/quickcontrols/qquickuniversalstyleconf/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickuniversalstyleconf/data/applicationwindow.qml2
-rw-r--r--tests/auto/quickcontrols/qquickuniversalstyleconf/qtquickcontrols2.conf4
-rw-r--r--tests/auto/quickcontrols/qquickuniversalstyleconf/tst_qquickuniversalstyleconf.cpp2
-rw-r--r--tests/auto/quickcontrols/revisions/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/revisions/tst_revisions.cpp2
-rw-r--r--tests/auto/quickcontrols/sanity/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/sanity/data/attachedTypeResolution.qml6
-rw-r--r--tests/auto/quickcontrols/sanity/quickcontrolssanity.cpp36
-rw-r--r--tests/auto/quickcontrols/sanity/quickcontrolssanity.h2
-rw-r--r--tests/auto/quickcontrols/sanity/tst_sanity.cpp16
-rw-r--r--tests/auto/quickcontrols/snippets/CMakeLists.txt4
-rw-r--r--tests/auto/quickcontrols/snippets/tst_snippets.cpp5
-rw-r--r--tests/auto/quickcontrols/styleimports/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/styleimports/data/applicationWindowWithButton.qml5
-rw-r--r--tests/auto/quickcontrols/styleimports/data/customStyleSelector.qml2
-rw-r--r--tests/auto/quickcontrols/styleimports/data/importStyleWithQmlDirFallback.qml17
-rw-r--r--tests/auto/quickcontrols/styleimports/data/styles/FileSystemStyle/Button.qml5
-rw-r--r--tests/auto/quickcontrols/styleimports/data/styles/StyleThatImportsMaterial/Button.qml34
-rw-r--r--tests/auto/quickcontrols/styleimports/data/styles/StyleThatImportsMaterial/qmldir3
-rw-r--r--tests/auto/quickcontrols/styleimports/tst_styleimports.cpp96
-rw-r--r--tests/auto/quickcontrols/styleimportscompiletimematerial/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/styleimportscompiletimematerial/data/importMaterialStyleWithoutControls.qml2
-rw-r--r--tests/auto/quickcontrols/styleimportscompiletimematerial/tst_styleimportscompiletimematerial.cpp2
-rw-r--r--tests/auto/quickcontrols/styleimportscompiletimeqmlonly/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/styleimportscompiletimeqmlonly/data/QmlOnly/Button.qml2
-rw-r--r--tests/auto/quickcontrols/styleimportscompiletimeqmlonly/data/importQmlOnlyStyleWithoutControls.qml2
-rw-r--r--tests/auto/quickcontrols/styleimportscompiletimeqmlonly/tst_styleimportscompiletimeqmlonly.cpp2
-rw-r--r--tests/auto/quickcontrols/translation/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/translation/data/comboBox.qml2
-rw-r--r--tests/auto/quickcontrols/translation/data/dialogButtonBox.qml2
-rw-r--r--tests/auto/quickcontrols/translation/data/dialogButtonBoxWithCustomButtons.qml2
-rw-r--r--tests/auto/quickcontrols/translation/data/stackView.qml2
-rw-r--r--tests/auto/quickcontrols/translation/tst_translation.cpp2
-rw-r--r--tests/auto/quickdialogs/qquickcolordialogimpl/CMakeLists.txt6
-rw-r--r--tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialog.qml2
-rw-r--r--tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindow.qml27
-rw-r--r--tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindowVisibleTrue.qml28
-rw-r--r--tests/auto/quickdialogs/qquickcolordialogimpl/data/windowSwapping.qml58
-rw-r--r--tests/auto/quickdialogs/qquickcolordialogimpl/tst_qquickcolordialogimpl.cpp96
-rw-r--r--tests/auto/quickdialogs/qquickfiledialogimpl/CMakeLists.txt6
-rw-r--r--tests/auto/quickdialogs/qquickfiledialogimpl/data/acceptRejectLabel.qml2
-rw-r--r--tests/auto/quickdialogs/qquickfiledialogimpl/data/bindAllTxtHtmlNameFilters.qml2
-rw-r--r--tests/auto/quickdialogs/qquickfiledialogimpl/data/bindCurrentFolder.qml2
-rw-r--r--tests/auto/quickdialogs/qquickfiledialogimpl/data/bindTitle.qml2
-rw-r--r--tests/auto/quickdialogs/qquickfiledialogimpl/data/bindTxtHtmlNameFilters.qml2
-rw-r--r--tests/auto/quickdialogs/qquickfiledialogimpl/data/fileDialog.qml2
-rw-r--r--tests/auto/quickdialogs/qquickfiledialogimpl/data/setSelectedFile.qml2
-rw-r--r--tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp309
-rw-r--r--tests/auto/quickdialogs/qquickfolderdialogimpl/CMakeLists.txt6
-rw-r--r--tests/auto/quickdialogs/qquickfolderdialogimpl/data/acceptRejectLabel.qml2
-rw-r--r--tests/auto/quickdialogs/qquickfolderdialogimpl/data/bindCurrentFolder.qml2
-rw-r--r--tests/auto/quickdialogs/qquickfolderdialogimpl/data/bindTitle.qml2
-rw-r--r--tests/auto/quickdialogs/qquickfolderdialogimpl/data/folderDialog.qml2
-rw-r--r--tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp21
-rw-r--r--tests/auto/quickdialogs/qquickfontdialogimpl/BLACKLIST1
-rw-r--r--tests/auto/quickdialogs/qquickfontdialogimpl/CMakeLists.txt6
-rw-r--r--tests/auto/quickdialogs/qquickfontdialogimpl/data/fontDialog.qml2
-rw-r--r--tests/auto/quickdialogs/qquickfontdialogimpl/tst_qquickfontdialogimpl.cpp4
-rw-r--r--tests/auto/quickdialogs/qquickmessagedialogimpl/CMakeLists.txt6
-rw-r--r--tests/auto/quickdialogs/qquickmessagedialogimpl/data/messageDialog.qml2
-rw-r--r--tests/auto/quickdialogs/qquickmessagedialogimpl/data/messageDialogWithButtons.qml19
-rw-r--r--tests/auto/quickdialogs/qquickmessagedialogimpl/tst_qquickmessagedialogimpl.cpp99
-rw-r--r--tests/auto/quicktest/polish-qml/CMakeLists.txt6
-rw-r--r--tests/auto/quicktest/polish-qml/data/tst_polish.qml2
-rw-r--r--tests/auto/quicktest/polish-qml/tst_polish-qml.cpp2
-rw-r--r--tests/auto/quicktest/polish/CMakeLists.txt6
-rw-r--r--tests/auto/quicktest/polish/data/childPolish.qml2
-rw-r--r--tests/auto/quicktest/polish/data/polish.qml2
-rw-r--r--tests/auto/quicktest/polish/tst_polish.cpp2
-rw-r--r--tests/auto/quicktest/quicktestmainwithsetup/CMakeLists.txt6
-rw-r--r--tests/auto/quicktest/quicktestmainwithsetup/data/tst_setup.qml2
-rw-r--r--tests/auto/quicktest/quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp2
-rw-r--r--tests/auto/quicktest/signalspy/CMakeLists.txt6
-rw-r--r--tests/auto/quicktest/signalspy/data/signalspy.qml2
-rw-r--r--tests/auto/quicktest/signalspy/data/signalspy2.qml2
-rw-r--r--tests/auto/quicktest/signalspy/mypropertymap.cpp2
-rw-r--r--tests/auto/quicktest/signalspy/mypropertymap.h2
-rw-r--r--tests/auto/quicktest/signalspy/tst_signalspy.cpp2
-rw-r--r--tests/auto/quicktest/testfiltering/quicktestmain/CMakeLists.txt6
-rw-r--r--tests/auto/quicktest/testfiltering/quicktestmain/quicktestmain.cpp2
-rw-r--r--tests/auto/quicktest/testfiltering/quicktestmain/tst_first.qml2
-rw-r--r--tests/auto/quicktest/testfiltering/quicktestmain/tst_second.qml2
-rw-r--r--tests/auto/quicktest/testfiltering/quicktestmain/tst_third.qml2
-rw-r--r--tests/auto/quicktest/testfiltering/test/CMakeLists.txt6
-rw-r--r--tests/auto/quicktest/testfiltering/tst_testfiltering.cpp2
-rw-r--r--tests/auto/quicktest/testswithcomponents/CMakeLists.txt6
-rw-r--r--tests/auto/quicktest/testswithcomponents/data/tst_setup.qml2
-rw-r--r--tests/auto/quicktest/testswithcomponents/tst_quicktestswithcomponents.cpp2
-rw-r--r--tests/auto/quickwidgets/qquickwidget/BLACKLIST7
-rw-r--r--tests/auto/quickwidgets/qquickwidget/CMakeLists.txt6
-rw-r--r--tests/auto/quickwidgets/qquickwidget/data/activeFocusOnTab.qml2
-rw-r--r--tests/auto/quickwidgets/qquickwidget/data/noActiveFocusOnTab.qml2
-rw-r--r--tests/auto/quickwidgets/qquickwidget/data/tapHandler.qml11
-rw-r--r--tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp172
-rw-r--r--tests/auto/toolsupport/CMakeLists.txt8
-rw-r--r--tests/auto/toolsupport/tst_toolsupport.cpp11
3016 files changed, 73151 insertions, 13237 deletions
diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt
index 74c4ee86d6..b47bd318d5 100644
--- a/tests/auto/CMakeLists.txt
+++ b/tests/auto/CMakeLists.txt
@@ -26,6 +26,7 @@ if(TARGET Qt::Quick)
endif()
if(TARGET Qt::QuickTest)
add_subdirectory(core)
+ add_subdirectory(qmlnetwork)
endif()
add_subdirectory(toolsupport)
if(NOT UIKIT AND NOT ANDROID AND NOT QNX) # FIXME: QTBUG-92591 QTBUG-100202
diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt
index fd2053176a..9d2ef3bd88 100644
--- a/tests/auto/cmake/CMakeLists.txt
+++ b/tests/auto/cmake/CMakeLists.txt
@@ -93,6 +93,12 @@ if(TARGET Qt::Quick)
)
endif()
+if(TARGET Qt::QuickControls2)
+ list(APPEND module_includes
+ QuickControls2 QQuickStyle
+ )
+endif()
+
_qt_internal_test_module_includes(${module_includes})
if(TARGET Qt::Qml)
@@ -110,10 +116,20 @@ if(TARGET Qt::Qml)
If(NOT ANDROID) # QML only project cannot run on Android with C++ enty point
_qt_internal_test_expect_pass(qmlquery)
endif()
+ _qt_internal_test_expect_fail(test_internal_singleton)
+
+ # Make sure that we don't attempt to run binary when crosscompiling
+ if(NOT CMAKE_CROSSCOMPILING)
+ set(test_static_qml_module_extra_args BINARY test_static_qml_module)
+ else()
+ set(test_static_qml_module_extra_args "")
+ endif()
+ _qt_internal_test_expect_pass(test_static_qml_module ${test_static_qml_module_extra_args})
endif()
if(TARGET Qt::Quick)
if(NOT CMAKE_CROSSCOMPILING)
+ _qt_internal_test_expect_pass(shared_qml_module)
_qt_internal_test_expect_pass(qtquickcompiler BINARY qqc_test)
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.21")
_qt_internal_test_expect_pass(test_common_import_path
@@ -121,6 +137,12 @@ if(TARGET Qt::Quick)
BINARY cmake_test
)
endif()
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.19")
+ _qt_internal_test_expect_pass(test_generate_qmlls_ini BINARY tst_generate_qmlls_ini)
+ endif()
+ _qt_internal_test_expect_pass(
+ test_link_qml_module_without_target
+ BINARY test_link_qml_module_without_target)
endif()
if(NOT QT6_IS_SHARED_LIBS_BUILD)
_qt_internal_test_expect_pass(test_import_static_shapes_plugin_resources
@@ -135,4 +157,3 @@ if(TARGET Qt::Quick)
endif()
endif()
endif()
-
diff --git a/tests/auto/cmake/empty_qmldir/enemy.cpp b/tests/auto/cmake/empty_qmldir/enemy.cpp
index 5365d75e05..2821cef07c 100644
--- a/tests/auto/cmake/empty_qmldir/enemy.cpp
+++ b/tests/auto/cmake/empty_qmldir/enemy.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "enemy.h"
diff --git a/tests/auto/cmake/empty_qmldir/enemy.h b/tests/auto/cmake/empty_qmldir/enemy.h
index 051176c8f6..96b3516884 100644
--- a/tests/auto/cmake/empty_qmldir/enemy.h
+++ b/tests/auto/cmake/empty_qmldir/enemy.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef ENEMY_H
#define ENEMY_H
diff --git a/tests/auto/cmake/empty_qmldir/main.cpp b/tests/auto/cmake/empty_qmldir/main.cpp
index e5a2176253..8bb5981bd9 100644
--- a/tests/auto/cmake/empty_qmldir/main.cpp
+++ b/tests/auto/cmake/empty_qmldir/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qobject.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/cmake/qmlimportscanner/main.cpp b/tests/auto/cmake/qmlimportscanner/main.cpp
index 8b6cc65c87..7dc3c46ca1 100644
--- a/tests/auto/cmake/qmlimportscanner/main.cpp
+++ b/tests/auto/cmake/qmlimportscanner/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore>
#include <QtQml>
diff --git a/tests/auto/cmake/qmlquery/CMakeLists.txt b/tests/auto/cmake/qmlquery/CMakeLists.txt
index 5baac4f967..bafabe70f2 100644
--- a/tests/auto/cmake/qmlquery/CMakeLists.txt
+++ b/tests/auto/cmake/qmlquery/CMakeLists.txt
@@ -8,3 +8,4 @@ find_package(Qt6 REQUIRED COMPONENTS Qml)
set(CMAKE_AUTOMOC TRUE)
add_subdirectory(My/Things)
+add_subdirectory(My/OtherThings)
diff --git a/tests/auto/cmake/qmlquery/My/OtherThings/CMakeLists.txt b/tests/auto/cmake/qmlquery/My/OtherThings/CMakeLists.txt
new file mode 100644
index 0000000000..5d2bbc4fdd
--- /dev/null
+++ b/tests/auto/cmake/qmlquery/My/OtherThings/CMakeLists.txt
@@ -0,0 +1,28 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_policy(SET QTP0001 NEW)
+
+function(verify_result keyword expected actual)
+ if(NOT "${actual}" STREQUAL "${expected}")
+ message(SEND_ERROR
+ " Expected ${keyword}: ${expected}\n"
+ " Actual ${keyword}: ${actual}"
+ )
+ endif()
+endfunction()
+
+qt_add_qml_module(MyOtherThings
+ URI My.OtherThings
+ SOURCES
+ test.h test.cpp
+)
+
+qt_query_qml_module(MyOtherThings
+ QML_FILES qml_files2
+ RESOURCES resources2
+)
+
+# empty resources and files
+verify_result(RESOURCES "${resources2}" "")
+verify_result(QML_FILES "${qml_files2}" "")
diff --git a/tests/auto/cmake/qmlquery/My/OtherThings/test.cpp b/tests/auto/cmake/qmlquery/My/OtherThings/test.cpp
new file mode 100644
index 0000000000..b9dde77775
--- /dev/null
+++ b/tests/auto/cmake/qmlquery/My/OtherThings/test.cpp
@@ -0,0 +1,3 @@
+#include "test.h"
+
+Test::Test() {}
diff --git a/tests/auto/cmake/qmlquery/My/OtherThings/test.h b/tests/auto/cmake/qmlquery/My/OtherThings/test.h
new file mode 100644
index 0000000000..93f71766a8
--- /dev/null
+++ b/tests/auto/cmake/qmlquery/My/OtherThings/test.h
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TEST_H
+#define TEST_H
+
+#include <QtQml/qqml.h>
+#include <QObject>
+
+class Test : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ Test();
+};
+
+#endif // TEST_H
diff --git a/tests/auto/cmake/qtquickcompiler/main.cpp b/tests/auto/cmake/qtquickcompiler/main.cpp
index 4cfc0bab2e..6780374dd3 100644
--- a/tests/auto/cmake/qtquickcompiler/main.cpp
+++ b/tests/auto/cmake/qtquickcompiler/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore>
#include <QtQml>
diff --git a/tests/auto/cmake/shared_qml_module/CMakeLists.txt b/tests/auto/cmake/shared_qml_module/CMakeLists.txt
new file mode 100644
index 0000000000..867caa4aad
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.16)
+
+project(scheduler VERSION 0.1 LANGUAGES CXX)
+
+find_package(Qt6 REQUIRED COMPONENTS Qml)
+qt_standard_project_setup(REQUIRES 6.8)
+
+add_custom_target(custom_qmllint_target ALL)
+set(QT_QMLLINT_ALL_TARGET custom_qmllint_target)
+
+add_subdirectory(external)
+add_subdirectory(Scheduler)
+add_subdirectory(SchedulerApp)
+add_subdirectory(tests)
diff --git a/tests/auto/cmake/shared_qml_module/Scheduler/CMakeLists.txt b/tests/auto/cmake/shared_qml_module/Scheduler/CMakeLists.txt
new file mode 100644
index 0000000000..a40688d3a3
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/Scheduler/CMakeLists.txt
@@ -0,0 +1,33 @@
+cmake_minimum_required(VERSION 3.16)
+
+project(scheduler VERSION 0.1 LANGUAGES CXX)
+
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
+
+qt_add_qml_module(scheduler
+ URI Scheduler
+ VERSION 1.0
+ SOURCES
+ task.h
+ task.cpp
+ schedulerglobal.h
+ QML_FILES
+ MainScreen.qml
+)
+
+target_compile_definitions(scheduler
+ PRIVATE
+ SCHEDULER_LIBRARY
+)
+
+target_include_directories(scheduler
+ PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+target_link_libraries(scheduler
+ PRIVATE
+ Qt6::Quick
+)
diff --git a/tests/auto/cmake/shared_qml_module/Scheduler/MainScreen.qml b/tests/auto/cmake/shared_qml_module/Scheduler/MainScreen.qml
new file mode 100644
index 0000000000..6260b4f918
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/Scheduler/MainScreen.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Rectangle {
+ color: "tomato"
+}
diff --git a/tests/auto/cmake/shared_qml_module/Scheduler/schedulerglobal.h b/tests/auto/cmake/shared_qml_module/Scheduler/schedulerglobal.h
new file mode 100644
index 0000000000..cd24bcc8b9
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/Scheduler/schedulerglobal.h
@@ -0,0 +1,15 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef SCHEDULEGLOBAL_H
+#define SCHEDULEGLOBAL_H
+
+#include <QtGlobal>
+
+#if defined(SCHEDULER_LIBRARY)
+#define SCHEDULER_EXPORT Q_DECL_EXPORT
+#else
+#define SCHEDULER_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // SCHEDULEGLOBAL_H
diff --git a/tests/auto/cmake/shared_qml_module/Scheduler/task.cpp b/tests/auto/cmake/shared_qml_module/Scheduler/task.cpp
new file mode 100644
index 0000000000..534a614139
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/Scheduler/task.cpp
@@ -0,0 +1,47 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "task.h"
+
+Task::Task()
+{
+}
+
+Task::Task(const QString &name, int durationInMinutes)
+ : mName(name)
+ , mDurationInMinutes(durationInMinutes)
+{
+}
+
+QString Task::name() const
+{
+ return mName;
+}
+
+void Task::setName(const QString &name)
+{
+ mName = name;
+}
+
+int Task::durationInMinutes() const
+{
+ return mDurationInMinutes;
+}
+
+void Task::setDurationInMinutes(int durationInMinutes)
+{
+ mDurationInMinutes = durationInMinutes;
+}
+
+bool Task::read(const QJsonObject &json)
+{
+ mName = json.value("name").toString();
+ mDurationInMinutes = json.value("durationInMinutes").toInt();
+ return true;
+}
+
+void Task::write(QJsonObject &json) const
+{
+ json["name"] = mName;
+ json["durationInMinutes"] = mDurationInMinutes;
+}
diff --git a/tests/auto/cmake/shared_qml_module/Scheduler/task.h b/tests/auto/cmake/shared_qml_module/Scheduler/task.h
new file mode 100644
index 0000000000..916f939508
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/Scheduler/task.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TASK_H
+#define TASK_H
+
+#include <QObject>
+#include <QJsonObject>
+
+#include "schedulerglobal.h"
+
+class SCHEDULER_EXPORT Task : public QObject
+{
+ Q_OBJECT
+
+public:
+ Task();
+ Task(const QString &name, int durationInMinutes);
+
+ bool read(const QJsonObject &json);
+ void write(QJsonObject &json) const;
+
+ QString name() const;
+ void setName(const QString &name);
+
+ int durationInMinutes() const;
+ void setDurationInMinutes(int durationInMinutes);
+
+private:
+ QString mName;
+ int mDurationInMinutes = 0;
+};
+
+#endif // TASK_H
diff --git a/tests/auto/cmake/shared_qml_module/SchedulerApp/CMakeLists.txt b/tests/auto/cmake/shared_qml_module/SchedulerApp/CMakeLists.txt
new file mode 100644
index 0000000000..fdbb1df701
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/SchedulerApp/CMakeLists.txt
@@ -0,0 +1,44 @@
+cmake_minimum_required(VERSION 3.16)
+
+project(schedulerapp VERSION 0.1 LANGUAGES CXX)
+
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
+
+qt_add_executable(schedulerapp
+ main.cpp
+)
+
+qt_add_qml_module(schedulerapp
+ URI SchedulerApp
+ DEPENDENCIES
+ TARGET scheduler
+ IMPORTS
+ TARGET nested_module
+ VERSION 1.0
+ QML_FILES
+ Main.qml
+)
+
+# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
+# If you are developing for iOS or macOS you should consider setting an
+# explicit, fixed bundle identifier manually though.
+set_target_properties(schedulerapp PROPERTIES
+# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.schedulerapp
+ MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
+ MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
+ MACOSX_BUNDLE TRUE
+ WIN32_EXECUTABLE TRUE
+)
+
+target_link_libraries(schedulerapp
+ PRIVATE Qt6::Quick
+)
+
+include(GNUInstallDirs)
+install(TARGETS schedulerapp
+ BUNDLE DESTINATION .
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+)
diff --git a/tests/auto/cmake/shared_qml_module/SchedulerApp/Main.qml b/tests/auto/cmake/shared_qml_module/SchedulerApp/Main.qml
new file mode 100644
index 0000000000..4dddb35ae8
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/SchedulerApp/Main.qml
@@ -0,0 +1,12 @@
+import QtQuick.Controls
+import Scheduler
+
+ApplicationWindow {
+ width: 640
+ height: 480
+ visible: true
+ title: qsTr("Scheduler")
+
+ MainScreen {}
+ Test {}
+}
diff --git a/tests/auto/cmake/shared_qml_module/SchedulerApp/main.cpp b/tests/auto/cmake/shared_qml_module/SchedulerApp/main.cpp
new file mode 100644
index 0000000000..6422d91bfa
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/SchedulerApp/main.cpp
@@ -0,0 +1,21 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+//
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ qputenv("QT_QUICK_CONTROLS_STYLE", "Material");
+
+ QQmlApplicationEngine engine;
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
+ &app, []() { QCoreApplication::exit(-1); },
+ Qt::QueuedConnection);
+ engine.loadFromModule("SchedulerApp", "Main");
+
+ return app.exec();
+}
diff --git a/tests/auto/cmake/shared_qml_module/external/CMakeLists.txt b/tests/auto/cmake/shared_qml_module/external/CMakeLists.txt
new file mode 100644
index 0000000000..798a23e1a5
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/external/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(nested/module)
diff --git a/tests/auto/cmake/shared_qml_module/external/nested/module/CMakeLists.txt b/tests/auto/cmake/shared_qml_module/external/nested/module/CMakeLists.txt
new file mode 100644
index 0000000000..da75d2333a
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/external/nested/module/CMakeLists.txt
@@ -0,0 +1,15 @@
+
+cmake_minimum_required(VERSION 3.16)
+
+project(scheduler VERSION 0.1 LANGUAGES CXX)
+
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
+
+qt_add_qml_module(nested_module
+ URI nested.module
+ VERSION 1.0
+ QML_FILES
+ Test.qml
+)
diff --git a/tests/auto/cmake/shared_qml_module/external/nested/module/Test.qml b/tests/auto/cmake/shared_qml_module/external/nested/module/Test.qml
new file mode 100644
index 0000000000..3052615aef
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/external/nested/module/Test.qml
@@ -0,0 +1,3 @@
+import QtQuick
+
+Item {}
diff --git a/tests/auto/cmake/shared_qml_module/tests/CMakeLists.txt b/tests/auto/cmake/shared_qml_module/tests/CMakeLists.txt
new file mode 100644
index 0000000000..0653827192
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/tests/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(auto)
diff --git a/tests/auto/cmake/shared_qml_module/tests/auto/CMakeLists.txt b/tests/auto/cmake/shared_qml_module/tests/auto/CMakeLists.txt
new file mode 100644
index 0000000000..269aea0c60
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/tests/auto/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(unit)
diff --git a/tests/auto/cmake/shared_qml_module/tests/auto/unit/CMakeLists.txt b/tests/auto/cmake/shared_qml_module/tests/auto/unit/CMakeLists.txt
new file mode 100644
index 0000000000..9d5f1d9f5e
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/tests/auto/unit/CMakeLists.txt
@@ -0,0 +1,40 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(tst_models LANGUAGES CXX)
+
+enable_testing()
+
+find_package(Qt6 REQUIRED COMPONENTS Gui Test Quick)
+
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+add_executable(tst_models tst_models.cpp)
+add_test(NAME tst_models COMMAND tst_models)
+
+target_link_libraries(tst_models
+ PRIVATE
+ scheduler
+ Qt6::Gui
+ Qt6::Test
+ Qt6::Quick
+)
+
+
+qt_add_qml_module(tst_models
+ URI unittest
+ DEPENDENCIES
+ TARGET scheduler
+)
+
+
+qt_add_executable(tst_models_dummy_helper dummy.cpp)
+qt_add_qml_module(tst_models_dummy_helper
+ URI unimportant
+ DEPENDENCIES
+ TARGET nested_module
+)
diff --git a/tests/auto/cmake/shared_qml_module/tests/auto/unit/dummy.cpp b/tests/auto/cmake/shared_qml_module/tests/auto/unit/dummy.cpp
new file mode 100644
index 0000000000..237c8ce181
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/tests/auto/unit/dummy.cpp
@@ -0,0 +1 @@
+int main() {}
diff --git a/tests/auto/cmake/shared_qml_module/tests/auto/unit/tst_models.cpp b/tests/auto/cmake/shared_qml_module/tests/auto/unit/tst_models.cpp
new file mode 100644
index 0000000000..0a7119fbcc
--- /dev/null
+++ b/tests/auto/cmake/shared_qml_module/tests/auto/unit/tst_models.cpp
@@ -0,0 +1,45 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtTest>
+
+
+class tst_models : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_models();
+ ~tst_models();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void qtconf();
+};
+
+tst_models::tst_models() {}
+
+tst_models::~tst_models() {}
+
+void tst_models::initTestCase() {}
+
+void tst_models::cleanupTestCase() {}
+
+void tst_models::qtconf()
+{
+ auto importPaths = QLibraryInfo::paths(QLibraryInfo::QmlImportsPath);
+ QCOMPARE_GE(importPaths.size(), 2);
+ if (importPaths.at(0).endsWith("shared_qml_module")) {
+ QVERIFY(importPaths.at(1).endsWith("external/nested"));
+ } else if (importPaths.at(0).endsWith("external/nested")) {
+ QVERIFY(importPaths.at(1).endsWith("shared_qml_module"));
+ } else {
+ QFAIL("Expected import paths were not found");
+ }
+}
+
+QTEST_MAIN(tst_models)
+
+#include "tst_models.moc"
diff --git a/tests/auto/cmake/test_common_import_path/CMakeLists.txt b/tests/auto/cmake/test_common_import_path/CMakeLists.txt
index 6071128010..13af36846b 100644
--- a/tests/auto/cmake/test_common_import_path/CMakeLists.txt
+++ b/tests/auto/cmake/test_common_import_path/CMakeLists.txt
@@ -13,6 +13,11 @@ set(CMAKE_AUTOMOC ON)
# Simplify finding the backing targets' DLLs on Windows
if(WIN32)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+else()
+ add_compile_options (
+ -Werror # Treat all warnings as errors
+ -Wshadow # Warn on shadowing
+ )
endif()
add_subdirectory(duck/tick)
diff --git a/tests/auto/cmake/test_common_import_path/main.cpp b/tests/auto/cmake/test_common_import_path/main.cpp
index 5cc81b1573..9430c94f31 100644
--- a/tests/auto/cmake/test_common_import_path/main.cpp
+++ b/tests/auto/cmake/test_common_import_path/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlengine.h>
diff --git a/tests/auto/cmake/test_generate_qmlls_ini/CMakeLists.txt b/tests/auto/cmake/test_generate_qmlls_ini/CMakeLists.txt
new file mode 100644
index 0000000000..f0fa09a66a
--- /dev/null
+++ b/tests/auto/cmake/test_generate_qmlls_ini/CMakeLists.txt
@@ -0,0 +1,43 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.19)
+project(tst_generate_qmlls_ini)
+
+find_package(Qt6 REQUIRED COMPONENTS Core Qml Test)
+
+qt_standard_project_setup()
+
+qt_add_executable(tst_generate_qmlls_ini main.cpp)
+target_link_libraries(tst_generate_qmlls_ini PRIVATE Qt6::Test)
+
+set(QT_QML_GENERATE_QMLLS_INI ON CACHE BOOL "" FORCE)
+
+add_subdirectory(SomeSubfolder)
+add_subdirectory(Dotted)
+
+qt_add_qml_module(tst_generate_qmlls_ini
+ URI MainModule
+ VERSION 1.0
+ NO_RESOURCE_TARGET_PATH
+ SOURCES
+ main.cpp
+ QML_FILES
+ Main.qml
+)
+target_compile_definitions(tst_generate_qmlls_ini
+ PRIVATE
+ "SOURCE_DIRECTORY=u\"${CMAKE_CURRENT_SOURCE_DIR}\"_s"
+ "BUILD_DIRECTORY=u\"${CMAKE_CURRENT_BINARY_DIR}\"_s"
+)
+
+qt_add_qml_module(Module
+ URI Module
+ VERSION 1.0
+ QML_FILES
+ Main.qml
+ OUTPUT_DIRECTORY ./qml/hello/subfolders/Module
+)
+
+# Ensure linting runs when building the default "all" target
+set_target_properties(all_qmllint PROPERTIES EXCLUDE_FROM_ALL FALSE)
diff --git a/tests/auto/cmake/test_generate_qmlls_ini/Dotted/CMakeLists.txt b/tests/auto/cmake/test_generate_qmlls_ini/Dotted/CMakeLists.txt
new file mode 100644
index 0000000000..e3d4518aae
--- /dev/null
+++ b/tests/auto/cmake/test_generate_qmlls_ini/Dotted/CMakeLists.txt
@@ -0,0 +1,4 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+add_subdirectory(Uri)
diff --git a/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/CMakeLists.txt b/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/CMakeLists.txt
new file mode 100644
index 0000000000..a2edbc25ce
--- /dev/null
+++ b/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/CMakeLists.txt
@@ -0,0 +1,9 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_add_qml_module(DottedUri
+ URI Dotted.Uri
+ QML_FILES Main.qml
+)
+
+add_subdirectory(Hello)
diff --git a/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Hello/CMakeLists.txt b/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Hello/CMakeLists.txt
new file mode 100644
index 0000000000..ecceec7e73
--- /dev/null
+++ b/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Hello/CMakeLists.txt
@@ -0,0 +1,4 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+add_subdirectory(World)
diff --git a/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Hello/World/CMakeLists.txt b/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Hello/World/CMakeLists.txt
new file mode 100644
index 0000000000..338674bc93
--- /dev/null
+++ b/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Hello/World/CMakeLists.txt
@@ -0,0 +1,7 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_add_qml_module(DottedUri2
+ URI Dotted.Uri.Hello.World
+ QML_FILES Main.qml
+)
diff --git a/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Hello/World/Main.qml b/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Hello/World/Main.qml
new file mode 100644
index 0000000000..f97cbcf115
--- /dev/null
+++ b/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Hello/World/Main.qml
@@ -0,0 +1,4 @@
+import QtQuick
+
+Item {
+}
diff --git a/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Main.qml b/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Main.qml
new file mode 100644
index 0000000000..f97cbcf115
--- /dev/null
+++ b/tests/auto/cmake/test_generate_qmlls_ini/Dotted/Uri/Main.qml
@@ -0,0 +1,4 @@
+import QtQuick
+
+Item {
+}
diff --git a/tests/auto/cmake/test_generate_qmlls_ini/Main.qml b/tests/auto/cmake/test_generate_qmlls_ini/Main.qml
new file mode 100644
index 0000000000..68c21087cb
--- /dev/null
+++ b/tests/auto/cmake/test_generate_qmlls_ini/Main.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Item {
+
+}
diff --git a/tests/auto/cmake/test_generate_qmlls_ini/SomeSubfolder/CMakeLists.txt b/tests/auto/cmake/test_generate_qmlls_ini/SomeSubfolder/CMakeLists.txt
new file mode 100644
index 0000000000..ae6fb009f8
--- /dev/null
+++ b/tests/auto/cmake/test_generate_qmlls_ini/SomeSubfolder/CMakeLists.txt
@@ -0,0 +1,13 @@
+qt_add_qml_module(ModuleA
+ URI ModuleA
+ VERSION 1.0
+ QML_FILES Main.qml
+ OUTPUT_DIRECTORY ./qml/Some/Sub/Folder/ModuleA
+)
+
+qt_add_qml_module(ModuleB
+ URI ModuleB
+ VERSION 1.0
+ QML_FILES Main.qml
+ OUTPUT_DIRECTORY ./qml/Some/Sub/Folder/ModuleB
+)
diff --git a/tests/auto/cmake/test_generate_qmlls_ini/SomeSubfolder/Main.qml b/tests/auto/cmake/test_generate_qmlls_ini/SomeSubfolder/Main.qml
new file mode 100644
index 0000000000..68c21087cb
--- /dev/null
+++ b/tests/auto/cmake/test_generate_qmlls_ini/SomeSubfolder/Main.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Item {
+
+}
diff --git a/tests/auto/cmake/test_generate_qmlls_ini/main.cpp b/tests/auto/cmake/test_generate_qmlls_ini/main.cpp
new file mode 100644
index 0000000000..2d663cdc23
--- /dev/null
+++ b/tests/auto/cmake/test_generate_qmlls_ini/main.cpp
@@ -0,0 +1,98 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qlibraryinfo.h>
+#include <QtQml/qqml.h>
+#include <QtTest/qtest.h>
+
+class tst_generate_qmlls_ini : public QObject
+{
+ Q_OBJECT
+private slots:
+ void qmllsIniAreCorrect();
+};
+
+using namespace Qt::StringLiterals;
+
+#ifndef SOURCE_DIRECTORY
+# define SOURCE_DIRECTORY u"invalid_source_directory"_s
+#endif
+#ifndef BUILD_DIRECTORY
+# define BUILD_DIRECTORY u"invalid_build_directory"_s
+#endif
+
+void tst_generate_qmlls_ini::qmllsIniAreCorrect()
+{
+ const QString qmllsIniName = u".qmlls.ini"_s;
+ QDir source(SOURCE_DIRECTORY);
+ QDir build(BUILD_DIRECTORY);
+ if (!source.exists())
+ QSKIP(u"Cannot find source directory '%1', skipping test..."_s.arg(SOURCE_DIRECTORY)
+ .toLatin1());
+
+ const QString &docPath = QLibraryInfo::path(QLibraryInfo::DocumentationPath);
+ {
+ auto file = QFile(source.absoluteFilePath(qmllsIniName));
+ QVERIFY(file.exists());
+ QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
+ const auto fileContent = QString::fromUtf8(file.readAll());
+ auto secondFolder = QDir(build.absolutePath().append(u"/qml/hello/subfolders"_s));
+ QVERIFY(secondFolder.exists());
+ QCOMPARE(fileContent,
+ u"[General]\nbuildDir=%1%2%3\nno-cmake-calls=false\ndocDir=%4\n"_s.arg(build.absolutePath(), QDir::listSeparator(),
+ secondFolder.absolutePath(), docPath));
+ }
+
+ {
+ QDir sourceSubfolder = source;
+ QVERIFY(sourceSubfolder.cd(u"SomeSubfolder"_s));
+ QDir buildSubfolder(build.absolutePath().append(u"/SomeSubfolder/qml/Some/Sub/Folder"_s));
+ {
+ auto file = QFile(sourceSubfolder.absoluteFilePath(qmllsIniName));
+ QVERIFY(file.exists());
+ QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
+ const auto fileContent = QString::fromUtf8(file.readAll());
+ QCOMPARE(fileContent,
+ u"[General]\nbuildDir=%1\nno-cmake-calls=false\ndocDir=%2\n"_s.arg(buildSubfolder.absolutePath(), docPath));
+ }
+ }
+
+ {
+ QDir dottedUriSubfolder = source;
+ QVERIFY(dottedUriSubfolder.cd(u"Dotted"_s));
+ QVERIFY(dottedUriSubfolder.cd(u"Uri"_s));
+ {
+ auto file = QFile(dottedUriSubfolder.absoluteFilePath(qmllsIniName));
+ QVERIFY(file.exists());
+ QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
+ const auto fileContent = QString::fromUtf8(file.readAll());
+ QCOMPARE(
+ fileContent,
+ u"[General]\nbuildDir=%1\nno-cmake-calls=false\ndocDir=%2\n"_s.arg(build.absolutePath(), docPath));
+ }
+ }
+ {
+ QDir dottedUriSubfolder = source;
+ QVERIFY(dottedUriSubfolder.cd(u"Dotted"_s));
+ QVERIFY(dottedUriSubfolder.cd(u"Uri"_s));
+ QVERIFY(dottedUriSubfolder.cd(u"Hello"_s));
+ QVERIFY(dottedUriSubfolder.cd(u"World"_s));
+ {
+ auto file = QFile(dottedUriSubfolder.absoluteFilePath(qmllsIniName));
+ QVERIFY(file.exists());
+ QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
+ const auto fileContent = QString::fromUtf8(file.readAll());
+ QCOMPARE(
+ fileContent,
+ u"[General]\nbuildDir=%1\nno-cmake-calls=false\ndocDir=%2\n"_s.arg(build.absolutePath(), docPath));
+ }
+ }
+}
+
+QTEST_MAIN(tst_generate_qmlls_ini)
+
+#include "main.moc"
diff --git a/tests/auto/cmake/test_import_static_shapes_plugin_resources/app.qml b/tests/auto/cmake/test_import_static_shapes_plugin_resources/app.qml
index e470b2e240..20a0d1db78 100644
--- a/tests/auto/cmake/test_import_static_shapes_plugin_resources/app.qml
+++ b/tests/auto/cmake/test_import_static_shapes_plugin_resources/app.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Shapes
diff --git a/tests/auto/cmake/test_import_static_shapes_plugin_resources/tst_main.cpp b/tests/auto/cmake/test_import_static_shapes_plugin_resources/tst_main.cpp
index 4d6265a9e6..5b99d8f22e 100644
--- a/tests/auto/cmake/test_import_static_shapes_plugin_resources/tst_main.cpp
+++ b/tests/auto/cmake/test_import_static_shapes_plugin_resources/tst_main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QtGlobal>
#include <QtCore/QScopeGuard>
diff --git a/tests/auto/cmake/test_internal_singleton/CMakeLists.txt b/tests/auto/cmake/test_internal_singleton/CMakeLists.txt
new file mode 100644
index 0000000000..f1db46a0f9
--- /dev/null
+++ b/tests/auto/cmake/test_internal_singleton/CMakeLists.txt
@@ -0,0 +1,23 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+
+cmake_minimum_required(VERSION 3.19)
+
+project(test_internal_singleton)
+
+find_package(Qt6 REQUIRED COMPONENTS Qml)
+
+qt_standard_project_setup()
+
+set_source_files_properties(Test.qml PROPERTIES
+ QT_QML_SINGLETON_TYPE TRUE
+ QT_QML_INTERNAL_TYPE TRUE
+)
+
+qt_add_qml_module(test_internal_singleton
+ URI Controls
+ VERSION 1.0
+ QML_FILES
+ Test.qml
+)
diff --git a/tests/auto/cmake/test_internal_singleton/Test.qml b/tests/auto/cmake/test_internal_singleton/Test.qml
new file mode 100644
index 0000000000..a2eb03bd4e
--- /dev/null
+++ b/tests/auto/cmake/test_internal_singleton/Test.qml
@@ -0,0 +1,4 @@
+pragma singleton
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/cmake/test_link_qml_module_without_target/Base/Base.cpp b/tests/auto/cmake/test_link_qml_module_without_target/Base/Base.cpp
new file mode 100644
index 0000000000..765c14383f
--- /dev/null
+++ b/tests/auto/cmake/test_link_qml_module_without_target/Base/Base.cpp
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "Base.h"
+#include <QDebug>
+
+Base::Base(QObject *parent) : QObject(parent)
+{
+ qDebug() << Q_FUNC_INFO << "Base library loaded";
+}
diff --git a/tests/auto/cmake/test_link_qml_module_without_target/Base/Base.h b/tests/auto/cmake/test_link_qml_module_without_target/Base/Base.h
new file mode 100644
index 0000000000..9835131a57
--- /dev/null
+++ b/tests/auto/cmake/test_link_qml_module_without_target/Base/Base.h
@@ -0,0 +1,16 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef BASE_H
+#define BASE_H
+
+#include <QObject>
+
+class Base : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Base(QObject *parent = nullptr);
+};
+
+#endif // BASE_H
diff --git a/tests/auto/cmake/test_link_qml_module_without_target/Base/CMakeLists.txt b/tests/auto/cmake/test_link_qml_module_without_target/Base/CMakeLists.txt
new file mode 100644
index 0000000000..1d94c8ea21
--- /dev/null
+++ b/tests/auto/cmake/test_link_qml_module_without_target/Base/CMakeLists.txt
@@ -0,0 +1,13 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_add_library(Base STATIC)
+qt_add_qml_module(Base
+ URI "Base"
+ QML_FILES
+ qml/Red.qml
+ SOURCES
+ Base.cpp
+)
+
+target_link_libraries(Base PRIVATE Qt6::Quick)
diff --git a/tests/auto/cmake/test_link_qml_module_without_target/Base/qml/Red.qml b/tests/auto/cmake/test_link_qml_module_without_target/Base/qml/Red.qml
new file mode 100644
index 0000000000..c75f13d7a8
--- /dev/null
+++ b/tests/auto/cmake/test_link_qml_module_without_target/Base/qml/Red.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Rectangle {
+ width: 320
+ height: 240
+ color: "red"
+}
diff --git a/tests/auto/cmake/test_link_qml_module_without_target/CMakeLists.txt b/tests/auto/cmake/test_link_qml_module_without_target/CMakeLists.txt
new file mode 100644
index 0000000000..86c43aa605
--- /dev/null
+++ b/tests/auto/cmake/test_link_qml_module_without_target/CMakeLists.txt
@@ -0,0 +1,59 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+
+project(test_link_qml_module_without_target)
+
+find_package(Qt6 COMPONENTS REQUIRED
+ Core
+ Test
+ Quick
+ QuickLayouts
+ QuickTestUtilsPrivate
+)
+
+qt_standard_project_setup(REQUIRES 6.5)
+
+add_subdirectory(Base)
+add_subdirectory(Derived)
+
+qt6_add_executable(test_link_qml_module_without_target main.cpp)
+
+target_link_libraries(test_link_qml_module_without_target PRIVATE
+ Qt6::Core
+ Qt6::Test
+ Qt6::QuickPrivate
+ Qt6::QuickTestUtilsPrivate
+)
+
+# Suppress running qmlimportscanner and auto linking of static qml plugins, to ensure we don't
+# automatically link to the project-created qml module object library initializers.
+# Doing that would be at odds with what the test is trying to test.
+set_target_properties(test_link_qml_module_without_target PROPERTIES _QT_QML_PLUGINS_IMPORTED TRUE)
+
+# Because we disable qmlimportscanner auto-linking above, we need to manually link to the Qt
+# provided qml plugins used by the project. Note that we link to the plugins, and not the
+# backing libraries, to ensure we link to the initializer object libraries as well
+# (which are dependencies of the plugin targets).
+if(NOT QT6_IS_SHARED_LIBS_BUILD)
+ target_link_libraries(test_link_qml_module_without_target PRIVATE
+ Qt6::qtquick2plugin
+ Qt6::qquicklayoutsplugin
+ )
+endif()
+
+# Make sure we build the libraries before we link to them.
+add_dependencies(test_link_qml_module_without_target Base Baseplugin Derived Derivedplugin)
+
+# Link against the library files and not the targets, so that we can confirm
+# the ability to manually initialize the qml modules and their resources from inside main.cpp
+# using Q_IMPORT_QML_PLUGIN calls.
+# The order of libraries is important, the plugins need to come before the backing libraries
+# so that linkers like 'Linux ld' don't discard symbols that haven't yet been marked as required.
+target_link_libraries(test_link_qml_module_without_target PRIVATE
+ $<TARGET_FILE:Baseplugin>
+ $<TARGET_FILE:Base>
+ $<TARGET_FILE:Derivedplugin>
+ $<TARGET_FILE:Derived>
+)
diff --git a/tests/auto/cmake/test_link_qml_module_without_target/Derived/CMakeLists.txt b/tests/auto/cmake/test_link_qml_module_without_target/Derived/CMakeLists.txt
new file mode 100644
index 0000000000..08f1155e11
--- /dev/null
+++ b/tests/auto/cmake/test_link_qml_module_without_target/Derived/CMakeLists.txt
@@ -0,0 +1,42 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# See comment below why we do this conditionally.
+set(main_qml "qml/main.qml")
+if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.19")
+ set(qml_extra_files "")
+else()
+ set(qml_extra_files "${main_qml}")
+endif()
+
+qt_add_library(Derived STATIC)
+qt_add_qml_module(Derived
+ URI "Derived"
+ QML_FILES
+ qml/Blue.qml
+ ${qml_extra_files}
+)
+
+# The library has no cpp sources, prevent 'ranlib: has no symbols' warnings
+set_target_properties(Derived PROPERTIES AUTOMOC OFF)
+
+# Add one more qml source in a separate qt_target_qml_sources call,
+# to ensure we correctly create an additional resource for the same
+# qml module and that linking to the qml module plugin + calling
+# Q_IMPORT_PLUGIN will initialize the resource.
+# We can only do it with CMake 3.19+, otherwise we get a configure time
+# error in qt6_target_qml_sources.
+if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.19")
+ qt6_target_qml_sources(Derived
+ QML_FILES
+ ${main_qml}
+ )
+endif()
+
+# Make sure we build the libraries before we link to them.
+add_dependencies(Derived Base Baseplugin)
+
+# Manually link to the library files, to avoid bringing in any
+# object library dependencies.
+target_link_libraries(Derived PRIVATE $<TARGET_FILE:Base>)
+target_link_libraries(Derived PRIVATE $<TARGET_FILE:Baseplugin>)
diff --git a/tests/auto/cmake/test_link_qml_module_without_target/Derived/qml/Blue.qml b/tests/auto/cmake/test_link_qml_module_without_target/Derived/qml/Blue.qml
new file mode 100644
index 0000000000..10668894c2
--- /dev/null
+++ b/tests/auto/cmake/test_link_qml_module_without_target/Derived/qml/Blue.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Rectangle {
+ width: 320
+ height: 240
+ color: "blue"
+}
diff --git a/tests/auto/cmake/test_link_qml_module_without_target/Derived/qml/main.qml b/tests/auto/cmake/test_link_qml_module_without_target/Derived/qml/main.qml
new file mode 100644
index 0000000000..7c797cf2ef
--- /dev/null
+++ b/tests/auto/cmake/test_link_qml_module_without_target/Derived/qml/main.qml
@@ -0,0 +1,23 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Layouts
+import Base
+import Derived
+
+RowLayout {
+ width: 200
+ height: 200
+
+ Red {
+ id: red
+ width: 100
+ height: 100
+ }
+
+ Blue {
+ width: 100
+ height: 100
+ }
+}
diff --git a/tests/auto/cmake/test_link_qml_module_without_target/main.cpp b/tests/auto/cmake/test_link_qml_module_without_target/main.cpp
new file mode 100644
index 0000000000..a0795cb20d
--- /dev/null
+++ b/tests/auto/cmake/test_link_qml_module_without_target/main.cpp
@@ -0,0 +1,43 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtCore/QDirIterator>
+#include <QtGui/QGuiApplication>
+#include <QtTest/QtTest>
+#include <QtQml/QQmlApplicationEngine>
+#include <QtQml/QQmlContext>
+#include <QtQml/qqmlextensionplugin.h>
+#include <QtQuick/QQuickView>
+#include <QtQuickTestUtils/private/viewtestutils_p.h>
+
+// Manually import the qml plugins so that the qml modules and their resources
+// are initialized.
+Q_IMPORT_QML_PLUGIN(BasePlugin)
+Q_IMPORT_QML_PLUGIN(DerivedPlugin)
+
+class TestLinkStaticQmlModule : public QObject
+{
+ Q_OBJECT
+private slots:
+ void canRun();
+};
+
+void TestLinkStaticQmlModule::canRun()
+{
+ // Show all the non-Qt loaded resources.
+ QDirIterator it(":", QDirIterator::Subdirectories);
+ while (it.hasNext()) {
+ const auto path = it.next();
+ if (!path.startsWith(u":/qt-project.org"_qs)) {
+ qDebug() << path;
+ }
+ }
+
+ QQuickView view;
+ QVERIFY(QFile::exists(":/qt/qml/Base/qml/Red.qml"));
+ QVERIFY(QFile::exists(":/qt/qml/Derived/qml/Blue.qml"));
+ QVERIFY(QQuickTest::showView(view, QUrl(u"qrc:/qt/qml/Derived/qml/main.qml"_qs)));
+}
+
+QTEST_MAIN(TestLinkStaticQmlModule)
+#include "main.moc"
diff --git a/tests/auto/cmake/test_qml_app_deployment/Shapes/EllipseShape/ellipseitem.cpp b/tests/auto/cmake/test_qml_app_deployment/Shapes/EllipseShape/ellipseitem.cpp
index fda229bbd8..ea99971d37 100644
--- a/tests/auto/cmake/test_qml_app_deployment/Shapes/EllipseShape/ellipseitem.cpp
+++ b/tests/auto/cmake/test_qml_app_deployment/Shapes/EllipseShape/ellipseitem.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "ellipseitem.h"
#include <QPainter>
diff --git a/tests/auto/cmake/test_qml_app_deployment/Shapes/EllipseShape/ellipseitem.h b/tests/auto/cmake/test_qml_app_deployment/Shapes/EllipseShape/ellipseitem.h
index 88ce76a641..b2aa94b3f3 100644
--- a/tests/auto/cmake/test_qml_app_deployment/Shapes/EllipseShape/ellipseitem.h
+++ b/tests/auto/cmake/test_qml_app_deployment/Shapes/EllipseShape/ellipseitem.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef ELLIPSEITEM_H
#define ELLIPSEITEM_H
diff --git a/tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/FunkyItemQml.qml b/tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/FunkyItemQml.qml
index 48794ff428..99af8c58fd 100644
--- a/tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/FunkyItemQml.qml
+++ b/tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/FunkyItemQml.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Shapes
diff --git a/tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/funkyitem.cpp b/tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/funkyitem.cpp
index b19232e624..3c6b2321e2 100644
--- a/tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/funkyitem.cpp
+++ b/tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/funkyitem.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "funkyitem.h"
#include <QPainter>
diff --git a/tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/funkyitem.h b/tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/funkyitem.h
index ea0338763d..6899cd41e9 100644
--- a/tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/funkyitem.h
+++ b/tests/auto/cmake/test_qml_app_deployment/Shapes/FunkyShape/funkyitem.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef FunkyItem_H
#define FunkyItem_H
diff --git a/tests/auto/cmake/test_qml_app_deployment/main.cpp b/tests/auto/cmake/test_qml_app_deployment/main.cpp
index 00ee6cf8eb..5af318ea14 100644
--- a/tests/auto/cmake/test_qml_app_deployment/main.cpp
+++ b/tests/auto/cmake/test_qml_app_deployment/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/QQmlEngine>
#include <QtQuick/QQuickView>
#include <QtTest/QTest>
diff --git a/tests/auto/cmake/test_qml_app_deployment/main.qml b/tests/auto/cmake/test_qml_app_deployment/main.qml
index 5df35a0592..abac994370 100644
--- a/tests/auto/cmake/test_qml_app_deployment/main.qml
+++ b/tests/auto/cmake/test_qml_app_deployment/main.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import Shapes
diff --git a/tests/auto/cmake/test_static_qml_module/CMakeLists.txt b/tests/auto/cmake/test_static_qml_module/CMakeLists.txt
new file mode 100644
index 0000000000..83d6b74daa
--- /dev/null
+++ b/tests/auto/cmake/test_static_qml_module/CMakeLists.txt
@@ -0,0 +1,38 @@
+cmake_minimum_required(VERSION 3.16)
+project(test_static_qml_module LANGUAGES CXX)
+
+find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick Test)
+qt_standard_project_setup(REQUIRES 6.5)
+
+qt_add_executable(test_static_qml_module
+ main.cpp
+)
+
+qt_add_qml_module(test_static_qml_module
+ URI MyAppUri
+ VERSION 1.0
+ QML_FILES
+ main.qml
+ IMPORT_PATH
+ ${CMAKE_CURRENT_BINARY_DIR}/qml
+)
+
+target_link_libraries(test_static_qml_module
+ PRIVATE
+ Qt::Core
+ Qt::Gui
+ Qt::Qml
+ Qt::Quick
+ Qt::Test
+)
+
+qt_add_qml_module(test_static_qml_module_lib
+ STATIC
+ URI MyUri
+ OUTPUT_DIRECTORY qml/MyUri
+ VERSION 1.0
+ SOURCES
+ MyElement.cpp MyElement.h
+)
+
+qt_import_qml_plugins(test_static_qml_module)
diff --git a/tests/auto/cmake/test_static_qml_module/MyElement.cpp b/tests/auto/cmake/test_static_qml_module/MyElement.cpp
new file mode 100644
index 0000000000..6e3cb8cf2e
--- /dev/null
+++ b/tests/auto/cmake/test_static_qml_module/MyElement.cpp
@@ -0,0 +1,4 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "MyElement.h"
diff --git a/tests/auto/cmake/test_static_qml_module/MyElement.h b/tests/auto/cmake/test_static_qml_module/MyElement.h
new file mode 100644
index 0000000000..118606aa33
--- /dev/null
+++ b/tests/auto/cmake/test_static_qml_module/MyElement.h
@@ -0,0 +1,20 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#pragma once
+
+#include <QObject>
+#include <QtQml>
+
+class MyElement : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(QString someProp MEMBER m_someProp)
+public:
+ MyElement() = default;
+ ~MyElement() = default;
+
+private:
+ QString m_someProp;
+};
diff --git a/tests/auto/cmake/test_static_qml_module/main.cpp b/tests/auto/cmake/test_static_qml_module/main.cpp
new file mode 100644
index 0000000000..87d690004a
--- /dev/null
+++ b/tests/auto/cmake/test_static_qml_module/main.cpp
@@ -0,0 +1,35 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QObject>
+#include <QString>
+#include <QTest>
+#include <QQmlEngine>
+#include <QQmlComponent>
+#include <QQmlExtensionPlugin>
+#include <QUrl>
+
+Q_IMPORT_QML_PLUGIN(MyUriPlugin)
+
+using namespace Qt::StringLiterals;
+
+class TestStaticQmlPlugin : public QObject
+{
+ Q_OBJECT
+private slots:
+ void ElementFromPluginAvailable();
+};
+
+void TestStaticQmlPlugin::ElementFromPluginAvailable()
+{
+ QQmlEngine engine;
+ engine.addImportPath(QStringLiteral(":/qt/qml"));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/MyAppUri/main.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
+
+QTEST_MAIN(TestStaticQmlPlugin)
+
+#include "main.moc"
diff --git a/tests/auto/cmake/test_static_qml_module/main.qml b/tests/auto/cmake/test_static_qml_module/main.qml
new file mode 100644
index 0000000000..29720ebae1
--- /dev/null
+++ b/tests/auto/cmake/test_static_qml_module/main.qml
@@ -0,0 +1,7 @@
+import QtQuick
+import MyUri
+
+MyElement {
+ id: el
+ someProp: "My window title"
+}
diff --git a/tests/auto/cmake/tooling_imports/First/Neighbor.cpp b/tests/auto/cmake/tooling_imports/First/Neighbor.cpp
index d6adca4823..920394cf6e 100644
--- a/tests/auto/cmake/tooling_imports/First/Neighbor.cpp
+++ b/tests/auto/cmake/tooling_imports/First/Neighbor.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "Neighbor.h"
diff --git a/tests/auto/cmake/tooling_imports/First/Neighbor.h b/tests/auto/cmake/tooling_imports/First/Neighbor.h
index e5119bc4c4..05e18d23d7 100644
--- a/tests/auto/cmake/tooling_imports/First/Neighbor.h
+++ b/tests/auto/cmake/tooling_imports/First/Neighbor.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef NEIGHBOR_H
#define NEIGHBOR_H
@@ -15,4 +15,11 @@ public:
Neighbor(QObject *parent = nullptr);
};
+class Absent : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_UNAVAILABLE
+};
+
#endif // NEIGHBOR_H
diff --git a/tests/auto/cmake/tooling_imports/main.cpp b/tests/auto/cmake/tooling_imports/main.cpp
index a1c8dd9daf..92693a832b 100644
--- a/tests/auto/cmake/tooling_imports/main.cpp
+++ b/tests/auto/cmake/tooling_imports/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore>
#include <QtQml>
diff --git a/tests/auto/core/CMakeLists.txt b/tests/auto/core/CMakeLists.txt
index fefa6ff1c1..8a5e039673 100644
--- a/tests/auto/core/CMakeLists.txt
+++ b/tests/auto/core/CMakeLists.txt
@@ -3,4 +3,6 @@
add_subdirectory(qqmlstandardpaths)
add_subdirectory(qqmlsysteminformation)
-add_subdirectory(qqmlsettings)
+if(QT_FEATURE_settings)
+ add_subdirectory(qqmlsettings)
+endif()
diff --git a/tests/auto/core/qqmlsettings/CMakeLists.txt b/tests/auto/core/qqmlsettings/CMakeLists.txt
index 0f8b04bbef..2a61b758dd 100644
--- a/tests/auto/core/qqmlsettings/CMakeLists.txt
+++ b/tests/auto/core/qqmlsettings/CMakeLists.txt
@@ -4,7 +4,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qqmlsettings LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
# Collect test data
@@ -23,6 +23,13 @@ qt_internal_add_test(tst_qqmlsettings
TESTDATA ${test_data}
)
+qt_add_resources(tst_qqmlsettings "test_settings"
+ PREFIX
+ "/"
+ FILES
+ "test_settings.ini"
+)
+
qt_internal_extend_target(tst_qqmlsettings CONDITION ANDROID OR IOS
DEFINES
QT_QMLTEST_DATADIR=":/data"
diff --git a/tests/auto/core/qqmlsettings/data/aliases.qml b/tests/auto/core/qqmlsettings/data/aliases.qml
index 547b4d5c13..de05370804 100644
--- a/tests/auto/core/qqmlsettings/data/aliases.qml
+++ b/tests/auto/core/qqmlsettings/data/aliases.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QtCore
import QtQuick
diff --git a/tests/auto/core/qqmlsettings/data/basic.qml b/tests/auto/core/qqmlsettings/data/basic.qml
index 2c395b56e3..f23284e199 100644
--- a/tests/auto/core/qqmlsettings/data/basic.qml
+++ b/tests/auto/core/qqmlsettings/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QtCore
diff --git a/tests/auto/core/qqmlsettings/data/categories.qml b/tests/auto/core/qqmlsettings/data/categories.qml
index 54cd22a8b1..bac1eb5ebb 100644
--- a/tests/auto/core/qqmlsettings/data/categories.qml
+++ b/tests/auto/core/qqmlsettings/data/categories.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QtCore
diff --git a/tests/auto/core/qqmlsettings/data/cpp-aliases.qml b/tests/auto/core/qqmlsettings/data/cpp-aliases.qml
index 22d7338986..146feb7c80 100644
--- a/tests/auto/core/qqmlsettings/data/cpp-aliases.qml
+++ b/tests/auto/core/qqmlsettings/data/cpp-aliases.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QtCore
import QtQuick
diff --git a/tests/auto/core/qqmlsettings/data/resources.qml b/tests/auto/core/qqmlsettings/data/resources.qml
new file mode 100644
index 0000000000..84cf89fbf2
--- /dev/null
+++ b/tests/auto/core/qqmlsettings/data/resources.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+import QtQml
+import QtCore
+
+Settings {
+ category: "test"
+ location: "qrc:/test_settings.ini"
+ property string text
+}
diff --git a/tests/auto/core/qqmlsettings/data/siblings.qml b/tests/auto/core/qqmlsettings/data/siblings.qml
index e483623d82..f26312ec67 100644
--- a/tests/auto/core/qqmlsettings/data/siblings.qml
+++ b/tests/auto/core/qqmlsettings/data/siblings.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QtCore
import QtQuick
diff --git a/tests/auto/core/qqmlsettings/data/types.qml b/tests/auto/core/qqmlsettings/data/types.qml
index 3f38594323..990a908d02 100644
--- a/tests/auto/core/qqmlsettings/data/types.qml
+++ b/tests/auto/core/qqmlsettings/data/types.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QtCore
import QtQuick
diff --git a/tests/auto/core/qqmlsettings/test_settings.ini b/tests/auto/core/qqmlsettings/test_settings.ini
new file mode 100644
index 0000000000..7fc7334438
--- /dev/null
+++ b/tests/auto/core/qqmlsettings/test_settings.ini
@@ -0,0 +1,3 @@
+# ini file in resources
+[test]
+text=from resource
diff --git a/tests/auto/core/qqmlsettings/tst_qqmlsettings.cpp b/tests/auto/core/qqmlsettings/tst_qqmlsettings.cpp
index 1b6ab3f68b..236ce4b3e9 100644
--- a/tests/auto/core/qqmlsettings/tst_qqmlsettings.cpp
+++ b/tests/auto/core/qqmlsettings/tst_qqmlsettings.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtCore/QCoreApplication>
@@ -33,6 +33,7 @@ private slots:
void siblings();
void initial();
void noApplicationIdentifiersSet();
+ void fromResources();
};
// ### Replace keyValueMap("foo", "bar") with QVariantMap({{"foo", "bar"}})
@@ -493,6 +494,17 @@ void tst_QQmlSettings::noApplicationIdentifiersSet()
QVERIFY(!settings.value("success").toBool());
}
+void tst_QQmlSettings::fromResources()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("resources.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
+
+ QCOMPARE(root->property("text").toString(), QLatin1String("from resource"));
+}
+
QTEST_MAIN(tst_QQmlSettings)
#include "tst_qqmlsettings.moc"
diff --git a/tests/auto/core/qqmlstandardpaths/CMakeLists.txt b/tests/auto/core/qqmlstandardpaths/CMakeLists.txt
index 6078c10755..2ae79515a4 100644
--- a/tests/auto/core/qqmlstandardpaths/CMakeLists.txt
+++ b/tests/auto/core/qqmlstandardpaths/CMakeLists.txt
@@ -4,7 +4,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qqmlstandardpaths LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
# Collect test data
diff --git a/tests/auto/core/qqmlstandardpaths/data/tst_standardpaths.qml b/tests/auto/core/qqmlstandardpaths/data/tst_standardpaths.qml
index afc196e92a..5b88d424ca 100644
--- a/tests/auto/core/qqmlstandardpaths/data/tst_standardpaths.qml
+++ b/tests/auto/core/qqmlstandardpaths/data/tst_standardpaths.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QtCore
diff --git a/tests/auto/core/qqmlstandardpaths/tst_qqmlstandardpaths.cpp b/tests/auto/core/qqmlstandardpaths/tst_qqmlstandardpaths.cpp
index b8f7878b41..352ce21f8b 100644
--- a/tests/auto/core/qqmlstandardpaths/tst_qqmlstandardpaths.cpp
+++ b/tests/auto/core/qqmlstandardpaths/tst_qqmlstandardpaths.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QQmlEngine>
#include <QQmlComponent>
@@ -113,9 +113,7 @@ void tst_qqmlstandardpaths::standardLocations()
#endif
QVERIFY2(!path.isEmpty(), qPrintable(QString::fromLatin1(
"Path for %1 received from QStandardPaths::standardLocations is empty").arg(locationName)));
- QUrl url = QUrl(path);
- if (url.scheme().isEmpty())
- url = QUrl::fromLocalFile(path);
+ QUrl url = QUrl::fromLocalFile(path);
QVERIFY(!url.isEmpty());
QVERIFY(url.isValid());
standardLocationUrls.append(url);
diff --git a/tests/auto/core/qqmlsysteminformation/CMakeLists.txt b/tests/auto/core/qqmlsysteminformation/CMakeLists.txt
index c69564634e..b9ccebf1e7 100644
--- a/tests/auto/core/qqmlsysteminformation/CMakeLists.txt
+++ b/tests/auto/core/qqmlsysteminformation/CMakeLists.txt
@@ -4,7 +4,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qqmlsysteminformation LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
# Collect test data
diff --git a/tests/auto/core/qqmlsysteminformation/data/tst_systeminformation.qml b/tests/auto/core/qqmlsysteminformation/data/tst_systeminformation.qml
index afc53dde54..ced47ff328 100644
--- a/tests/auto/core/qqmlsysteminformation/data/tst_systeminformation.qml
+++ b/tests/auto/core/qqmlsysteminformation/data/tst_systeminformation.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QtCore
diff --git a/tests/auto/core/qqmlsysteminformation/tst_qqmlsysteminformation.cpp b/tests/auto/core/qqmlsysteminformation/tst_qqmlsysteminformation.cpp
index 5a743dee0c..2f9374f5b1 100644
--- a/tests/auto/core/qqmlsysteminformation/tst_qqmlsysteminformation.cpp
+++ b/tests/auto/core/qqmlsysteminformation/tst_qqmlsysteminformation.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QQmlEngine>
#include <QQmlComponent>
diff --git a/tests/auto/guiapplauncher/examples.txt b/tests/auto/guiapplauncher/examples.txt
index 40c41e59fb..88ff180a17 100644
--- a/tests/auto/guiapplauncher/examples.txt
+++ b/tests/auto/guiapplauncher/examples.txt
@@ -2,11 +2,8 @@
"quick/models/stringlistmodel Example", "examples/quick/models/stringlistmodel", "stringlistmodel", 0, -1
"quick/models/objectlistmodel Example", "examples/quick/models/objectlistmodel", "objectlistmodel", 0, -1
"quick/models/abstractitemmodel Example", "examples/quick/models/abstractitemmodel", "abstractitemmodel", 0, -1
-"quick/righttoleft Example", "examples/quick/righttoleft", "righttoleft", 0, -1
-"quick/externaldraganddrop Example", "examples/quick/externaldraganddrop", "externaldraganddrop", 0, -1
"quick/customitems/maskedmousearea Example", "examples/quick/customitems/maskedmousearea", "maskedmousearea", 0, -1
"quick/imageelements Example", "examples/quick/imageelements", "imageelements", 0, -1
-"quick/threading Example", "examples/quick/threading", "threading", 0, -1
"quick/scenegraph/openglunderqml Example", "examples/quick/scenegraph/openglunderqml", "openglunderqml", 0, -1
"quick/scenegraph/threadedanimation Example", "examples/quick/scenegraph/threadedanimation", "threadedanimation", 0, -1
"quick/scenegraph/twotextureproviders Example", "examples/quick/scenegraph/twotextureproviders", "twotextureproviders", 0, -1
@@ -30,23 +27,11 @@
"quick/positioners Example", "examples/quick/positioners", "positioners", 0, -1
"quick/shadereffects Example", "examples/quick/shadereffects", "shadereffects", 0, -1
"quick/mousearea Example", "examples/quick/mousearea", "mousearea", 0, -1
-"quick/touchinteraction Example", "examples/quick/touchinteraction", "touchinteraction", 0, -1
"quick/canvas Example", "examples/quick/canvas", "canvas", 0, -1
"quick/text Example", "examples/quick/text", "text", 0, -1
"quick/quickwidgets/qquickviewcomparison Example", "examples/quick/quickwidgets/qquickviewcomparison", "qquickviewcomparison", 0, -1
"quick/quickwidgets/quickwidget Example", "examples/quick/quickwidgets/quickwidget", "quickwidget", 0, -1
"qml/shell Example", "examples/qml/shell", "shell", 10, -1
-"qml/referenceexamples/extended Example", "examples/qml/referenceexamples/extended", "extended", 0, -1
-"qml/referenceexamples/binding Example", "examples/qml/referenceexamples/binding", "binding", 10, -1
-"qml/referenceexamples/adding Example", "examples/qml/referenceexamples/adding", "adding", 10, -1
-"qml/referenceexamples/attached Example", "examples/qml/referenceexamples/attached", "attached", 10, -1
-"qml/referenceexamples/default Example", "examples/qml/referenceexamples/default", "default", 10, -1
-"qml/referenceexamples/signal Example", "examples/qml/referenceexamples/signal", "signal", 10, -1
-"qml/referenceexamples/coercion Example", "examples/qml/referenceexamples/coercion", "coercion", 10, -1
-"qml/referenceexamples/grouped Example", "examples/qml/referenceexamples/grouped", "grouped", 10, -1
-"qml/referenceexamples/valuesource Example", "examples/qml/referenceexamples/valuesource", "valuesource", 10, -1
-"qml/referenceexamples/properties Example", "examples/qml/referenceexamples/properties", "properties", 10, -1
-"qml/referenceexamples/methods Example", "examples/qml/referenceexamples/methods", "methods", 10, -1
"qml/networkaccessmanagerfactory Example", "examples/qml/networkaccessmanagerfactory", "networkaccessmanagerfactory", 10, -1
"qml/xmlhttprequest Example", "examples/qml/xmlhttprequest", "xmlhttprequest", 0, -1
"qmltest/qmltest Example", "examples/qmltest/qmltest", "tst_qmltestexample", 10, -1
diff --git a/tests/auto/particles/qquickage/CMakeLists.txt b/tests/auto/particles/qquickage/CMakeLists.txt
index 0873359a5c..0f941dd421 100644
--- a/tests/auto/particles/qquickage/CMakeLists.txt
+++ b/tests/auto/particles/qquickage/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickage Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickage LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickage/data/jump.qml b/tests/auto/particles/qquickage/data/jump.qml
index f8bb2c6c99..ebef068da8 100644
--- a/tests/auto/particles/qquickage/data/jump.qml
+++ b/tests/auto/particles/qquickage/data/jump.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickage/data/kill.qml b/tests/auto/particles/qquickage/data/kill.qml
index 7d7a5c47bd..64e71feb08 100644
--- a/tests/auto/particles/qquickage/data/kill.qml
+++ b/tests/auto/particles/qquickage/data/kill.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickage/data/onceoff.qml b/tests/auto/particles/qquickage/data/onceoff.qml
index bed3e53dad..7233fb819a 100644
--- a/tests/auto/particles/qquickage/data/onceoff.qml
+++ b/tests/auto/particles/qquickage/data/onceoff.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickage/data/sustained.qml b/tests/auto/particles/qquickage/data/sustained.qml
index 0f6a6261eb..45cc46a642 100644
--- a/tests/auto/particles/qquickage/data/sustained.qml
+++ b/tests/auto/particles/qquickage/data/sustained.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickage/tst_qquickage.cpp b/tests/auto/particles/qquickage/tst_qquickage.cpp
index 21b79d8921..cff4ab9cba 100644
--- a/tests/auto/particles/qquickage/tst_qquickage.cpp
+++ b/tests/auto/particles/qquickage/tst_qquickage.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickangleddirection/CMakeLists.txt b/tests/auto/particles/qquickangleddirection/CMakeLists.txt
index c2914f20ff..5895974c75 100644
--- a/tests/auto/particles/qquickangleddirection/CMakeLists.txt
+++ b/tests/auto/particles/qquickangleddirection/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickangleddirection Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickangleddirection LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickangleddirection/data/basic.qml b/tests/auto/particles/qquickangleddirection/data/basic.qml
index 1c284b2c73..b763bc65d1 100644
--- a/tests/auto/particles/qquickangleddirection/data/basic.qml
+++ b/tests/auto/particles/qquickangleddirection/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickangleddirection/tst_qquickangleddirection.cpp b/tests/auto/particles/qquickangleddirection/tst_qquickangleddirection.cpp
index 8b2cb417cb..ff38dabc76 100644
--- a/tests/auto/particles/qquickangleddirection/tst_qquickangleddirection.cpp
+++ b/tests/auto/particles/qquickangleddirection/tst_qquickangleddirection.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <qmath.h>
diff --git a/tests/auto/particles/qquickcumulativedirection/CMakeLists.txt b/tests/auto/particles/qquickcumulativedirection/CMakeLists.txt
index 564baccdfd..784d557ae6 100644
--- a/tests/auto/particles/qquickcumulativedirection/CMakeLists.txt
+++ b/tests/auto/particles/qquickcumulativedirection/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickcumulativedirection Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickcumulativedirection LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickcumulativedirection/data/basic.qml b/tests/auto/particles/qquickcumulativedirection/data/basic.qml
index 9cb93ba24e..49538b99c0 100644
--- a/tests/auto/particles/qquickcumulativedirection/data/basic.qml
+++ b/tests/auto/particles/qquickcumulativedirection/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickcumulativedirection/tst_qquickcumulativedirection.cpp b/tests/auto/particles/qquickcumulativedirection/tst_qquickcumulativedirection.cpp
index df427600c5..d510a44eb2 100644
--- a/tests/auto/particles/qquickcumulativedirection/tst_qquickcumulativedirection.cpp
+++ b/tests/auto/particles/qquickcumulativedirection/tst_qquickcumulativedirection.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickcustomaffector/CMakeLists.txt b/tests/auto/particles/qquickcustomaffector/CMakeLists.txt
index 85aabd4c3a..34dc258c8b 100644
--- a/tests/auto/particles/qquickcustomaffector/CMakeLists.txt
+++ b/tests/auto/particles/qquickcustomaffector/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickcustomaffector Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickcustomaffector LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickcustomaffector/data/affectedSignal.qml b/tests/auto/particles/qquickcustomaffector/data/affectedSignal.qml
index b5216be5b2..965479f305 100644
--- a/tests/auto/particles/qquickcustomaffector/data/affectedSignal.qml
+++ b/tests/auto/particles/qquickcustomaffector/data/affectedSignal.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickcustomaffector/data/basic.qml b/tests/auto/particles/qquickcustomaffector/data/basic.qml
index 879e7d3ecf..4748fc45d2 100644
--- a/tests/auto/particles/qquickcustomaffector/data/basic.qml
+++ b/tests/auto/particles/qquickcustomaffector/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickcustomaffector/data/move.qml b/tests/auto/particles/qquickcustomaffector/data/move.qml
index 33671d52e2..078bff7814 100644
--- a/tests/auto/particles/qquickcustomaffector/data/move.qml
+++ b/tests/auto/particles/qquickcustomaffector/data/move.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickcustomaffector/tst_qquickcustomaffector.cpp b/tests/auto/particles/qquickcustomaffector/tst_qquickcustomaffector.cpp
index e10885cf84..b4468905f1 100644
--- a/tests/auto/particles/qquickcustomaffector/tst_qquickcustomaffector.cpp
+++ b/tests/auto/particles/qquickcustomaffector/tst_qquickcustomaffector.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickellipseextruder/CMakeLists.txt b/tests/auto/particles/qquickellipseextruder/CMakeLists.txt
index 2930acfd4d..634fd49a63 100644
--- a/tests/auto/particles/qquickellipseextruder/CMakeLists.txt
+++ b/tests/auto/particles/qquickellipseextruder/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickellipseextruder Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickellipseextruder LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickellipseextruder/data/basic.qml b/tests/auto/particles/qquickellipseextruder/data/basic.qml
index b3d904b382..d03d3175e3 100644
--- a/tests/auto/particles/qquickellipseextruder/data/basic.qml
+++ b/tests/auto/particles/qquickellipseextruder/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickellipseextruder/tst_qquickellipseextruder.cpp b/tests/auto/particles/qquickellipseextruder/tst_qquickellipseextruder.cpp
index 98139e8271..78875ac62b 100644
--- a/tests/auto/particles/qquickellipseextruder/tst_qquickellipseextruder.cpp
+++ b/tests/auto/particles/qquickellipseextruder/tst_qquickellipseextruder.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qmath.h>
#include <QtTest/QtTest>
diff --git a/tests/auto/particles/qquickfriction/CMakeLists.txt b/tests/auto/particles/qquickfriction/CMakeLists.txt
index 7a9b1daaa8..ade4635990 100644
--- a/tests/auto/particles/qquickfriction/CMakeLists.txt
+++ b/tests/auto/particles/qquickfriction/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickfriction Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickfriction LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickfriction/data/basic.qml b/tests/auto/particles/qquickfriction/data/basic.qml
index d5911535b0..da6f779d22 100644
--- a/tests/auto/particles/qquickfriction/data/basic.qml
+++ b/tests/auto/particles/qquickfriction/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickfriction/data/threshold.qml b/tests/auto/particles/qquickfriction/data/threshold.qml
index 64b9bc7117..2d836671ad 100644
--- a/tests/auto/particles/qquickfriction/data/threshold.qml
+++ b/tests/auto/particles/qquickfriction/data/threshold.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickfriction/tst_qquickfriction.cpp b/tests/auto/particles/qquickfriction/tst_qquickfriction.cpp
index edc3770f85..579e68355b 100644
--- a/tests/auto/particles/qquickfriction/tst_qquickfriction.cpp
+++ b/tests/auto/particles/qquickfriction/tst_qquickfriction.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickgravity/CMakeLists.txt b/tests/auto/particles/qquickgravity/CMakeLists.txt
index 69a5484b24..d4b97b6516 100644
--- a/tests/auto/particles/qquickgravity/CMakeLists.txt
+++ b/tests/auto/particles/qquickgravity/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickgravity Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickgravity LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickgravity/data/basic.qml b/tests/auto/particles/qquickgravity/data/basic.qml
index dd5e1c90d3..6cc950eea0 100644
--- a/tests/auto/particles/qquickgravity/data/basic.qml
+++ b/tests/auto/particles/qquickgravity/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickgravity/tst_qquickgravity.cpp b/tests/auto/particles/qquickgravity/tst_qquickgravity.cpp
index d95bb19827..8590308bc5 100644
--- a/tests/auto/particles/qquickgravity/tst_qquickgravity.cpp
+++ b/tests/auto/particles/qquickgravity/tst_qquickgravity.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickgroupgoal/CMakeLists.txt b/tests/auto/particles/qquickgroupgoal/CMakeLists.txt
index 6b123882ec..84bbac6bf4 100644
--- a/tests/auto/particles/qquickgroupgoal/CMakeLists.txt
+++ b/tests/auto/particles/qquickgroupgoal/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickgroupgoal Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickgroupgoal LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickgroupgoal/data/basic.qml b/tests/auto/particles/qquickgroupgoal/data/basic.qml
index 737bf275dc..8bf5d8e995 100644
--- a/tests/auto/particles/qquickgroupgoal/data/basic.qml
+++ b/tests/auto/particles/qquickgroupgoal/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickgroupgoal/tst_qquickgroupgoal.cpp b/tests/auto/particles/qquickgroupgoal/tst_qquickgroupgoal.cpp
index 87a0c9f21e..2e18e4e9a5 100644
--- a/tests/auto/particles/qquickgroupgoal/tst_qquickgroupgoal.cpp
+++ b/tests/auto/particles/qquickgroupgoal/tst_qquickgroupgoal.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickimageparticle/CMakeLists.txt b/tests/auto/particles/qquickimageparticle/CMakeLists.txt
index 49e1a74227..f104aefce7 100644
--- a/tests/auto/particles/qquickimageparticle/CMakeLists.txt
+++ b/tests/auto/particles/qquickimageparticle/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickimageparticle Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickimageparticle LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickimageparticle/data/basic.qml b/tests/auto/particles/qquickimageparticle/data/basic.qml
index 32a8483975..0b97fb3f3d 100644
--- a/tests/auto/particles/qquickimageparticle/data/basic.qml
+++ b/tests/auto/particles/qquickimageparticle/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickimageparticle/data/colorVariance.qml b/tests/auto/particles/qquickimageparticle/data/colorVariance.qml
index 572577715f..18bafdb8f3 100644
--- a/tests/auto/particles/qquickimageparticle/data/colorVariance.qml
+++ b/tests/auto/particles/qquickimageparticle/data/colorVariance.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickimageparticle/data/colored.qml b/tests/auto/particles/qquickimageparticle/data/colored.qml
index 6707a50f16..cb4baa1974 100644
--- a/tests/auto/particles/qquickimageparticle/data/colored.qml
+++ b/tests/auto/particles/qquickimageparticle/data/colored.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickimageparticle/data/deformed.qml b/tests/auto/particles/qquickimageparticle/data/deformed.qml
index 487d1366a5..d54874f1e9 100644
--- a/tests/auto/particles/qquickimageparticle/data/deformed.qml
+++ b/tests/auto/particles/qquickimageparticle/data/deformed.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickimageparticle/data/sprite.qml b/tests/auto/particles/qquickimageparticle/data/sprite.qml
index 2906dae813..0f9b10b898 100644
--- a/tests/auto/particles/qquickimageparticle/data/sprite.qml
+++ b/tests/auto/particles/qquickimageparticle/data/sprite.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickimageparticle/data/tabled.qml b/tests/auto/particles/qquickimageparticle/data/tabled.qml
index 2dcf0f5c54..ce91ca15b6 100644
--- a/tests/auto/particles/qquickimageparticle/data/tabled.qml
+++ b/tests/auto/particles/qquickimageparticle/data/tabled.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickimageparticle/tst_qquickimageparticle.cpp b/tests/auto/particles/qquickimageparticle/tst_qquickimageparticle.cpp
index f4b6794cc2..b9bce20a24 100644
--- a/tests/auto/particles/qquickimageparticle/tst_qquickimageparticle.cpp
+++ b/tests/auto/particles/qquickimageparticle/tst_qquickimageparticle.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtCore/QtMath>
diff --git a/tests/auto/particles/qquickitemparticle/CMakeLists.txt b/tests/auto/particles/qquickitemparticle/CMakeLists.txt
index 8e7283c51e..835a98ae08 100644
--- a/tests/auto/particles/qquickitemparticle/CMakeLists.txt
+++ b/tests/auto/particles/qquickitemparticle/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickitemparticle Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickitemparticle LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickitemparticle/data/basic.qml b/tests/auto/particles/qquickitemparticle/data/basic.qml
index 2f25de4a19..60923589e8 100644
--- a/tests/auto/particles/qquickitemparticle/data/basic.qml
+++ b/tests/auto/particles/qquickitemparticle/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickitemparticle/data/loader.qml b/tests/auto/particles/qquickitemparticle/data/loader.qml
index f6a90d6a24..8711bd4868 100644
--- a/tests/auto/particles/qquickitemparticle/data/loader.qml
+++ b/tests/auto/particles/qquickitemparticle/data/loader.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickitemparticle/data/managed.qml b/tests/auto/particles/qquickitemparticle/data/managed.qml
index 00405bd519..a1f34fe213 100644
--- a/tests/auto/particles/qquickitemparticle/data/managed.qml
+++ b/tests/auto/particles/qquickitemparticle/data/managed.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickitemparticle/data/takeGive.qml b/tests/auto/particles/qquickitemparticle/data/takeGive.qml
index 1b6b42d0cb..f1bfd8355f 100644
--- a/tests/auto/particles/qquickitemparticle/data/takeGive.qml
+++ b/tests/auto/particles/qquickitemparticle/data/takeGive.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickitemparticle/data/unmanaged.qml b/tests/auto/particles/qquickitemparticle/data/unmanaged.qml
index 63b0943574..082b6e22ca 100644
--- a/tests/auto/particles/qquickitemparticle/data/unmanaged.qml
+++ b/tests/auto/particles/qquickitemparticle/data/unmanaged.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickitemparticle/tst_qquickitemparticle.cpp b/tests/auto/particles/qquickitemparticle/tst_qquickitemparticle.cpp
index 8e82f91a92..4620c26574 100644
--- a/tests/auto/particles/qquickitemparticle/tst_qquickitemparticle.cpp
+++ b/tests/auto/particles/qquickitemparticle/tst_qquickitemparticle.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquicklineextruder/CMakeLists.txt b/tests/auto/particles/qquicklineextruder/CMakeLists.txt
index 8391a07fc1..b48478e4f1 100644
--- a/tests/auto/particles/qquicklineextruder/CMakeLists.txt
+++ b/tests/auto/particles/qquicklineextruder/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicklineextruder Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicklineextruder LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquicklineextruder/data/basic.qml b/tests/auto/particles/qquicklineextruder/data/basic.qml
index 83e1ead18a..9ed70921c9 100644
--- a/tests/auto/particles/qquicklineextruder/data/basic.qml
+++ b/tests/auto/particles/qquicklineextruder/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquicklineextruder/tst_qquicklineextruder.cpp b/tests/auto/particles/qquicklineextruder/tst_qquicklineextruder.cpp
index 98e300d90a..3d65886b3a 100644
--- a/tests/auto/particles/qquicklineextruder/tst_qquicklineextruder.cpp
+++ b/tests/auto/particles/qquicklineextruder/tst_qquicklineextruder.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickmaskextruder/CMakeLists.txt b/tests/auto/particles/qquickmaskextruder/CMakeLists.txt
index b876532612..6b447af949 100644
--- a/tests/auto/particles/qquickmaskextruder/CMakeLists.txt
+++ b/tests/auto/particles/qquickmaskextruder/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickmaskextruder Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickmaskextruder LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickmaskextruder/data/basic.qml b/tests/auto/particles/qquickmaskextruder/data/basic.qml
index a2d6520f66..6ec6f2ac23 100644
--- a/tests/auto/particles/qquickmaskextruder/data/basic.qml
+++ b/tests/auto/particles/qquickmaskextruder/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickmaskextruder/tst_qquickmaskextruder.cpp b/tests/auto/particles/qquickmaskextruder/tst_qquickmaskextruder.cpp
index 6c4bb44a07..a5fafd384c 100644
--- a/tests/auto/particles/qquickmaskextruder/tst_qquickmaskextruder.cpp
+++ b/tests/auto/particles/qquickmaskextruder/tst_qquickmaskextruder.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickparticlegroup/CMakeLists.txt b/tests/auto/particles/qquickparticlegroup/CMakeLists.txt
index 6837565c08..a7bc94fb9e 100644
--- a/tests/auto/particles/qquickparticlegroup/CMakeLists.txt
+++ b/tests/auto/particles/qquickparticlegroup/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickparticlegroup Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickparticlegroup LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickparticlegroup/data/basic.qml b/tests/auto/particles/qquickparticlegroup/data/basic.qml
index 76eb1bc546..8eda2235bb 100644
--- a/tests/auto/particles/qquickparticlegroup/data/basic.qml
+++ b/tests/auto/particles/qquickparticlegroup/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickparticlegroup/tst_qquickparticlegroup.cpp b/tests/auto/particles/qquickparticlegroup/tst_qquickparticlegroup.cpp
index 75c2e72c34..bc1183a24c 100644
--- a/tests/auto/particles/qquickparticlegroup/tst_qquickparticlegroup.cpp
+++ b/tests/auto/particles/qquickparticlegroup/tst_qquickparticlegroup.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickparticlesystem/CMakeLists.txt b/tests/auto/particles/qquickparticlesystem/CMakeLists.txt
index 0a55dd1b4a..b3f826e0d9 100644
--- a/tests/auto/particles/qquickparticlesystem/CMakeLists.txt
+++ b/tests/auto/particles/qquickparticlesystem/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickparticlesystem Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickparticlesystem LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickparticlesystem/data/basic.qml b/tests/auto/particles/qquickparticlesystem/data/basic.qml
index 32a8483975..0b97fb3f3d 100644
--- a/tests/auto/particles/qquickparticlesystem/data/basic.qml
+++ b/tests/auto/particles/qquickparticlesystem/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickparticlesystem/data/crashaffectors.qml b/tests/auto/particles/qquickparticlesystem/data/crashaffectors.qml
index ae483686a5..96a4038378 100644
--- a/tests/auto/particles/qquickparticlesystem/data/crashaffectors.qml
+++ b/tests/auto/particles/qquickparticlesystem/data/crashaffectors.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 reMarkable A/S
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.6
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickparticlesystem/tst_qquickparticlesystem.cpp b/tests/auto/particles/qquickparticlesystem/tst_qquickparticlesystem.cpp
index cadeac66f5..51404e5321 100644
--- a/tests/auto/particles/qquickparticlesystem/tst_qquickparticlesystem.cpp
+++ b/tests/auto/particles/qquickparticlesystem/tst_qquickparticlesystem.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickpointattractor/CMakeLists.txt b/tests/auto/particles/qquickpointattractor/CMakeLists.txt
index f8a9d83d4e..ccf2babc78 100644
--- a/tests/auto/particles/qquickpointattractor/CMakeLists.txt
+++ b/tests/auto/particles/qquickpointattractor/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickpointattractor Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpointattractor LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickpointattractor/data/basic.qml b/tests/auto/particles/qquickpointattractor/data/basic.qml
index 71682a7f1d..41d1a1c8ab 100644
--- a/tests/auto/particles/qquickpointattractor/data/basic.qml
+++ b/tests/auto/particles/qquickpointattractor/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickpointattractor/tst_qquickpointattractor.cpp b/tests/auto/particles/qquickpointattractor/tst_qquickpointattractor.cpp
index e5822c1b88..2afaff634a 100644
--- a/tests/auto/particles/qquickpointattractor/tst_qquickpointattractor.cpp
+++ b/tests/auto/particles/qquickpointattractor/tst_qquickpointattractor.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickpointdirection/CMakeLists.txt b/tests/auto/particles/qquickpointdirection/CMakeLists.txt
index e394058ef3..fdaa071077 100644
--- a/tests/auto/particles/qquickpointdirection/CMakeLists.txt
+++ b/tests/auto/particles/qquickpointdirection/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickpointdirection Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpointdirection LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickpointdirection/data/basic.qml b/tests/auto/particles/qquickpointdirection/data/basic.qml
index 6a18ced3fe..70d38bcead 100644
--- a/tests/auto/particles/qquickpointdirection/data/basic.qml
+++ b/tests/auto/particles/qquickpointdirection/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickpointdirection/tst_qquickpointdirection.cpp b/tests/auto/particles/qquickpointdirection/tst_qquickpointdirection.cpp
index 8c39bad812..ba4949f095 100644
--- a/tests/auto/particles/qquickpointdirection/tst_qquickpointdirection.cpp
+++ b/tests/auto/particles/qquickpointdirection/tst_qquickpointdirection.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickrectangleextruder/CMakeLists.txt b/tests/auto/particles/qquickrectangleextruder/CMakeLists.txt
index 70c192dd77..79edac296a 100644
--- a/tests/auto/particles/qquickrectangleextruder/CMakeLists.txt
+++ b/tests/auto/particles/qquickrectangleextruder/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickrectangleextruder Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickrectangleextruder LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickrectangleextruder/data/basic.qml b/tests/auto/particles/qquickrectangleextruder/data/basic.qml
index 5aae3e5378..a3e2eab7f7 100644
--- a/tests/auto/particles/qquickrectangleextruder/data/basic.qml
+++ b/tests/auto/particles/qquickrectangleextruder/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickrectangleextruder/tst_qquickrectangleextruder.cpp b/tests/auto/particles/qquickrectangleextruder/tst_qquickrectangleextruder.cpp
index 99cbeba35a..1486ff9e1c 100644
--- a/tests/auto/particles/qquickrectangleextruder/tst_qquickrectangleextruder.cpp
+++ b/tests/auto/particles/qquickrectangleextruder/tst_qquickrectangleextruder.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickspritegoal/CMakeLists.txt b/tests/auto/particles/qquickspritegoal/CMakeLists.txt
index 9f3b7b4520..c85662b889 100644
--- a/tests/auto/particles/qquickspritegoal/CMakeLists.txt
+++ b/tests/auto/particles/qquickspritegoal/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickspritegoal Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickspritegoal LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickspritegoal/data/basic.qml b/tests/auto/particles/qquickspritegoal/data/basic.qml
index 89e9675e6a..5984007104 100644
--- a/tests/auto/particles/qquickspritegoal/data/basic.qml
+++ b/tests/auto/particles/qquickspritegoal/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickspritegoal/tst_qquickspritegoal.cpp b/tests/auto/particles/qquickspritegoal/tst_qquickspritegoal.cpp
index 4dd965aff7..327c443c9c 100644
--- a/tests/auto/particles/qquickspritegoal/tst_qquickspritegoal.cpp
+++ b/tests/auto/particles/qquickspritegoal/tst_qquickspritegoal.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquicktargetdirection/CMakeLists.txt b/tests/auto/particles/qquicktargetdirection/CMakeLists.txt
index 3febb4efc9..4c2b68d01b 100644
--- a/tests/auto/particles/qquicktargetdirection/CMakeLists.txt
+++ b/tests/auto/particles/qquicktargetdirection/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicktargetdirection Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicktargetdirection LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquicktargetdirection/data/basic.qml b/tests/auto/particles/qquicktargetdirection/data/basic.qml
index 59e848841d..6ff5ba5e56 100644
--- a/tests/auto/particles/qquicktargetdirection/data/basic.qml
+++ b/tests/auto/particles/qquicktargetdirection/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquicktargetdirection/tst_qquicktargetdirection.cpp b/tests/auto/particles/qquicktargetdirection/tst_qquicktargetdirection.cpp
index 6e695440a0..61777f4836 100644
--- a/tests/auto/particles/qquicktargetdirection/tst_qquicktargetdirection.cpp
+++ b/tests/auto/particles/qquicktargetdirection/tst_qquicktargetdirection.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquicktrailemitter/CMakeLists.txt b/tests/auto/particles/qquicktrailemitter/CMakeLists.txt
index 74f2026635..05fc453274 100644
--- a/tests/auto/particles/qquicktrailemitter/CMakeLists.txt
+++ b/tests/auto/particles/qquicktrailemitter/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicktrailemitter Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicktrailemitter LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquicktrailemitter/data/basic.qml b/tests/auto/particles/qquicktrailemitter/data/basic.qml
index d6324a2a77..f44008f5ef 100644
--- a/tests/auto/particles/qquicktrailemitter/data/basic.qml
+++ b/tests/auto/particles/qquicktrailemitter/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquicktrailemitter/tst_qquicktrailemitter.cpp b/tests/auto/particles/qquicktrailemitter/tst_qquicktrailemitter.cpp
index 230c666c8d..7233e57224 100644
--- a/tests/auto/particles/qquicktrailemitter/tst_qquicktrailemitter.cpp
+++ b/tests/auto/particles/qquicktrailemitter/tst_qquicktrailemitter.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickturbulence/CMakeLists.txt b/tests/auto/particles/qquickturbulence/CMakeLists.txt
index 411c7c20dd..13a971cb71 100644
--- a/tests/auto/particles/qquickturbulence/CMakeLists.txt
+++ b/tests/auto/particles/qquickturbulence/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickturbulence Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickturbulence LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickturbulence/data/basic.qml b/tests/auto/particles/qquickturbulence/data/basic.qml
index 3eae9c807d..3b387fcc00 100644
--- a/tests/auto/particles/qquickturbulence/data/basic.qml
+++ b/tests/auto/particles/qquickturbulence/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickturbulence/tst_qquickturbulence.cpp b/tests/auto/particles/qquickturbulence/tst_qquickturbulence.cpp
index d90dd17199..99340993cf 100644
--- a/tests/auto/particles/qquickturbulence/tst_qquickturbulence.cpp
+++ b/tests/auto/particles/qquickturbulence/tst_qquickturbulence.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/qquickwander/CMakeLists.txt b/tests/auto/particles/qquickwander/CMakeLists.txt
index e4d2f9488c..f1ef2737a9 100644
--- a/tests/auto/particles/qquickwander/CMakeLists.txt
+++ b/tests/auto/particles/qquickwander/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickwander Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickwander LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/particles/qquickwander/data/basic.qml b/tests/auto/particles/qquickwander/data/basic.qml
index 8d95cce1ad..8fd94d0e44 100644
--- a/tests/auto/particles/qquickwander/data/basic.qml
+++ b/tests/auto/particles/qquickwander/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/particles/qquickwander/tst_qquickwander.cpp b/tests/auto/particles/qquickwander/tst_qquickwander.cpp
index 71a8ee1f97..3099323919 100644
--- a/tests/auto/particles/qquickwander/tst_qquickwander.cpp
+++ b/tests/auto/particles/qquickwander/tst_qquickwander.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include "../shared/particlestestsshared.h"
diff --git a/tests/auto/particles/shared/particlestestsshared.h b/tests/auto/particles/shared/particlestestsshared.h
index 22c7cd70df..36b27fab64 100644
--- a/tests/auto/particles/shared/particlestestsshared.h
+++ b/tests/auto/particles/shared/particlestestsshared.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef PARTICLES_TESTS_SHARED
#define PARTICLES_TESTS_SHARED
diff --git a/tests/auto/qml/CMakeLists.txt b/tests/auto/qml/CMakeLists.txt
index 77663f350d..6b81f4c616 100644
--- a/tests/auto/qml/CMakeLists.txt
+++ b/tests/auto/qml/CMakeLists.txt
@@ -17,8 +17,9 @@ add_subdirectory(qjsonbinding)
add_subdirectory(qqmlfile)
if(NOT INTEGRITY)
- # The INTEGRITY linker tends to crash on tst_qqmlfileselector
+ # The INTEGRITY linker tends to crash on tst_qqmlfileselector and tst_qml_common
add_subdirectory(qqmlfileselector)
+ add_subdirectory(common)
endif()
# Limit set of tests to run for static Qt builds.
@@ -33,7 +34,9 @@ add_subdirectory(qqmlerror)
add_subdirectory(qqmlincubator)
add_subdirectory(qqmlinfo)
add_subdirectory(qqmllistreference)
-add_subdirectory(qqmllocale)
+if(QT_FEATURE_qml_locale)
+ add_subdirectory(qqmllocale)
+endif()
add_subdirectory(qqmlmetaobject)
if(NOT ANDROID) # QTBUG-100003
add_subdirectory(qqmlmoduleplugin)
@@ -45,7 +48,9 @@ add_subdirectory(qqmlpromise)
add_subdirectory(qtqmlmodules)
add_subdirectory(qquickfolderlistmodel)
add_subdirectory(qqmlapplicationengine)
-add_subdirectory(qqmlsettings)
+if(QT_FEATURE_settings)
+ add_subdirectory(qqmlsettings)
+endif()
if(NOT INTEGRITY)
# There's no mounted filesystem on INTEGRITY therefore skipping qmldiskcache
@@ -55,7 +60,7 @@ endif()
add_subdirectory(qqmlmetatype)
if(TARGET Qt::Quick)
add_subdirectory(qmltc_manual)
- # QML Type Compiler tests cannot be run on webOS due to missing support for multiple
+ # QML type compiler tests cannot be run on webOS due to missing support for multiple
# consecutive window creation from a single QtWayland client
if(NOT WEBOS)
add_subdirectory(qmltc)
@@ -76,6 +81,7 @@ if(TARGET Qt::Widgets)
add_subdirectory(qjsengine)
add_subdirectory(qjsvalue)
add_subdirectory(qjsmanagedvalue)
+ add_subdirectory(qwidgetsinqml)
endif()
if(QT_FEATURE_process AND QT_FEATURE_qml_debug)
add_subdirectory(debugger)
@@ -140,9 +146,14 @@ if(QT_FEATURE_private_tests)
add_subdirectory(qqmltreemodeltotablemodel)
add_subdirectory(qv4assembler)
add_subdirectory(qv4mm)
+ add_subdirectory(qv4estable)
add_subdirectory(qv4identifiertable)
add_subdirectory(qv4regexp)
- if(QT_FEATURE_process AND NOT QNX)
+ add_subdirectory(qv4urlobject)
+ if(QT_FEATURE_process AND NOT QNX AND NOT
+ (ANDROID AND CLANG AND
+ CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "14.0.0" AND
+ CMAKE_CXX_COMPILER_VERSION VERSION_LESS "15.0.0"))
add_subdirectory(ecmascripttests)
endif()
add_subdirectory(bindingdependencyapi)
diff --git a/tests/auto/qml/animation/qabstractanimationjob/CMakeLists.txt b/tests/auto/qml/animation/qabstractanimationjob/CMakeLists.txt
index 03099ef616..9e6ba7fcb6 100644
--- a/tests/auto/qml/animation/qabstractanimationjob/CMakeLists.txt
+++ b/tests/auto/qml/animation/qabstractanimationjob/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qabstractanimationjob Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qabstractanimationjob LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qabstractanimationjob
SOURCES
tst_qabstractanimationjob.cpp
diff --git a/tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp b/tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp
index e2e5e59e95..40eb8a6910 100644
--- a/tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp
+++ b/tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/private/qabstractanimationjob_p.h>
@@ -53,8 +53,7 @@ void tst_QAbstractAnimationJob::construction()
void tst_QAbstractAnimationJob::destruction()
{
- TestableQAbstractAnimation *anim = new TestableQAbstractAnimation;
- delete anim;
+ std::unique_ptr<TestableQAbstractAnimation> anim = std::make_unique<TestableQAbstractAnimation>();
}
void tst_QAbstractAnimationJob::currentLoop()
diff --git a/tests/auto/qml/animation/qanimationgroupjob/CMakeLists.txt b/tests/auto/qml/animation/qanimationgroupjob/CMakeLists.txt
index 286bdeed4a..db46ef71dc 100644
--- a/tests/auto/qml/animation/qanimationgroupjob/CMakeLists.txt
+++ b/tests/auto/qml/animation/qanimationgroupjob/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qanimationgroupjob Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qanimationgroupjob LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qanimationgroupjob
SOURCES
tst_qanimationgroupjob.cpp
diff --git a/tests/auto/qml/animation/qanimationgroupjob/tst_qanimationgroupjob.cpp b/tests/auto/qml/animation/qanimationgroupjob/tst_qanimationgroupjob.cpp
index cac9581803..a3fe188b65 100644
--- a/tests/auto/qml/animation/qanimationgroupjob/tst_qanimationgroupjob.cpp
+++ b/tests/auto/qml/animation/qanimationgroupjob/tst_qanimationgroupjob.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -236,7 +236,7 @@ void tst_QAnimationGroupJob::addChildTwice()
{
QAbstractAnimationJob *subGroup;
QAbstractAnimationJob *subGroup2;
- auto *parent = new QSequentialAnimationGroupJob();
+ auto parent = std::make_unique<QSequentialAnimationGroupJob>();
subGroup = new QAbstractAnimationJob;
parent->appendAnimation(subGroup);
@@ -266,7 +266,6 @@ void tst_QAnimationGroupJob::addChildTwice()
QCOMPARE(parent->children()->first(), subGroup2);
QCOMPARE(parent->children()->last(), subGroup);
- delete parent;
}
QTEST_MAIN(tst_QAnimationGroupJob)
diff --git a/tests/auto/qml/animation/qparallelanimationgroupjob/CMakeLists.txt b/tests/auto/qml/animation/qparallelanimationgroupjob/CMakeLists.txt
index 74e3b3fed4..0a275aaaa1 100644
--- a/tests/auto/qml/animation/qparallelanimationgroupjob/CMakeLists.txt
+++ b/tests/auto/qml/animation/qparallelanimationgroupjob/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qparallelanimationgroupjob Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qparallelanimationgroupjob LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qparallelanimationgroupjob
SOURCES
tst_qparallelanimationgroupjob.cpp
diff --git a/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp b/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp
index a11ae75033..91c47586c1 100644
--- a/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp
+++ b/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -395,8 +395,8 @@ void tst_QParallelAnimationGroupJob::deleteChildrenWithRunningGroup()
// test if children can be activated when their group is stopped
QParallelAnimationGroupJob group;
- TestAnimation *anim1 = new TestAnimation(200);
- group.appendAnimation(anim1);
+ std::unique_ptr<TestAnimation> anim1 = std::make_unique<TestAnimation>(200);
+ group.appendAnimation(anim1.get());
QCOMPARE(group.duration(), anim1->duration());
@@ -406,7 +406,7 @@ void tst_QParallelAnimationGroupJob::deleteChildrenWithRunningGroup()
QTRY_VERIFY(group.currentLoopTime() > 0);
- delete anim1;
+ anim1.reset();
QVERIFY(group.children()->isEmpty());
QCOMPARE(group.duration(), 0);
QCOMPARE(group.state(), QAnimationGroupJob::Stopped);
@@ -793,34 +793,34 @@ void tst_QParallelAnimationGroupJob::addAndRemoveDuration()
{
QParallelAnimationGroupJob group;
QCOMPARE(group.duration(), 0);
- TestAnimation *test = new TestAnimation(250); // 0, duration = 250;
- group.appendAnimation(test);
+ std::unique_ptr<TestAnimation> test = std::make_unique<TestAnimation>(250); // 0, duration = 250;
+ group.appendAnimation(test.get());
QCOMPARE(test->group(), static_cast<QAnimationGroupJob*>(&group));
QCOMPARE(test->duration(), 250);
QCOMPARE(group.duration(), 250);
- TestAnimation *test2 = new TestAnimation(750); // 1
- group.appendAnimation(test2);
+ std::unique_ptr<TestAnimation> test2 = std::make_unique<TestAnimation>(750); // 1
+ group.appendAnimation(test2.get());
QCOMPARE(test2->group(), static_cast<QAnimationGroupJob*>(&group));
QCOMPARE(group.duration(), 750);
- TestAnimation *test3 = new TestAnimation(500); // 2
- group.appendAnimation(test3);
+ std::unique_ptr<TestAnimation> test3 = std::make_unique<TestAnimation>(500); // 2
+ group.appendAnimation(test3.get());
QCOMPARE(test3->group(), static_cast<QAnimationGroupJob*>(&group));
QCOMPARE(group.duration(), 750);
- group.removeAnimation(test2); // remove the one with duration = 750
- delete test2;
+ group.removeAnimation(test2.get()); // remove the one with duration = 750
+ test2.reset();
QCOMPARE(group.duration(), 500);
- group.removeAnimation(test3); // remove the one with duration = 500
- delete test3;
+ group.removeAnimation(test3.get()); // remove the one with duration = 500
+ test3.reset();
QCOMPARE(group.duration(), 250);
- group.removeAnimation(test); // remove the last one (with duration = 250)
+ group.removeAnimation(test.get()); // remove the last one (with duration = 250)
QCOMPARE(test->group(), static_cast<QAnimationGroupJob*>(nullptr));
QCOMPARE(group.duration(), 0);
- delete test;
+ test.reset();
}
void tst_QParallelAnimationGroupJob::pauseResume()
@@ -878,16 +878,16 @@ void tst_QParallelAnimationGroupJob::pauseResume()
void tst_QParallelAnimationGroupJob::crashWhenRemovingUncontrolledAnimation()
{
QParallelAnimationGroupJob group;
- TestAnimation *anim = new TestAnimation;
+ std::unique_ptr<TestAnimation> anim = std::make_unique<TestAnimation>();
anim->setLoopCount(-1);
- TestAnimation *anim2 = new TestAnimation;
+ std::unique_ptr<TestAnimation> anim2 = std::make_unique<TestAnimation>();
anim2->setLoopCount(-1);
- group.appendAnimation(anim);
- group.appendAnimation(anim2);
+ group.appendAnimation(anim.get());
+ group.appendAnimation(anim2.get());
group.start();
- delete anim;
+ anim.reset();
// it would crash here because the internals of the group would still have a reference to anim
- delete anim2;
+ anim2.reset();
}
void tst_QParallelAnimationGroupJob::uncontrolledWithLoops()
diff --git a/tests/auto/qml/animation/qpauseanimationjob/CMakeLists.txt b/tests/auto/qml/animation/qpauseanimationjob/CMakeLists.txt
index 5f67083ea4..2dc9e42f90 100644
--- a/tests/auto/qml/animation/qpauseanimationjob/CMakeLists.txt
+++ b/tests/auto/qml/animation/qpauseanimationjob/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qpauseanimationjob Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qpauseanimationjob LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qpauseanimationjob
SOURCES
tst_qpauseanimationjob.cpp
diff --git a/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp b/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp
index db433af8c6..c658f590c9 100644
--- a/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp
+++ b/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
diff --git a/tests/auto/qml/animation/qsequentialanimationgroupjob/CMakeLists.txt b/tests/auto/qml/animation/qsequentialanimationgroupjob/CMakeLists.txt
index e9a680ace5..fa7ad06a03 100644
--- a/tests/auto/qml/animation/qsequentialanimationgroupjob/CMakeLists.txt
+++ b/tests/auto/qml/animation/qsequentialanimationgroupjob/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qsequentialanimationgroupjob Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qsequentialanimationgroupjob LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qsequentialanimationgroupjob
SOURCES
tst_qsequentialanimationgroupjob.cpp
diff --git a/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp b/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp
index cc67df420c..71aa2240ff 100644
--- a/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp
+++ b/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQml/private/qsequentialanimationgroupjob_p.h>
@@ -110,7 +110,7 @@ public:
{
states << newState;
if (beEvil) {
- delete job->group();
+ delete job->group(); //manual delete intentional
groupDeleted = true;
}
}
@@ -1090,8 +1090,8 @@ void tst_QSequentialAnimationGroupJob::deleteChildrenWithRunningGroup()
// test if children can be activated when their group is stopped
QSequentialAnimationGroupJob group;
- TestAnimation *anim1 = new TestAnimation(200);
- group.appendAnimation(anim1);
+ std::unique_ptr<TestAnimation> anim1 = std::make_unique<TestAnimation>(200);
+ group.appendAnimation(anim1.get());
QCOMPARE(group.duration(), anim1->duration());
@@ -1102,7 +1102,7 @@ void tst_QSequentialAnimationGroupJob::deleteChildrenWithRunningGroup()
QTest::qWait(100);
QTRY_VERIFY(group.currentLoopTime() > 0);
- delete anim1;
+ anim1.reset();
QVERIFY(group.children()->isEmpty());
QCOMPARE(group.duration(), 0);
QCOMPARE(group.state(), QAnimationGroupJob::Stopped);
diff --git a/tests/auto/qml/bindingdependencyapi/CMakeLists.txt b/tests/auto/qml/bindingdependencyapi/CMakeLists.txt
index e8ab157548..febc0bcfdd 100644
--- a/tests/auto/qml/bindingdependencyapi/CMakeLists.txt
+++ b/tests/auto/qml/bindingdependencyapi/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_bindingdependencyapi Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_bindingdependencyapi LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp b/tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp
index 5fbf28b15b..6b1f4e1622 100644
--- a/tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp
+++ b/tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -104,12 +104,12 @@ void tst_bindingdependencyapi::testSingleDep()
QQmlEngine engine;
QQmlComponent c(&engine);
c.setData(code, QUrl());
- QObject *rect = c.create();
+ std::unique_ptr<QObject> rect { c.create() };
QTest::qWait(10);
- QVERIFY(rect != nullptr);
+ QVERIFY(rect.get() != nullptr);
QObject *text = rect->findChildren<QQuickText *>().front();
- QObject *referencedObject = rect->objectName() == referencedObjectName ? rect : rect->findChild<QObject *>(referencedObjectName);
+ QObject *referencedObject = rect->objectName() == referencedObjectName ? rect.get() : rect->findChild<QObject *>(referencedObjectName);
auto data = QQmlData::get(text);
QVERIFY(data);
@@ -125,8 +125,6 @@ void tst_bindingdependencyapi::testSingleDep()
QCOMPARE(dependency.property().name(), "labelText");
QCOMPARE(dependency.read().toString(), QStringLiteral("Hello world!"));
QCOMPARE(dependency, QQmlProperty(referencedObject, "labelText"));
-
- delete rect;
}
bool tst_bindingdependencyapi::findProperties(const QVector<QQmlProperty> &properties, QObject *obj, const QString &propertyName, const QVariant &value)
@@ -183,12 +181,12 @@ void tst_bindingdependencyapi::testManyDeps()
QQmlEngine engine;
QQmlComponent c(&engine);
c.setData(code, QUrl());
- QObject *rect = c.create();
+ std::unique_ptr<QObject> rect { c.create() };
if (c.isError()) {
qWarning() << c.errorString();
}
QTest::qWait(100);
- QVERIFY(rect != nullptr);
+ QVERIFY(rect.get() != nullptr);
QObject *text = rect->findChildren<QQuickText *>().front();
QObject *configObj = rect->findChild<QObject *>("config");
@@ -201,11 +199,9 @@ void tst_bindingdependencyapi::testManyDeps()
auto dependencies = binding->dependencies();
QCOMPARE(dependencies.size(), 3);
- QVERIFY(findProperties(dependencies, rect, "name", "world"));
+ QVERIFY(findProperties(dependencies, rect.get(), "name", "world"));
QVERIFY(findProperties(dependencies, text, "greeting", "Hello"));
QVERIFY(findProperties(dependencies, configObj, "helloWorldTemplate", "%1 %2!"));
-
- delete rect;
}
void tst_bindingdependencyapi::testConditionalDependencies_data()
@@ -263,12 +259,12 @@ void tst_bindingdependencyapi::testConditionalDependencies()
QQmlEngine engine;
QQmlComponent c(&engine);
c.setData(code, QUrl());
- QObject *rect = c.create();
+ std::unique_ptr<QObject> rect { c.create() };
QTest::qWait(10);
- QVERIFY(rect != nullptr);
+ QVERIFY(rect.get() != nullptr);
QObject *text = rect->findChildren<QQuickText *>().front();
- QObject *referencedObject = rect->objectName() == referencedObjectName ? rect : rect->findChild<QObject *>(referencedObjectName);
+ QObject *referencedObject = rect->objectName() == referencedObjectName ? rect.get() : rect->findChild<QObject *>(referencedObjectName);
auto data = QQmlData::get(text);
QVERIFY(data);
@@ -290,8 +286,6 @@ void tst_bindingdependencyapi::testConditionalDependencies()
dependencies = binding->dependencies();
QCOMPARE(dependencies.size(), 1);
QVERIFY(findProperties(dependencies, referencedObject, "haveDep", false));
-
- delete rect;
}
void tst_bindingdependencyapi::testBindingLoop()
@@ -306,12 +300,12 @@ void tst_bindingdependencyapi::testBindingLoop()
"text: labelText\n"
"}\n"
"}"), QUrl());
- QObject *rect = c.create();
+ std::unique_ptr<QObject> rect { c.create() };
if (c.isError()) {
qWarning() << c.errorString();
}
QTest::qWait(100);
- QVERIFY(rect != nullptr);
+ QVERIFY(rect.get() != nullptr);
QObject *text = rect->findChildren<QQuickText *>().front();
auto data = QQmlData::get(text);
@@ -324,10 +318,8 @@ void tst_bindingdependencyapi::testBindingLoop()
QCOMPARE(dependencies.size(), 1);
auto dependency = dependencies.front();
QVERIFY(dependency.isValid());
- QCOMPARE(quintptr(dependency.object()), quintptr(rect));
+ QCOMPARE(quintptr(dependency.object()), quintptr(rect.get()));
QCOMPARE(dependency.property().name(), "labelText");
-
- delete rect;
}
void tst_bindingdependencyapi::testQproperty()
diff --git a/tests/auto/qml/common/CMakeLists.txt b/tests/auto/qml/common/CMakeLists.txt
new file mode 100644
index 0000000000..4b7714a11d
--- /dev/null
+++ b/tests/auto/qml/common/CMakeLists.txt
@@ -0,0 +1,11 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_policy(SET QTP0001 NEW)
+
+qt_internal_add_test(tst_qml_common
+ SOURCES
+ tst_qml_common.cpp tst_qml_common.h
+ LIBRARIES
+ Qt::QmlPrivate
+)
diff --git a/tests/auto/qml/common/tst_qml_common.cpp b/tests/auto/qml/common/tst_qml_common.cpp
new file mode 100644
index 0000000000..e9baae5d53
--- /dev/null
+++ b/tests/auto/qml/common/tst_qml_common.cpp
@@ -0,0 +1,168 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "tst_qml_common.h"
+
+using namespace Qt::StringLiterals;
+
+void tst_qml_common::tst_propertyNameToChangedSignalName_data()
+{
+ QTest::addColumn<QString>("property");
+ QTest::addColumn<QString>("expected");
+
+ QTest::addRow("normalProperty") << u"helloWorld"_s << u"helloWorldChanged"_s;
+ QTest::addRow("changedProperty") << u"changed"_s << u"changedChanged"_s;
+ QTest::addRow("chängedProperty") << u"chänged"_s << u"chängedChanged"_s;
+}
+void tst_qml_common::tst_propertyNameToChangedSignalName()
+{
+ QFETCH(QString, property);
+ QFETCH(QString, expected);
+
+ QVERIFY(QQmlSignalNames::isChangedSignalName(expected));
+ QCOMPARE(QQmlSignalNames::propertyNameToChangedSignalName(property), expected);
+ QCOMPARE(QQmlSignalNames::changedSignalNameToPropertyName(expected).value(), property);
+}
+
+void tst_qml_common::tst_propertyNameToChangedHandlerName_data()
+{
+ QTest::addColumn<QString>("property");
+ QTest::addColumn<QString>("expected");
+
+ QTest::addRow("normalProperty") << u"helloWorld"_s << u"onHelloWorldChanged"_s;
+ QTest::addRow("changedProperty") << u"changed"_s << u"onChangedChanged"_s;
+ QTest::addRow("chängedProperty") << u"chänged"_s << u"onChängedChanged"_s;
+ QTest::addRow("äProperty") << u"ä"_s << u"onÄChanged"_s;
+ QTest::addRow("_Property") << u"_"_s << u"on_Changed"_s;
+ QTest::addRow("___123aProperty") << u"___123a"_s << u"on___123AChanged"_s;
+ QTest::addRow("___123Property") << u"___123"_s << u"on___123Changed"_s;
+ QTest::addRow("AProperty") << u"A"_s << u"onAChanged"_s;
+ QTest::addRow("_Property") << u"_"_s << u"on_Changed"_s;
+ QTest::addRow("$Property") << u"$"_s << u"on$Changed"_s;
+}
+void tst_qml_common::tst_propertyNameToChangedHandlerName()
+{
+ QFETCH(QString, property);
+ QFETCH(QString, expected);
+
+ QVERIFY(QQmlSignalNames::isChangedHandlerName(expected));
+ QCOMPARE(QQmlSignalNames::propertyNameToChangedHandlerName(property), expected);
+ auto reverse = QQmlSignalNames::changedHandlerNameToPropertyName(expected);
+ QVERIFY(reverse);
+ QEXPECT_FAIL("AProperty",
+ "Cannot distinguish between property names starting with upper case"
+ " from properties starting with a lower case letter.",
+ Continue);
+ QCOMPARE(reverse.value(), property);
+}
+
+void tst_qml_common::tst_signalNameToHandlerName_data()
+{
+ QTest::addColumn<QString>("signalName");
+ QTest::addColumn<QString>("expected");
+
+ QTest::addRow("normalProperty") << u"helloWorld"_s << u"onHelloWorld"_s;
+ QTest::addRow("changedProperty") << u"changed"_s << u"onChanged"_s;
+ QTest::addRow("chängedProperty") << u"chänged"_s << u"onChänged"_s;
+ QTest::addRow("äProperty") << u"ä"_s << u"onÄ"_s;
+ QTest::addRow("_Property") << u"_"_s << u"on_"_s;
+ QTest::addRow("___123aProperty") << u"___123a"_s << u"on___123A"_s;
+ QTest::addRow("___123Property") << u"___123"_s << u"on___123"_s;
+ QTest::addRow("AProperty") << u"A"_s << u"onA"_s;
+ QTest::addRow("_Property") << u"_"_s << u"on_"_s;
+ QTest::addRow("$Property") << u"$"_s << u"on$"_s;
+}
+
+void tst_qml_common::tst_signalNameToHandlerName()
+{
+ QFETCH(QString, signalName);
+ QFETCH(QString, expected);
+
+ QVERIFY(QQmlSignalNames::isHandlerName(expected));
+ QCOMPARE(QQmlSignalNames::signalNameToHandlerName(signalName), expected);
+
+ auto result = QQmlSignalNames::handlerNameToSignalName(expected);
+ QVERIFY(result.has_value());
+
+ QEXPECT_FAIL("AProperty",
+ "Cannot distinguish between signal names starting with upper case"
+ " from signal names starting with a lower case letter.",
+ Continue);
+
+ QCOMPARE(result.value(), signalName);
+}
+
+void tst_qml_common::tst_changedSignalNameToPropertyName_data()
+{
+ // only test when it should return nothing, see also tst_propertyNameToChangedSignalName.
+ QTest::addColumn<QString>("changedSignalName");
+
+ QTest::addRow("normalProperty") << u"helloWorld"_s;
+ QTest::addRow("Changed") << u"Changed"_s;
+ QTest::addRow("empty") << u""_s;
+}
+
+void tst_qml_common::tst_changedSignalNameToPropertyName()
+{
+ QFETCH(QString, changedSignalName);
+
+ QVERIFY(!QQmlSignalNames::changedSignalNameToPropertyName(changedSignalName).has_value());
+}
+
+void tst_qml_common::tst_changedHandlerNameToPropertyName_data()
+{
+ // only test when it should return nothing, see also tst_propertyNameToChangedHandler.
+ QTest::addColumn<QString>("changedHandler");
+
+ QTest::addRow("normalProperty") << u"helloWorld"_s;
+ QTest::addRow("Changed") << u"Changed"_s;
+ QTest::addRow("empty") << u""_s;
+ QTest::addRow("empty2") << u"onChanged"_s;
+ QTest::addRow("on") << u"on"_s;
+}
+void tst_qml_common::tst_changedHandlerNameToPropertyName()
+{
+ QFETCH(QString, changedHandler);
+
+ QVERIFY(!QQmlSignalNames::changedHandlerNameToPropertyName(changedHandler).has_value());
+}
+
+void tst_qml_common::tst_handlerNameToSignalName_data()
+{
+ // only test when it should return nothing, see also tst_signalNameToHandlerName.
+ QTest::addColumn<QString>("handler");
+
+ QTest::addRow("normalProperty") << u"helloWorld"_s;
+ QTest::addRow("Changed") << u"Changed"_s;
+ QTest::addRow("empty") << u""_s;
+ QTest::addRow("on") << u"on"_s;
+}
+void tst_qml_common::tst_handlerNameToSignalName()
+{
+ QFETCH(QString, handler);
+
+ QVERIFY(!QQmlSignalNames::handlerNameToSignalName(handler).has_value());
+}
+
+void tst_qml_common::tst_isChangedHandlerName_data()
+{
+ QTest::addColumn<QString>("name");
+ QTest::addColumn<bool>("expected");
+
+ QTest::addRow("normalProperty") << u"helloWorld"_s << false;
+ QTest::addRow("Changed") << u"Changed"_s << false;
+ QTest::addRow("empty") << u""_s << false;
+ QTest::addRow("empty2") << u"onChanged"_s << false;
+ QTest::addRow("on") << u"on"_s << false;
+ QTest::addRow("on_Changed") << u"on_Changed"_s << true;
+ QTest::addRow("on$Changed") << u"on$Changed"_s << true;
+}
+void tst_qml_common::tst_isChangedHandlerName()
+{
+ QFETCH(QString, name);
+ QFETCH(bool, expected);
+
+ QCOMPARE(QQmlSignalNames::isChangedHandlerName(name), expected);
+}
+
+QTEST_MAIN(tst_qml_common)
diff --git a/tests/auto/qml/common/tst_qml_common.h b/tests/auto/qml/common/tst_qml_common.h
new file mode 100644
index 0000000000..98e462ded6
--- /dev/null
+++ b/tests/auto/qml/common/tst_qml_common.h
@@ -0,0 +1,35 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TST_QML_COMMON_H
+#define TST_QML_COMMON_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qlibraryinfo.h>
+#include <QtTest/qtest.h>
+#include <QtQml/private/qqmlsignalnames_p.h>
+
+class tst_qml_common : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void tst_propertyNameToChangedSignalName_data();
+ void tst_propertyNameToChangedSignalName();
+ void tst_propertyNameToChangedHandlerName();
+ void tst_propertyNameToChangedHandlerName_data();
+ void tst_signalNameToHandlerName();
+ void tst_signalNameToHandlerName_data();
+
+ void tst_changedSignalNameToPropertyName();
+ void tst_changedSignalNameToPropertyName_data();
+ void tst_changedHandlerNameToPropertyName();
+ void tst_changedHandlerNameToPropertyName_data();
+ void tst_handlerNameToSignalName();
+ void tst_handlerNameToSignalName_data();
+
+ void tst_isChangedHandlerName();
+ void tst_isChangedHandlerName_data();
+};
+
+#endif // TST_QML_COMMON_H
diff --git a/tests/auto/qml/debugger/qdebugmessageservice/CMakeLists.txt b/tests/auto/qml/debugger/qdebugmessageservice/CMakeLists.txt
index d3df19bc40..07b6e26544 100644
--- a/tests/auto/qml/debugger/qdebugmessageservice/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qdebugmessageservice/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qdebugmessageservice Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qdebugmessageservice LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qdebugmessageservice/data/test.qml b/tests/auto/qml/debugger/qdebugmessageservice/data/test.qml
index b8134b37e6..bdb91d08e5 100644
--- a/tests/auto/qml/debugger/qdebugmessageservice/data/test.qml
+++ b/tests/auto/qml/debugger/qdebugmessageservice/data/test.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
index 11c4203429..cd39b51b25 100644
--- a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
+++ b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
//QQmlDebugTest
#include "../shared/debugutil_p.h"
diff --git a/tests/auto/qml/debugger/qpacketprotocol/CMakeLists.txt b/tests/auto/qml/debugger/qpacketprotocol/CMakeLists.txt
index 146999b9bd..91941de381 100644
--- a/tests/auto/qml/debugger/qpacketprotocol/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qpacketprotocol/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qpacketprotocol Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qpacketprotocol LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qpacketprotocol
SOURCES
../shared/debugutil.cpp ../shared/debugutil_p.h
diff --git a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
index 81d8694406..2ce062b0cc 100644
--- a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
+++ b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QSignalSpy>
#include <QTimer>
@@ -18,9 +18,9 @@ class tst_QPacketProtocol : public QObject
Q_OBJECT
private:
- QTcpServer *m_server;
- QTcpSocket *m_client;
- QTcpSocket *m_serverConn;
+ std::unique_ptr<QTcpServer> m_server;
+ std::unique_ptr<QTcpSocket> m_client;
+ std::unique_ptr<QTcpSocket> m_serverConn;
private slots:
void init();
@@ -34,34 +34,34 @@ private slots:
void tst_QPacketProtocol::init()
{
- m_server = new QTcpServer(this);
+ m_server = std::make_unique<QTcpServer>(this);
m_serverConn = nullptr;
QVERIFY(m_server->listen(QHostAddress("127.0.0.1")));
- m_client = new QTcpSocket(this);
+ m_client = std::make_unique<QTcpSocket>(this);
- QSignalSpy serverSpy(m_server, SIGNAL(newConnection()));
- QSignalSpy clientSpy(m_client, SIGNAL(connected()));
+ QSignalSpy serverSpy(m_server.get(), SIGNAL(newConnection()));
+ QSignalSpy clientSpy(m_client.get(), SIGNAL(connected()));
m_client->connectToHost(m_server->serverAddress(), m_server->serverPort());
QVERIFY(clientSpy.size() > 0 || clientSpy.wait());
QVERIFY(serverSpy.size() > 0 || serverSpy.wait());
- m_serverConn = m_server->nextPendingConnection();
+ m_serverConn.reset(m_server->nextPendingConnection());
}
void tst_QPacketProtocol::cleanup()
{
- delete m_client;
- delete m_serverConn;
- delete m_server;
+ m_client.reset();
+ m_serverConn.reset();
+ m_server.reset();
}
void tst_QPacketProtocol::send()
{
- QPacketProtocol in(m_client);
- QPacketProtocol out(m_serverConn);
+ QPacketProtocol in(m_client.get());
+ QPacketProtocol out(m_serverConn.get());
QByteArray ba;
int num;
@@ -82,8 +82,8 @@ void tst_QPacketProtocol::packetsAvailable()
{
QFETCH(int, packetCount);
- QPacketProtocol out(m_client);
- QPacketProtocol in(m_serverConn);
+ QPacketProtocol out(m_client.get());
+ QPacketProtocol in(m_serverConn.get());
QCOMPARE(out.packetsAvailable(), qint64(0));
QCOMPARE(in.packetsAvailable(), qint64(0));
@@ -109,8 +109,8 @@ void tst_QPacketProtocol::packetsAvailable_data()
void tst_QPacketProtocol::read()
{
- QPacketProtocol in(m_client);
- QPacketProtocol out(m_serverConn);
+ QPacketProtocol in(m_client.get());
+ QPacketProtocol out(m_serverConn.get());
QVERIFY(in.read().isEmpty());
diff --git a/tests/auto/qml/debugger/qqmldebugclient/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebugclient/CMakeLists.txt
index 6b33ee0024..d0a63440da 100644
--- a/tests/auto/qml/debugger/qqmldebugclient/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebugclient/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldebugclient Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebugclient LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmldebugclient
SOURCES
../shared/debugutil.cpp ../shared/debugutil_p.h
diff --git a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
index 509791b96d..d0e9c22f2c 100644
--- a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
+++ b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "debugutil_p.h"
#include "qqmldebugtestservice.h"
@@ -44,11 +44,16 @@ void tst_QQmlDebugClient::initTestCase()
m_service = new QQmlDebugTestService("tst_QQmlDebugClient::handshake()");
- foreach (const QString &service, QQmlDebuggingEnabler::debuggerServices())
+ const QStringList debuggerServices = QQmlDebuggingEnabler::debuggerServices();
+ for (const QString &service : debuggerServices)
QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr);
- foreach (const QString &service, QQmlDebuggingEnabler::inspectorServices())
+
+ const QStringList inspectorServices = QQmlDebuggingEnabler::inspectorServices();
+ for (const QString &service : inspectorServices)
QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr);
- foreach (const QString &service, QQmlDebuggingEnabler::profilerServices())
+
+ const QStringList profilerServices = QQmlDebuggingEnabler::profilerServices();
+ for (const QString &service : profilerServices)
QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr);
const QString waitingMsg = QString("QML Debugger: Waiting for connection on port %1...").arg(PORT);
diff --git a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/CMakeLists.txt
index b73c2aa218..53b1e9c683 100644
--- a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldebuggingenabler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebuggingenabler LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmldebuggingenabler
SOURCES
../../shared/debugutil.cpp ../../shared/debugutil_p.h
diff --git a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/data/test.qml b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/data/test.qml
index 9bd5130e71..2474016705 100644
--- a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/data/test.qml
+++ b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/data/test.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp
index ab599e9a23..03a65f56ca 100644
--- a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp
+++ b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "debugutil_p.h"
#include "qqmldebugprocess_p.h"
@@ -41,14 +41,14 @@ void tst_QQmlDebuggingEnabler::data()
QTest::addColumn<bool>("blockMode");
QTest::addColumn<QStringList>("services");
- QStringList connectors({
+ const QStringList connectors({
QLatin1String("QQmlDebugServer"),
QLatin1String("QQmlNativeDebugConnector")
});
- QList<bool> blockModes({ true, false });
+ const QList<bool> blockModes({ true, false });
- QList<QStringList> serviceLists({
+ const QList<QStringList> serviceLists({
QStringList(),
QQmlDebuggingEnabler::nativeDebuggerServices(),
QQmlDebuggingEnabler::debuggerServices(),
@@ -57,9 +57,9 @@ void tst_QQmlDebuggingEnabler::data()
QQmlDebuggingEnabler::debuggerServices() + QQmlDebuggingEnabler::inspectorServices()
});
- foreach (const QString &connector, connectors) {
- foreach (bool blockMode, blockModes) {
- foreach (const QStringList &serviceList, serviceLists) {
+ for (const QString &connector : connectors) {
+ for (bool blockMode : blockModes) {
+ for (const QStringList &serviceList : serviceLists) {
QString name = connector + QLatin1Char(',')
+ QLatin1String(blockMode ? "block" : "noblock") + QLatin1Char(',')
+ serviceList.join(QLatin1Char('-'));
@@ -103,7 +103,7 @@ void tst_QQmlDebuggingEnabler::qmlscene()
m_clients = QQmlDebugTest::createOtherClients(m_connection);
m_connection->connectToHost("127.0.0.1", m_process->debugPort());
QVERIFY(m_connection->waitForConnected());
- foreach (QQmlDebugClient *client, m_clients)
+ for (QQmlDebugClient *client : std::as_const(m_clients))
QCOMPARE(client->state(), (services.isEmpty() || services.contains(client->name())) ?
QQmlDebugClient::Enabled : QQmlDebugClient::Unavailable);
}
diff --git a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenablerserver/qqmldebuggingenablerserver.cpp b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenablerserver/qqmldebuggingenablerserver.cpp
index 33bb0d6d37..6baaf8f430 100644
--- a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenablerserver/qqmldebuggingenablerserver.cpp
+++ b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenablerserver/qqmldebuggingenablerserver.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qcoreapplication.h>
#include <QtCore/qlibraryinfo.h>
diff --git a/tests/auto/qml/debugger/qqmldebugjs/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebugjs/CMakeLists.txt
index e48f8e965d..3d65442ebf 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebugjs/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldebugjs Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebugjs LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/breakOnAnchor.qml b/tests/auto/qml/debugger/qqmldebugjs/data/breakOnAnchor.qml
index 03bc85f5a4..6650096b55 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/breakOnAnchor.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/breakOnAnchor.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.11
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml b/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml
index 3a846c0eeb..254924743e 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/changeBreakpoint.qml b/tests/auto/qml/debugger/qqmldebugjs/data/changeBreakpoint.qml
index 2d747c28a5..3ebe44ea76 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/changeBreakpoint.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/changeBreakpoint.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/condition.qml b/tests/auto/qml/debugger/qqmldebugjs/data/condition.qml
index a4952f79cc..0f02f62750 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/condition.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/condition.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/createComponent.qml b/tests/auto/qml/debugger/qqmldebugjs/data/createComponent.qml
index e67713ba67..f58b474876 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/createComponent.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/createComponent.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/exception.qml b/tests/auto/qml/debugger/qqmldebugjs/data/exception.qml
index dc3be646ce..807735573e 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/exception.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/exception.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/loadjsfile.qml b/tests/auto/qml/debugger/qqmldebugjs/data/loadjsfile.qml
index 0af1188015..bcd8f4e9d5 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/loadjsfile.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/loadjsfile.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import "test.js" as Script
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml b/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml
index 6cf2d7c030..4cc13a7952 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/quit.qml b/tests/auto/qml/debugger/qqmldebugjs/data/quit.qml
index 026911d1cc..788cd86cce 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/quit.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/quit.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/quitInJS.qml b/tests/auto/qml/debugger/qqmldebugjs/data/quitInJS.qml
index 4f21b53ff4..ab8566b77c 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/quitInJS.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/quitInJS.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import "quit.js" as Quit;
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/stepAction.qml b/tests/auto/qml/debugger/qqmldebugjs/data/stepAction.qml
index f442a9c491..1de3078f19 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/stepAction.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/stepAction.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/test.js b/tests/auto/qml/debugger/qqmldebugjs/data/test.js
index 7a28dafdd2..f631b1657b 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/test.js
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/test.js
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
function printMessage(msg)
{
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/test.qml b/tests/auto/qml/debugger/qqmldebugjs/data/test.qml
index 687955dffc..bc84f7b3af 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/test.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/test.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/timer.qml b/tests/auto/qml/debugger/qqmldebugjs/data/timer.qml
index 923acb72ad..a823a9a407 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/timer.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/timer.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
index ac607df0a0..35a94aae78 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "debugutil_p.h"
#include "qqmldebugprocess_p.h"
@@ -140,8 +140,8 @@ private slots:
void letConstLocals();
private:
- ConnectResult init(bool qmlscene, const QString &qmlFile = QString(TEST_QMLFILE),
- bool blockMode = true, bool restrictServices = false);
+ ConnectResult runAndConnect(bool qmlscene, const QString &qmlFile = QString(TEST_QMLFILE),
+ bool blockMode = true, bool restrictServices = false);
QList<QQmlDebugClient *> createClients() override;
QPointer<QV4DebugClient> m_client;
@@ -163,7 +163,7 @@ void tst_QQmlDebugJS::initTestCase()
QQmlDebugTest::initTestCase();
}
#include <iostream>
-QQmlDebugTest::ConnectResult tst_QQmlDebugJS::init(bool qmlscene, const QString &qmlFile,
+QQmlDebugTest::ConnectResult tst_QQmlDebugJS::runAndConnect(bool qmlscene, const QString &qmlFile,
bool blockMode, bool restrictServices)
{
const QString executable = qmlscene
@@ -195,7 +195,7 @@ void tst_QQmlDebugJS::connect()
QFETCH(bool, restrictMode);
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene, QString(TEST_QMLFILE), blockMode, restrictMode), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, QString(TEST_QMLFILE), blockMode, restrictMode), ConnectSuccess);
m_client->connect();
QVERIFY(waitForClientSignal(SIGNAL(connected())));
}
@@ -205,7 +205,7 @@ void tst_QQmlDebugJS::interrupt()
//void connect()
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene), ConnectSuccess);
m_client->connect();
m_client->interrupt();
@@ -217,7 +217,7 @@ void tst_QQmlDebugJS::getVersion()
//void version()
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene), ConnectSuccess);
m_client->connect();
QVERIFY(waitForClientSignal(SIGNAL(connected())));
@@ -231,7 +231,7 @@ void tst_QQmlDebugJS::getVersionWhenAttaching()
//void version()
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene, QLatin1String(TIMER_QMLFILE), false), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, QLatin1String(TIMER_QMLFILE), false), ConnectSuccess);
m_client->connect();
m_client->version();
@@ -244,7 +244,7 @@ void tst_QQmlDebugJS::disconnect()
//void disconnect()
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene), ConnectSuccess);
m_client->connect();
m_client->disconnect();
@@ -257,7 +257,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnCompleted()
QFETCH(bool, qmlscene);
int sourceLine = 9;
- QCOMPARE(init(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -276,7 +276,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnComponentCreated()
QFETCH(bool, qmlscene);
int sourceLine = 9;
- QCOMPARE(init(qmlscene, CREATECOMPONENT_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, CREATECOMPONENT_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -294,7 +294,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnTimerCallback()
QFETCH(bool, qmlscene);
int sourceLine = 10;
- QCOMPARE(init(qmlscene, TIMER_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, TIMER_QMLFILE), ConnectSuccess);
m_client->connect();
//We can set the breakpoint after connect() here because the timer is repeating and if we miss
@@ -315,7 +315,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptInDifferentFile()
QFETCH(bool, qmlscene);
int sourceLine = 6;
- QCOMPARE(init(qmlscene, LOADJSFILE_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, LOADJSFILE_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(TEST_JSFILE), sourceLine, -1, true);
m_client->connect();
@@ -335,7 +335,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnComment()
int sourceLine = 9;
int actualLine = 11;
- QCOMPARE(init(qmlscene, BREAKPOINTRELOCATION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, BREAKPOINTRELOCATION_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -356,7 +356,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnEmptyLine()
int sourceLine = 10;
int actualLine = 11;
- QCOMPARE(init(qmlscene, BREAKPOINTRELOCATION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, BREAKPOINTRELOCATION_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -376,7 +376,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnOptimizedBinding()
QFETCH(bool, qmlscene);
int sourceLine = 14;
- QCOMPARE(init(qmlscene, BREAKPOINTRELOCATION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, BREAKPOINTRELOCATION_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -395,7 +395,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptWithCondition()
int out = 10;
int sourceLine = 12;
- QCOMPARE(init(qmlscene, CONDITION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, CONDITION_QMLFILE), ConnectSuccess);
m_client->connect();
//The breakpoint is in a timer loop so we can set it after connect().
@@ -425,7 +425,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptThatQuits()
{
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene, QUIT_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, QUIT_QMLFILE), ConnectSuccess);
int sourceLine = 11;
@@ -465,7 +465,7 @@ void tst_QQmlDebugJS::setBreakpointInJavaScript()
QTRY_COMPARE(process.state(), QProcess::NotRunning);
}
- QCOMPARE(init(qmlscene, QUITINJS_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, QUITINJS_QMLFILE), ConnectSuccess);
const int sourceLine = 2;
@@ -488,7 +488,7 @@ void tst_QQmlDebugJS::setBreakpointInJavaScript()
void tst_QQmlDebugJS::setBreakpointWhenAttaching()
{
int sourceLine = 10;
- QCOMPARE(init(true, QLatin1String(TIMER_QMLFILE), false), ConnectSuccess);
+ QCOMPARE(runAndConnect(true, QLatin1String(TIMER_QMLFILE), false), ConnectSuccess);
m_client->connect();
@@ -509,7 +509,7 @@ void tst_QQmlDebugJS::clearBreakpoint()
int sourceLine1 = 12;
int sourceLine2 = 13;
- QCOMPARE(init(qmlscene, CHANGEBREAKPOINT_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, CHANGEBREAKPOINT_QMLFILE), ConnectSuccess);
m_client->connect();
//The breakpoints are in a timer loop so we can set them after connect().
@@ -556,7 +556,7 @@ void tst_QQmlDebugJS::changeBreakpoint()
int sourceLine2 = 12;
int sourceLine1 = 13;
const QString file = QLatin1String(CHANGEBREAKPOINT_QMLFILE);
- QCOMPARE(init(qmlscene, file), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, file), ConnectSuccess);
bool isStopped = false;
QObject::connect(m_client.data(), &QV4DebugClient::stopped, this, [&]() { isStopped = true; });
@@ -629,7 +629,7 @@ void tst_QQmlDebugJS::setExceptionBreak()
//void setExceptionBreak(QString type, bool enabled = false);
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene, EXCEPTION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, EXCEPTION_QMLFILE), ConnectSuccess);
m_client->setExceptionBreak(QV4DebugClient::All,true);
m_client->connect();
QVERIFY(waitForClientSignal(SIGNAL(stopped())));
@@ -641,7 +641,7 @@ void tst_QQmlDebugJS::stepNext()
QFETCH(bool, qmlscene);
int sourceLine = 12;
- QCOMPARE(init(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -669,7 +669,7 @@ void tst_QQmlDebugJS::stepIn()
int sourceLine = 16;
int actualLine = 11;
- QCOMPARE(init(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine, 1, true);
m_client->connect();
@@ -691,7 +691,7 @@ void tst_QQmlDebugJS::stepOut()
int sourceLine = 12;
int actualLine = 16;
- QCOMPARE(init(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -713,7 +713,7 @@ void tst_QQmlDebugJS::continueDebugging()
int sourceLine1 = 16;
int sourceLine2 = 13;
- QCOMPARE(init(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine1, -1, true);
m_client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine2, -1, true);
@@ -736,7 +736,7 @@ void tst_QQmlDebugJS::backtrace()
QFETCH(bool, qmlscene);
int sourceLine = 9;
- QCOMPARE(init(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -752,7 +752,7 @@ void tst_QQmlDebugJS::getFrameDetails()
QFETCH(bool, qmlscene);
int sourceLine = 9;
- QCOMPARE(init(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -768,7 +768,7 @@ void tst_QQmlDebugJS::getScopeDetails()
QFETCH(bool, qmlscene);
int sourceLine = 9;
- QCOMPARE(init(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -781,7 +781,7 @@ void tst_QQmlDebugJS::getScopeDetails()
void tst_QQmlDebugJS::evaluateInGlobalScope()
{
//void evaluate(QString expr, int frame = -1);
- QCOMPARE(init(true), ConnectSuccess);
+ QCOMPARE(runAndConnect(true), ConnectSuccess);
m_client->connect();
@@ -802,7 +802,7 @@ void tst_QQmlDebugJS::evaluateInLocalScope()
QFETCH(bool, qmlscene);
int sourceLine = 9;
- QCOMPARE(init(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -889,7 +889,7 @@ void tst_QQmlDebugJS::getScripts()
//void scripts(int types = -1, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant());
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene), ConnectSuccess);
m_client->setBreakpoint(QString(TEST_QMLFILE), 10, -1, true);
m_client->connect();
@@ -908,7 +908,7 @@ void tst_QQmlDebugJS::getScripts()
void tst_QQmlDebugJS::encodeQmlScope()
{
QString file(ENCODEQMLSCOPE_QMLFILE);
- QCOMPARE(init(true, file), ConnectSuccess);
+ QCOMPARE(runAndConnect(true, file), ConnectSuccess);
int numFrames = 0;
int numExpectedScopes = 0;
@@ -968,7 +968,7 @@ void tst_QQmlDebugJS::encodeQmlScope()
void tst_QQmlDebugJS::breakOnAnchor()
{
QString file(BREAKONANCHOR_QMLFILE);
- QCOMPARE(init(true, file), ConnectSuccess);
+ QCOMPARE(runAndConnect(true, file), ConnectSuccess);
int breaks = 0;
bool stopped = false;
@@ -1005,7 +1005,7 @@ void tst_QQmlDebugJS::breakOnAnchor()
void tst_QQmlDebugJS::breakPointIds()
{
QString file(BREAKPOINTIDS_QMLFILE);
- QCOMPARE(init(true, file), ConnectSuccess);
+ QCOMPARE(runAndConnect(true, file), ConnectSuccess);
int breaks = 0;
int breakPointIds[] = { -1, -1, -1, -1, -1, -1};
@@ -1038,7 +1038,7 @@ void tst_QQmlDebugJS::breakPointIds()
void tst_QQmlDebugJS::letConstLocals()
{
QString file(LETCONSTLOCALS_QMLFILE);
- QCOMPARE(init(true, file), ConnectSuccess);
+ QCOMPARE(runAndConnect(true, file), ConnectSuccess);
QObject::connect(m_client.data(), &QV4DebugClient::stopped, this, [&]() {
m_client->frame();
diff --git a/tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.cpp b/tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.cpp
index b24e4c4445..4b3d7dc6fa 100644
--- a/tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtGui/qguiapplication.h>
#include <QtQml/qqmlengine.h>
diff --git a/tests/auto/qml/debugger/qqmldebuglocal/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebuglocal/CMakeLists.txt
index 471336139d..03dcb24b3f 100644
--- a/tests/auto/qml/debugger/qqmldebuglocal/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebuglocal/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldebuglocal Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebuglocal LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmldebuglocal
SOURCES
../shared/debugutil.cpp ../shared/debugutil_p.h
diff --git a/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp
index 7449062332..bca70b7273 100644
--- a/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp
+++ b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qqmldebugtestservice.h"
#include "debugutil_p.h"
diff --git a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/CMakeLists.txt
index ea07333ec7..54fe36b7d5 100644
--- a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldebugprocess Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebugprocess LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmldebugprocess
SOURCES
../../shared/qqmldebugprocess.cpp ../../shared/qqmldebugprocess_p.h
diff --git a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp
index 7b1faa1131..2a403fa361 100644
--- a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp
+++ b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qqmldebugprocess_p.h>
#include <QtTest>
diff --git a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocessprocess/qqmldebugprocessprocess.cpp b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocessprocess/qqmldebugprocessprocess.cpp
index 595fe70e58..f275c2e836 100644
--- a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocessprocess/qqmldebugprocessprocess.cpp
+++ b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocessprocess/qqmldebugprocessprocess.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qdebug.h>
#include <QtCore/qcoreapplication.h>
diff --git a/tests/auto/qml/debugger/qqmldebugservice/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebugservice/CMakeLists.txt
index 33b7ba1c2f..2169cb8e0e 100644
--- a/tests/auto/qml/debugger/qqmldebugservice/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebugservice/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldebugservice Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebugservice LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmldebugservice/data/test.qml b/tests/auto/qml/debugger/qqmldebugservice/data/test.qml
index 687955dffc..bc84f7b3af 100644
--- a/tests/auto/qml/debugger/qqmldebugservice/data/test.qml
+++ b/tests/auto/qml/debugger/qqmldebugservice/data/test.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
index 7dbff4279e..462caf930f 100644
--- a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
@@ -1,6 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qqmldebugtestservice.h"
#include "debugutil_p.h"
@@ -30,7 +29,7 @@ public:
tst_QQmlDebugService();
private:
- QQmlDebugConnection *m_conn;
+ std::unique_ptr<QQmlDebugConnection> m_conn;
QQmlDebugTestService *m_service;
private slots:
@@ -60,20 +59,23 @@ void tst_QQmlDebugService::initTestCase()
<< QStringLiteral("tst_QQmlDebugService"));
m_service = new QQmlDebugTestService("tst_QQmlDebugService", 2);
- foreach (const QString &service, QQmlDebuggingEnabler::debuggerServices())
+ const QStringList debuggerServices = QQmlDebuggingEnabler::debuggerServices();
+ for (const QString &service : debuggerServices)
QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr);
- foreach (const QString &service, QQmlDebuggingEnabler::inspectorServices())
+
+ const QStringList inspectorServices = QQmlDebuggingEnabler::inspectorServices();
+ for (const QString &service : inspectorServices)
QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr);
- foreach (const QString &service, QQmlDebuggingEnabler::profilerServices())
+
+ const QStringList profilerServices = QQmlDebuggingEnabler::profilerServices();
+ for (const QString &service : profilerServices)
QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr);
const QString waitingMsg = QString("QML Debugger: Waiting for connection on port %1...").arg(PORT);
QTest::ignoreMessage(QtDebugMsg, waitingMsg.toLatin1().constData());
QQmlDebuggingEnabler::startTcpDebugServer(PORT);
- new QQmlEngine(this);
-
- m_conn = new QQmlDebugConnection(this);
+ m_conn = std::make_unique<QQmlDebugConnection>(this);
for (int i = 0; i < 50; ++i) {
// try for 5 seconds ...
@@ -136,7 +138,7 @@ void tst_QQmlDebugService::state()
QCOMPARE(m_service->state(), QQmlDebugService::Unavailable);
{
- QQmlDebugTestClient client("tst_QQmlDebugService", m_conn);
+ QQmlDebugTestClient client("tst_QQmlDebugService", m_conn.get());
QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled);
QTRY_COMPARE(m_service->state(), QQmlDebugService::Enabled);
}
@@ -154,7 +156,7 @@ void tst_QQmlDebugService::state()
void tst_QQmlDebugService::sendMessage()
{
- QQmlDebugTestClient client("tst_QQmlDebugService", m_conn);
+ QQmlDebugTestClient client("tst_QQmlDebugService", m_conn.get());
QByteArray msg = "hello!";
@@ -175,7 +177,7 @@ void tst_QQmlDebugService::sendMessage()
void tst_QQmlDebugService::checkSupportForDataStreamVersion()
{
- QQmlDebugTestClient client("tst_QQmlDebugService", m_conn);
+ QQmlDebugTestClient client("tst_QQmlDebugService", m_conn.get());
QByteArray msg = "hello!";
@@ -192,22 +194,19 @@ void tst_QQmlDebugService::idForObject()
{
QCOMPARE(QQmlDebugService::idForObject(nullptr), -1);
- QObject *objA = new QObject;
+ std::unique_ptr<QObject> objA = std::make_unique<QObject>();
- int idA = QQmlDebugService::idForObject(objA);
+ int idA = QQmlDebugService::idForObject(objA.get());
QVERIFY(idA >= 0);
- QCOMPARE(QQmlDebugService::objectForId(idA), objA);
+ QCOMPARE(QQmlDebugService::objectForId(idA), objA.get());
- int idAA = QQmlDebugService::idForObject(objA);
+ int idAA = QQmlDebugService::idForObject(objA.get());
QCOMPARE(idAA, idA);
- QObject *objB = new QObject;
- int idB = QQmlDebugService::idForObject(objB);
+ std::unique_ptr<QObject> objB = std::make_unique<QObject>();
+ int idB = QQmlDebugService::idForObject(objB.get());
QVERIFY(idB != idA);
- QCOMPARE(QQmlDebugService::objectForId(idB), objB);
-
- delete objA;
- delete objB;
+ QCOMPARE(QQmlDebugService::objectForId(idB), objB.get());
}
void tst_QQmlDebugService::objectForId()
@@ -215,19 +214,18 @@ void tst_QQmlDebugService::objectForId()
QCOMPARE(QQmlDebugService::objectForId(-1), static_cast<QObject*>(nullptr));
QCOMPARE(QQmlDebugService::objectForId(1), static_cast<QObject*>(nullptr));
- QObject *obj = new QObject;
- int id = QQmlDebugService::idForObject(obj);
- QCOMPARE(QQmlDebugService::objectForId(id), obj);
+ std::unique_ptr<QObject> obj = std::make_unique<QObject>();
+ int id = QQmlDebugService::idForObject(obj.get());
+ QCOMPARE(QQmlDebugService::objectForId(id), obj.get());
- delete obj;
+ obj.reset();
QCOMPARE(QQmlDebugService::objectForId(id), static_cast<QObject*>(nullptr));
}
void tst_QQmlDebugService::checkSupportForOldDataStreamVersion()
{
//create a new connection;
- delete m_conn;
- m_conn = new QQmlDebugConnection(this);
+ m_conn = std::make_unique<QQmlDebugConnection>(this);
m_conn->setMaximumDataStreamVersion(QDataStream::Qt_5_0);
for (int i = 0; i < 50; ++i) {
// try for 5 seconds ...
@@ -238,7 +236,7 @@ void tst_QQmlDebugService::checkSupportForOldDataStreamVersion()
}
QVERIFY(m_conn->isConnected());
- QQmlDebugTestClient client("tst_QQmlDebugService", m_conn);
+ QQmlDebugTestClient client("tst_QQmlDebugService", m_conn.get());
QByteArray msg = "hello!";
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationclient/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebugtranslationclient/CMakeLists.txt
index fd44b5d32f..56c2e8d88a 100644
--- a/tests/auto/qml/debugger/qqmldebugtranslationclient/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebugtranslationclient/CMakeLists.txt
@@ -5,6 +5,12 @@
## tst_qqmldebugtranslationclient Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebugtranslationclient LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationclient/data/test.qml b/tests/auto/qml/debugger/qqmldebugtranslationclient/data/test.qml
index 5b4784bbff..e90f9a5a80 100644
--- a/tests/auto/qml/debugger/qqmldebugtranslationclient/data/test.qml
+++ b/tests/auto/qml/debugger/qqmldebugtranslationclient/data/test.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationclient/tst_qqmldebugtranslationclient.cpp b/tests/auto/qml/debugger/qqmldebugtranslationclient/tst_qqmldebugtranslationclient.cpp
index 4ad9699cb9..068ab69d4c 100644
--- a/tests/auto/qml/debugger/qqmldebugtranslationclient/tst_qqmldebugtranslationclient.cpp
+++ b/tests/auto/qml/debugger/qqmldebugtranslationclient/tst_qqmldebugtranslationclient.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
//QQmlDebugTest
#include <debugutil_p.h>
@@ -105,9 +105,7 @@ private:
if (newCurrentOutputLine > m_currentOutputLine) {
// lets wait a little bit more to not cut anything
int triggeredCount = 0;
- int debugCounter = 0;
do {
- debugCounter++;
triggeredCount = m_process->output().size();
QTest::qWait(updateTimeOut);
newCurrentOutputLine = m_process->output().size();
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebugtranslationservice/CMakeLists.txt
index 7f971df399..5081f51557 100644
--- a/tests/auto/qml/debugger/qqmldebugtranslationservice/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/CMakeLists.txt
@@ -5,6 +5,12 @@
## tst_qqmldebugtranslationservice Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebugtranslationservice LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml b/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml
index 1212fa100a..5d3957bffa 100644
--- a/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml
+++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp b/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp
index 0e0340b672..88d7bd39fd 100644
--- a/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp
+++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
//QQmlDebugTest
#include <debugutil_p.h>
diff --git a/tests/auto/qml/debugger/qqmlenginecontrol/CMakeLists.txt b/tests/auto/qml/debugger/qqmlenginecontrol/CMakeLists.txt
index 39435fe894..12c5b4ad1f 100644
--- a/tests/auto/qml/debugger/qqmlenginecontrol/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmlenginecontrol/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlenginecontrol Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlenginecontrol LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp b/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
index 638389eb3c..bd01c69163 100644
--- a/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
+++ b/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "debugutil_p.h"
#include <QtQuickTestUtils/private/qmlutils_p.h>
diff --git a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/CMakeLists.txt b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/CMakeLists.txt
index 8b4fc93594..bb36f678c3 100644
--- a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlenginedebuginspectorintegration Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlenginedebuginspectorintegration LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
index 890f4eeef6..7bbc8830b1 100644
--- a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "../shared/debugutil_p.h"
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -24,7 +24,7 @@ public:
tst_QQmlEngineDebugInspectorIntegration();
private:
- ConnectResult init(bool restrictServices);
+ ConnectResult runAndConnect(bool restrictServices);
QList<QQmlDebugClient *> createClients() override;
QQmlEngineDebugObjectReference findRootObject();
@@ -68,7 +68,7 @@ tst_QQmlEngineDebugInspectorIntegration::tst_QQmlEngineDebugInspectorIntegration
{
}
-QQmlDebugTest::ConnectResult tst_QQmlEngineDebugInspectorIntegration::init(bool restrictServices)
+QQmlDebugTest::ConnectResult tst_QQmlEngineDebugInspectorIntegration::runAndConnect(bool restrictServices)
{
return QQmlDebugTest::connectTo(
QLibraryInfo::path(QLibraryInfo::BinariesPath) + "/qml",
@@ -96,15 +96,15 @@ void tst_QQmlEngineDebugInspectorIntegration::connect_data()
void tst_QQmlEngineDebugInspectorIntegration::connect()
{
QFETCH(bool, restrictMode);
- QCOMPARE(init(restrictMode), ConnectSuccess);
+ QCOMPARE(runAndConnect(restrictMode), ConnectSuccess);
}
void tst_QQmlEngineDebugInspectorIntegration::objectLocationLookup()
{
- QCOMPARE(init(true), ConnectSuccess);
+ QCOMPARE(runAndConnect(true), ConnectSuccess);
bool success = false;
- QQmlEngineDebugObjectReference rootObject = findRootObject();
+ const QQmlEngineDebugObjectReference rootObject = findRootObject();
QVERIFY(rootObject.debugId != -1);
const QString fileName = QFileInfo(rootObject.source.url.toString()).fileName();
int lineNumber = rootObject.source.lineNumber;
@@ -114,7 +114,7 @@ void tst_QQmlEngineDebugInspectorIntegration::objectLocationLookup()
QVERIFY(success);
QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
- foreach (QQmlEngineDebugObjectReference child, rootObject.children) {
+ for (const QQmlEngineDebugObjectReference &child : rootObject.children) {
success = false;
lineNumber = child.source.lineNumber;
columnNumber = child.source.columnNumber;
@@ -127,12 +127,12 @@ void tst_QQmlEngineDebugInspectorIntegration::objectLocationLookup()
void tst_QQmlEngineDebugInspectorIntegration::select()
{
- QCOMPARE(init(true), ConnectSuccess);
+ QCOMPARE(runAndConnect(true), ConnectSuccess);
- QQmlEngineDebugObjectReference rootObject = findRootObject();
+ const QQmlEngineDebugObjectReference rootObject = findRootObject();
QList<int> childIds;
int requestId = 0;
- foreach (const QQmlEngineDebugObjectReference &child, rootObject.children) {
+ for (const QQmlEngineDebugObjectReference &child : rootObject.children) {
requestId = m_inspectorClient->select(QList<int>() << child.debugId);
QTRY_COMPARE(m_recipient->lastResponseId, requestId);
QVERIFY(m_recipient->lastResult);
@@ -145,7 +145,7 @@ void tst_QQmlEngineDebugInspectorIntegration::select()
void tst_QQmlEngineDebugInspectorIntegration::createObject()
{
- QCOMPARE(init(true), ConnectSuccess);
+ QCOMPARE(runAndConnect(true), ConnectSuccess);
QString qml = QLatin1String("Rectangle {\n"
" id: xxxyxxx\n"
@@ -172,7 +172,7 @@ void tst_QQmlEngineDebugInspectorIntegration::createObject()
void tst_QQmlEngineDebugInspectorIntegration::moveObject()
{
- QCOMPARE(init(true), ConnectSuccess);
+ QCOMPARE(runAndConnect(true), ConnectSuccess);
QCOMPARE(m_inspectorClient->state(), QQmlDebugClient::Enabled);
QQmlEngineDebugObjectReference rootObject = findRootObject();
@@ -197,7 +197,7 @@ void tst_QQmlEngineDebugInspectorIntegration::moveObject()
void tst_QQmlEngineDebugInspectorIntegration::destroyObject()
{
- QCOMPARE(init(true), ConnectSuccess);
+ QCOMPARE(runAndConnect(true), ConnectSuccess);
QCOMPARE(m_inspectorClient->state(), QQmlDebugClient::Enabled);
QQmlEngineDebugObjectReference rootObject = findRootObject();
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/CMakeLists.txt b/tests/auto/qml/debugger/qqmlenginedebugservice/CMakeLists.txt
index 4d4a939da5..d412368767 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlenginedebugservice Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlenginedebugservice LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/complexItem.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/complexItem.qml
index 9e4546bdac..bda1673b18 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/complexItem.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/complexItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import Test 1.0
@@ -7,7 +7,7 @@ Item {
id: root
width: 10; height: 20; scale: blueRect.scale;
Rectangle { id: blueRect; width: 500; height: 600; color: "blue"; }
- Text { font.bold: true; color: blueRect.color; }
+ Text { id: blueText; font.bold: true; color: blueRect.color; }
MouseArea {
onEntered: { console.log('hello') }
}
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/customTypes.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/customTypes.qml
index a472988772..3203cc5bfc 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/customTypes.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/customTypes.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import Backend 1.0
CustomTypes {
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/debuggerCrashOnAttach.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/debuggerCrashOnAttach.qml
index 0532b44726..994b2f82f1 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/debuggerCrashOnAttach.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/debuggerCrashOnAttach.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Controls 2.5
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/emptyItem.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/emptyItem.qml
index ebbf3f85e3..ded2b620ce 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/emptyItem.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/emptyItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
Item {
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/fetchValueType.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/fetchValueType.qml
index ea0c3ff8c0..0a2e68f786 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/fetchValueType.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/fetchValueType.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/itemWithFunctions.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/itemWithFunctions.qml
index 118b13f2d7..e107ed5259 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/itemWithFunctions.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/itemWithFunctions.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
Item {
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/jsonTest.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/jsonTest.qml
index eb0c65b42f..27f6ffcc92 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/jsonTest.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/jsonTest.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import JsonTest 1.0
JsonTest {
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/rectangleWithTransitions.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/rectangleWithTransitions.qml
index fee3f969b8..d8fe7f98c3 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/rectangleWithTransitions.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/rectangleWithTransitions.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
Rectangle {
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
index e6e21cbb9e..a63c690cf0 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "debugutil_p.h"
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -22,6 +22,7 @@
#include <QtQml/qqmlproperty.h>
#include <QtQml/qqmlincubator.h>
#include <QtQml/qqmlapplicationengine.h>
+#include <QtQml/private/qqmlsignalnames_p.h>
#include <QtQuick/qquickitem.h>
#include <QtNetwork/qhostaddress.h>
@@ -244,7 +245,7 @@ void tst_QQmlEngineDebugService::recursiveObjectTest(
QCOMPARE(p.objectDebugId, QQmlDebugService::idForObject(o));
// signal properties are fake - they are generated from QQmlAbstractBoundSignal children
- if (p.name.startsWith("on") && p.name.size() > 2 && p.name[2].isUpper()) {
+ if (QQmlSignalNames::isHandlerName(p.name)) {
QString signal = p.value.toString();
QQmlBoundSignalExpression *expr = QQmlPropertyPrivate::signalExpression(QQmlProperty(o, p.name));
QVERIFY(expr && expr->expression() == signal);
@@ -414,10 +415,10 @@ void tst_QQmlEngineDebugService::watch_property()
bool success;
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->addWatch(prop, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->addWatch(QQmlEngineDebugPropertyReference(), &success);
QVERIFY(success);
@@ -458,10 +459,10 @@ void tst_QQmlEngineDebugService::watch_object()
bool success;
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->addWatch(obj, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->addWatch(QQmlEngineDebugObjectReference(), &success);
QVERIFY(success);
@@ -525,10 +526,10 @@ void tst_QQmlEngineDebugService::watch_expression()
bool success;
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->addWatch(obj, expr, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->addWatch(QQmlEngineDebugObjectReference(), expr, &success);
QVERIFY(success);
@@ -600,10 +601,10 @@ void tst_QQmlEngineDebugService::queryAvailableEngines()
{
bool success;
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->queryAvailableEngines(&success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->queryAvailableEngines(&success);
QVERIFY(success);
@@ -628,10 +629,10 @@ void tst_QQmlEngineDebugService::queryRootContexts()
QVERIFY(m_dbg->engines().size());
const QQmlEngineDebugEngineReference engine = m_dbg->engines()[0];
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->queryRootContexts(engine, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->queryRootContexts(engine, &success);
QVERIFY(success);
@@ -659,10 +660,10 @@ void tst_QQmlEngineDebugService::queryObject()
QQmlEngineDebugObjectReference rootObject = findRootObject();
QVERIFY(!rootObject.className.isEmpty());
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
recursive ? unconnected->queryObjectRecursive(rootObject, &success) : unconnected->queryObject(rootObject, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
recursive ? m_dbg->queryObjectRecursive(rootObject, &success) : m_dbg->queryObject(rootObject, &success);
QVERIFY(success);
@@ -690,9 +691,9 @@ void tst_QQmlEngineDebugService::queryObject()
QQmlEngineDebugObjectReference text;
for (const QQmlEngineDebugObjectReference &child : obj.children) {
QVERIFY(!child.className.isEmpty());
- if (child.className == "Rectangle")
+ if (child.idString == "blueRect")
rect = child;
- else if (child.className == "Text")
+ else if (child.idString == "blueText")
text = child;
}
@@ -731,13 +732,13 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation()
int lineNumber = rootObject.source.lineNumber;
int columnNumber = rootObject.source.columnNumber;
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
recursive ? unconnected->queryObjectsForLocationRecursive(fileName, lineNumber,
columnNumber, &success)
: unconnected->queryObjectsForLocation(fileName, lineNumber,
columnNumber, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
recursive ? m_dbg->queryObjectsForLocationRecursive(fileName, lineNumber,
columnNumber, &success)
@@ -769,9 +770,9 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation()
QQmlEngineDebugObjectReference text;
for (const QQmlEngineDebugObjectReference &child : obj.children) {
QVERIFY(!child.className.isEmpty());
- if (child.className == "Rectangle")
+ if (child.idString == "blueRect")
rect = child;
- else if (child.className == "Text")
+ else if (child.idString == "blueText")
text = child;
}
@@ -813,9 +814,9 @@ void tst_QQmlEngineDebugService::regression_QTCREATORBUG_7451()
"text: \"test\"\n"
"}");
component.setData(content, rootObject.source.url);
- QObject *object = component.create(context);
+ std::unique_ptr<QObject> object { component.create(context) };
QVERIFY(object);
- int idNew = QQmlDebugService::idForObject(object);
+ int idNew = QQmlDebugService::idForObject(object.get());
QVERIFY(idNew >= 0);
const QString fileName = QFileInfo(rootObject.source.url.toString()).fileName();
@@ -839,7 +840,7 @@ void tst_QQmlEngineDebugService::regression_QTCREATORBUG_7451()
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
}
- delete object;
+ object.reset();
QObject *deleted = QQmlDebugService::objectForId(idNew);
QVERIFY(!deleted);
@@ -870,10 +871,10 @@ void tst_QQmlEngineDebugService::queryObjectWithNonStreamableTypes()
QQmlEngineDebugObjectReference rootObject = findRootObject(4, true);
QVERIFY(!rootObject.className.isEmpty());
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->queryObject(rootObject, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->queryObject(rootObject, &success);
QVERIFY(success);
@@ -914,10 +915,10 @@ void tst_QQmlEngineDebugService::queryExpressionResult()
bool success;
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->queryExpressionResult(objectId, expr, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->queryExpressionResult(objectId, expr, &success);
QVERIFY(success);
@@ -967,10 +968,10 @@ void tst_QQmlEngineDebugService::queryExpressionResultBC()
bool success;
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->queryExpressionResultBC(objectId, expr, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->queryExpressionResultBC(objectId, expr, &success);
QVERIFY(success);
diff --git a/tests/auto/qml/debugger/qqmlinspector/CMakeLists.txt b/tests/auto/qml/debugger/qqmlinspector/CMakeLists.txt
index 7e6fb3559d..34a9b7a393 100644
--- a/tests/auto/qml/debugger/qqmlinspector/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmlinspector/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlinspector Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlinspector LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
index 897d8c8688..7f4e5eb73f 100644
--- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
+++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "../shared/debugutil_p.h"
#include "../shared/qqmldebugprocess_p.h"
diff --git a/tests/auto/qml/debugger/qqmlnativeconnector/CMakeLists.txt b/tests/auto/qml/debugger/qqmlnativeconnector/CMakeLists.txt
index 705361c3be..f6d8988ec2 100644
--- a/tests/auto/qml/debugger/qqmlnativeconnector/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmlnativeconnector/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlnativeconnector Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlnativeconnector LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlnativeconnector
SOURCES
tst_qqmlnativeconnector.cpp
diff --git a/tests/auto/qml/debugger/qqmlnativeconnector/tst_qqmlnativeconnector.cpp b/tests/auto/qml/debugger/qqmlnativeconnector/tst_qqmlnativeconnector.cpp
index 55a9aeb3f5..dd9789cdc5 100644
--- a/tests/auto/qml/debugger/qqmlnativeconnector/tst_qqmlnativeconnector.cpp
+++ b/tests/auto/qml/debugger/qqmlnativeconnector/tst_qqmlnativeconnector.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
diff --git a/tests/auto/qml/debugger/qqmlpreview/CMakeLists.txt b/tests/auto/qml/debugger/qqmlpreview/CMakeLists.txt
index 3eaf14b35d..83d33a617f 100644
--- a/tests/auto/qml/debugger/qqmlpreview/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmlpreview/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlpreview Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlpreview LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
list(APPEND test_data "data/window.qml")
list(APPEND test_data "data/qtquick2.qml")
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/broken.qml b/tests/auto/qml/debugger/qqmlpreview/data/broken.qml
index 75387c42aa..e8f82461a0 100644
--- a/tests/auto/qml/debugger/qqmlpreview/data/broken.qml
+++ b/tests/auto/qml/debugger/qqmlpreview/data/broken.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/qtquick2.qml b/tests/auto/qml/debugger/qqmlpreview/data/qtquick2.qml
index 4013dfc9ff..d49b94fc7e 100644
--- a/tests/auto/qml/debugger/qqmlpreview/data/qtquick2.qml
+++ b/tests/auto/qml/debugger/qqmlpreview/data/qtquick2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/window.qml b/tests/auto/qml/debugger/qqmlpreview/data/window.qml
index 951b9a7f10..1141292a2c 100644
--- a/tests/auto/qml/debugger/qqmlpreview/data/window.qml
+++ b/tests/auto/qml/debugger/qqmlpreview/data/window.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Window 2.0
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/window1.qml b/tests/auto/qml/debugger/qqmlpreview/data/window1.qml
index 4a24041dea..20c7ab04ea 100644
--- a/tests/auto/qml/debugger/qqmlpreview/data/window1.qml
+++ b/tests/auto/qml/debugger/qqmlpreview/data/window1.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Window 2.3
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/window2.qml b/tests/auto/qml/debugger/qqmlpreview/data/window2.qml
index 0de5dc36c8..d144cfb033 100644
--- a/tests/auto/qml/debugger/qqmlpreview/data/window2.qml
+++ b/tests/auto/qml/debugger/qqmlpreview/data/window2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Window 2.3
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/zoom.qml b/tests/auto/qml/debugger/qqmlpreview/data/zoom.qml
index 86445a2fdc..18712a7e2d 100644
--- a/tests/auto/qml/debugger/qqmlpreview/data/zoom.qml
+++ b/tests/auto/qml/debugger/qqmlpreview/data/zoom.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp
index 0c4fd568a9..5874100ebd 100644
--- a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp
+++ b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qqmldebugprocess_p.h>
#include <debugutil_p.h>
@@ -303,7 +303,7 @@ void tst_QQmlPreview::zoom()
for (auto testZoomFactor : {2.0f, 1.5f, 0.5f}) {
m_client->triggerZoom(testZoomFactor);
- verifyZoomFactor(m_process, testZoomFactor);
+ verifyZoomFactor(m_process, testZoomFactor * baseZoomFactor);
}
m_client->triggerZoom(-1.0f);
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/CMakeLists.txt b/tests/auto/qml/debugger/qqmlprofilerservice/CMakeLists.txt
index 1e6c4c1753..d770f1fb27 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlprofilerservice Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlprofilerservice LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml
index 3a7c093fa5..6e16eaa7b1 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.0
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/quit.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/quit.qml
index 026911d1cc..788cd86cce 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/quit.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/quit.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index 53971d3e8b..2088f958ae 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "debugutil_p.h"
#include "qqmldebugprocess_p.h"
@@ -80,7 +80,7 @@ void QQmlProfilerTestClient::addEvent(const QQmlProfilerEvent &event)
const QQmlProfilerEventType &type = types[typeIndex];
- QVERIFY(event.timestamp() >= lastTimestamp);
+ const qint64 oldTimestamp = lastTimestamp;
lastTimestamp = event.timestamp();
switch (type.message()) {
@@ -149,6 +149,8 @@ void QQmlProfilerTestClient::addEvent(const QQmlProfilerEvent &event)
}
break;
}
+
+ QCOMPARE_GE(lastTimestamp, oldTimestamp);
}
class tst_QQmlProfilerService : public QQmlDebugTest
@@ -287,7 +289,7 @@ void tst_QQmlProfilerService::checkJsHeap()
qint64 allocated = 0;
qint64 used = 0;
qint64 lastTimestamp = -1;
- foreach (const QQmlProfilerEvent &message, m_client->jsHeapMessages) {
+ for (const QQmlProfilerEvent &message : std::as_const(m_client->jsHeapMessages)) {
const auto amount = message.number<qint64>(0);
const QQmlProfilerEventType &type = m_client->types.at(message.typeIndex());
switch (type.detailType()) {
@@ -440,7 +442,7 @@ bool tst_QQmlProfilerService::verify(tst_QQmlProfilerService::MessageListType ty
return true;
} while (++position < target->size() && target->at(position).timestamp() == timestamp);
- foreach (const QString &message, warnings)
+ for (const QString &message : std::as_const(warnings))
qWarning() << message.toLocal8Bit().constData();
return false;
@@ -580,7 +582,7 @@ void tst_QQmlProfilerService::scenegraphData()
QCOMPARE(connectTo(true, "scenegraphTest.qml"), ConnectSuccess);
while (!m_process->output().contains(QLatin1String("tick")))
- QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
+ QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput()), 30000));
m_client->client->setRecording(false);
checkTraceReceived();
@@ -594,7 +596,7 @@ void tst_QQmlProfilerService::scenegraphData()
// interleaved. Also, events could carry the same time stamps and be sorted in an unexpected way
// if the clocks are acting up.
qint64 renderFrameTime = -1;
- foreach (const QQmlProfilerEvent &msg, m_client->asynchronousMessages) {
+ for (const QQmlProfilerEvent &msg : std::as_const(m_client->asynchronousMessages)) {
const QQmlProfilerEventType &type = m_client->types.at(msg.typeIndex());
if (type.detailType() == SceneGraphRendererFrame) {
renderFrameTime = msg.timestamp();
diff --git a/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt b/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt
index 0b60a0092b..42f6cf931a 100644
--- a/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qv4debugger Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qv4debugger LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -17,11 +23,12 @@ qt_add_library(testCppTypes STATIC)
qt_autogen_tools_initial_setup(testCppTypes)
target_link_libraries(testCppTypes PRIVATE Qt::Qml Qt::QmlPrivate Qt::Quick)
+qt_policy(SET QTP0001 NEW)
+
qt6_add_qml_module(testCppTypes
URI TestTypes
SOURCES
commontypes.h
- AUTO_RESOURCE_PREFIX
OUTPUT_DIRECTORY TestTypes
)
qt_autogen_tools_initial_setup(testCppTypesplugin)
diff --git a/tests/auto/qml/debugger/qv4debugger/commontypes.h b/tests/auto/qml/debugger/qv4debugger/commontypes.h
index 01b2125ae3..b63059b0e6 100644
--- a/tests/auto/qml/debugger/qv4debugger/commontypes.h
+++ b/tests/auto/qml/debugger/qv4debugger/commontypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef COMMONTYPES_H
#define COMMONTYPES_H
@@ -14,7 +14,7 @@ class MyType : public QQuickItem
QML_ELEMENT
public:
MyType(QQuickItem *parent = nullptr) : QQuickItem(parent) {}
- Q_INVOKABLE void name(QQmlV4Function*) const {}
+ Q_INVOKABLE void name(QQmlV4FunctionPtr) const {}
};
#endif // COMMONTYPES_H
diff --git a/tests/auto/qml/debugger/qv4debugger/data/breakPointInJSModule.qml b/tests/auto/qml/debugger/qv4debugger/data/breakPointInJSModule.qml
new file mode 100644
index 0000000000..2582a23ec5
--- /dev/null
+++ b/tests/auto/qml/debugger/qv4debugger/data/breakPointInJSModule.qml
@@ -0,0 +1,4 @@
+import QtQml 2.15
+import "module1.js" as Module1
+
+QtObject {}
diff --git a/tests/auto/qml/debugger/qv4debugger/data/module1.js b/tests/auto/qml/debugger/qv4debugger/data/module1.js
new file mode 100644
index 0000000000..9ce1f1e6b1
--- /dev/null
+++ b/tests/auto/qml/debugger/qv4debugger/data/module1.js
@@ -0,0 +1,5 @@
+.pragma library
+
+.import "module2.mjs" as Module2
+
+Module2.crashMe();
diff --git a/tests/auto/qml/debugger/qv4debugger/data/module2.mjs b/tests/auto/qml/debugger/qv4debugger/data/module2.mjs
new file mode 100644
index 0000000000..80f82af953
--- /dev/null
+++ b/tests/auto/qml/debugger/qv4debugger/data/module2.mjs
@@ -0,0 +1,7 @@
+import * as Module3 from "module3.mjs"
+import * as Module4 from "module4.mjs"
+
+export function crashMe()
+{
+ console.log("Hello world!");
+}
diff --git a/tests/auto/qml/debugger/qv4debugger/data/module3.mjs b/tests/auto/qml/debugger/qv4debugger/data/module3.mjs
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/qml/debugger/qv4debugger/data/module3.mjs
diff --git a/tests/auto/qml/debugger/qv4debugger/data/module4.mjs b/tests/auto/qml/debugger/qv4debugger/data/module4.mjs
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/qml/debugger/qv4debugger/data/module4.mjs
diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
index 6f147446f0..3da401b5bb 100644
--- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
+++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtTest/QtTest>
@@ -167,7 +168,7 @@ public slots:
m_thrownValue = job.exceptionValue();
}
- foreach (const TestBreakPoint &bp, m_breakPointsToAddWhenPaused)
+ for (const TestBreakPoint &bp : std::as_const(m_breakPointsToAddWhenPaused))
debugger->addBreakPoint(bp.fileName, bp.lineNumber);
m_breakPointsToAddWhenPaused.clear();
@@ -216,10 +217,14 @@ public:
QJsonArray scopes = frameObj.value(QLatin1String("scopes")).toArray();
int nscopes = scopes.size();
int s = 0;
- for (s = 0; s < nscopes; ++s) {
- QJsonObject o = scopes.at(s).toObject();
- if (o.value(QLatin1String("type")).toInt(-2) == 1) // CallContext
- break;
+ if (m_targetScope != -1) {
+ s = m_targetScope;
+ } else {
+ for (s = 0; s < nscopes; ++s) {
+ QJsonObject o = scopes.at(s).toObject();
+ if (o.value(QLatin1String("type")).toInt(-2) == 1) // CallContext
+ break;
+ }
}
if (s == nscopes)
return;
@@ -249,6 +254,7 @@ public:
bool m_wasPaused;
QV4Debugger::PauseReason m_pauseReason;
bool m_captureContextInfo;
+ int m_targetScope = -1;
QList<QV4Debugger::ExecutionState> m_statesWhenPaused;
QList<TestBreakPoint> m_breakPointsToAddWhenPaused;
QVector<QV4::StackFrame> m_stackTrace;
@@ -274,9 +280,10 @@ public:
void dumpStackTrace() const
{
qDebug() << "Stack depth:" << m_stackTrace.size();
- foreach (const QV4::StackFrame &frame, m_stackTrace)
+ for (const QV4::StackFrame &frame : m_stackTrace) {
qDebug("\t%s (%s:%d:%d)", qPrintable(frame.function), qPrintable(frame.source),
- frame.line, frame.column);
+ qAbs(frame.line), frame.column);
+ }
}
};
@@ -322,6 +329,9 @@ private slots:
void readThis();
void signalParameters();
void debuggerNoCrash();
+
+ void breakPointInJSModule();
+
private:
QV4Debugger *debugger() const
{
@@ -329,27 +339,27 @@ private:
}
void evaluateJavaScript(const QString &script, const QString &fileName, int lineNumber = 1)
{
- QMetaObject::invokeMethod(m_engine, "evaluate", Qt::QueuedConnection,
+ QMetaObject::invokeMethod(m_engine.get(), "evaluate", Qt::QueuedConnection,
Q_ARG(QString, script), Q_ARG(QString, fileName),
Q_ARG(int, lineNumber));
- waitForSignal(m_engine, SIGNAL(evaluateFinished()), /*timeout*/0);
+ waitForSignal(m_engine.get(), SIGNAL(evaluateFinished()), /*timeout*/0);
}
- TestEngine *m_engine;
+ std::unique_ptr<TestEngine> m_engine;
QV4::ExecutionEngine *m_v4;
- TestAgent *m_debuggerAgent;
- QThread *m_javaScriptThread;
+ std::unique_ptr<TestAgent> m_debuggerAgent;
+ std::unique_ptr<QThread> m_javaScriptThread;
};
void tst_qv4debugger::init()
{
- m_javaScriptThread = new QThread;
- m_engine = new TestEngine;
+ m_javaScriptThread = std::make_unique<QThread>();
+ m_engine = std::make_unique<TestEngine>();
m_v4 = m_engine->v4Engine();
m_v4->setDebugger(new QV4Debugger(m_v4));
- m_engine->moveToThread(m_javaScriptThread);
+ m_engine->moveToThread(m_javaScriptThread.get());
m_javaScriptThread->start();
- m_debuggerAgent = new TestAgent(m_v4);
+ m_debuggerAgent = std::make_unique<TestAgent>(m_v4);
m_debuggerAgent->addDebugger(debugger());
}
@@ -357,11 +367,11 @@ void tst_qv4debugger::cleanup()
{
m_javaScriptThread->exit();
m_javaScriptThread->wait();
- delete m_engine;
- delete m_javaScriptThread;
+ m_engine.reset();
+ m_javaScriptThread.reset();
m_engine = nullptr;
m_v4 = nullptr;
- delete m_debuggerAgent;
+ m_debuggerAgent.reset();
m_debuggerAgent = nullptr;
}
@@ -453,7 +463,7 @@ void tst_qv4debugger::removeBreakPointForNextInstruction()
"someCall();\n"
"var i = 42;";
- QMetaObject::invokeMethod(m_engine, "injectFunction", Qt::BlockingQueuedConnection,
+ QMetaObject::invokeMethod(m_engine.get(), "injectFunction", Qt::BlockingQueuedConnection,
Q_ARG(QString, "someCall"), Q_ARG(InjectedFunction, someCall));
debugger()->addBreakPoint("removeBreakPointForNextInstruction", 2);
@@ -967,6 +977,35 @@ void tst_qv4debugger::debuggerNoCrash()
debugThread->wait();
}
+void tst_qv4debugger::breakPointInJSModule()
+{
+ QQmlEngine engine;
+ QV4::ExecutionEngine *v4 = engine.handle();
+ QPointer<QV4Debugger> v4Debugger = new QV4Debugger(v4);
+ v4->setDebugger(v4Debugger.data());
+
+ QScopedPointer<QThread> debugThread(new QThread);
+ debugThread->start();
+ QScopedPointer<TestAgent> debuggerAgent(new TestAgent(v4));
+ debuggerAgent->addDebugger(v4Debugger);
+ debuggerAgent->moveToThread(debugThread.data());
+
+ QQmlComponent component(&engine, testFileUrl("breakPointInJSModule.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+
+ debuggerAgent->m_captureContextInfo = true;
+ debuggerAgent->m_targetScope = 1;
+ v4Debugger->addBreakPoint("module2.mjs", 6);
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+
+ QVERIFY(!debuggerAgent->m_capturedScope.isEmpty());
+
+ debugThread->quit();
+ debugThread->wait();
+}
+
tst_qv4debugger::tst_qv4debugger() : QQmlDataTest(QT_QMLTEST_DATADIR) { }
QTEST_MAIN(tst_qv4debugger)
diff --git a/tests/auto/qml/debugger/shared/debugutil.cpp b/tests/auto/qml/debugger/shared/debugutil.cpp
index bce2c28378..28d40d768d 100644
--- a/tests/auto/qml/debugger/shared/debugutil.cpp
+++ b/tests/auto/qml/debugger/shared/debugutil.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "debugutil_p.h"
#include "qqmldebugprocess_p.h"
diff --git a/tests/auto/qml/debugger/shared/debugutil_p.h b/tests/auto/qml/debugger/shared/debugutil_p.h
index 0303aa2da9..188cc14c32 100644
--- a/tests/auto/qml/debugger/shared/debugutil_p.h
+++ b/tests/auto/qml/debugger/shared/debugutil_p.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DEBUGUTIL_P_H
#define DEBUGUTIL_P_H
diff --git a/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp b/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp
index 4944ba2e15..97477370c8 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp
+++ b/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qqmldebugprocess_p.h"
@@ -56,7 +56,7 @@ QString QQmlDebugProcess::stateString() const
void QQmlDebugProcess::start(const QStringList &arguments)
{
-#ifdef Q_OS_MAC
+#ifdef Q_OS_MACOS
// make sure m_executable points to the actual binary even if it's inside an app bundle
QFileInfo binFile(m_executable);
if (!binFile.isExecutable()) {
diff --git a/tests/auto/qml/debugger/shared/qqmldebugprocess_p.h b/tests/auto/qml/debugger/shared/qqmldebugprocess_p.h
index 56ed9b9830..94554928a5 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugprocess_p.h
+++ b/tests/auto/qml/debugger/shared/qqmldebugprocess_p.h
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef QQMLDEBUGPROCESS_P_H
#define QQMLDEBUGPROCESS_P_H
diff --git a/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp b/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp
index daafa8c26e..4884c9d400 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp
+++ b/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qqmldebugtestservice.h"
#include <QThread>
diff --git a/tests/auto/qml/debugger/shared/qqmldebugtestservice.h b/tests/auto/qml/debugger/shared/qqmldebugtestservice.h
index 150ded9b1b..a2a3ce6161 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugtestservice.h
+++ b/tests/auto/qml/debugger/shared/qqmldebugtestservice.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef QQMLDEBUGTESTSERVICE_H
#define QQMLDEBUGTESTSERVICE_H
diff --git a/tests/auto/qml/ecmascripttests/CMakeLists.txt b/tests/auto/qml/ecmascripttests/CMakeLists.txt
index d3da3adb53..1ee70cb101 100644
--- a/tests/auto/qml/ecmascripttests/CMakeLists.txt
+++ b/tests/auto/qml/ecmascripttests/CMakeLists.txt
@@ -5,15 +5,22 @@
## tst_ecmascripttests Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_ecmascripttests LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
test262/*)
list(APPEND test_data ${test_data_glob})
+list(FILTER test_data EXCLUDE REGEX ".git")
qt_internal_add_test(tst_ecmascripttests
SOURCES
- qjstest/test262runner.cpp qjstest/test262runner.h
+ test262runner.cpp test262runner.h
tst_ecmascripttests.cpp
LIBRARIES
Qt::QmlPrivate
@@ -40,7 +47,3 @@ else()
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/test262"
)
endif()
-
-if(NOT CMAKE_CROSSCOMPILING)
- add_subdirectory(qjstest)
-endif()
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index 75fdd1cb0c..cc5eae456d 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -18,6 +18,12 @@ language/statements/labeled/let-identifier-with-newline.js sloppyFails
language/statements/while/let-identifier-with-newline.js sloppyFails
language/statements/with/let-identifier-with-newline.js sloppyFails
+# These failures are a defect in the Yarr regexp engine we are using.
+# They all amount to some variation of: /\udf06/u.exec('\ud834\udf06')
+built-ins/RegExp/prototype/Symbol.match/builtin-infer-unicode.js
+built-ins/RegExp/prototype/Symbol.search/u-lastindex-advance.js
+built-ins/RegExp/prototype/exec/u-lastindex-adv.js
+
# The ES6/7 spec says that [[DefineOwnProperty]] on the module namespace exotic object
# always returns false. This was changed in https://github.com/tc39/ecma262/pull/858
# but it's not in the published spec yet.
@@ -92,7 +98,6 @@ built-ins/Array/prototype/slice/length-exceeding-integer-limit-proxied-array.js
built-ins/Array/prototype/slice/length-exceeding-integer-limit.js fails
built-ins/Array/prototype/some/15.4.4.17-3-28.js fails
built-ins/Array/prototype/some/15.4.4.17-3-29.js fails
-built-ins/Array/prototype/sort/comparefn-nonfunction-call-throws.js fails
built-ins/Array/prototype/splice/S15.4.4.12_A3_T1.js fails
built-ins/Array/prototype/splice/clamps-length-to-integer-limit.js fails
built-ins/Array/prototype/splice/create-ctor-non-object.js fails
@@ -211,7 +216,6 @@ built-ins/Promise/prototype/then/ctor-throws.js fails
built-ins/Promise/race/ctx-ctor.js fails
built-ins/Proxy/ownKeys/return-duplicate-entries-throws.js fails
built-ins/Proxy/ownKeys/return-duplicate-symbol-entries-throws.js fails
-built-ins/RegExp/prototype/Symbol.match/builtin-success-u-return-val-groups.js fails
built-ins/RegExp/prototype/Symbol.split/species-ctor.js fails
built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T3.js fails
built-ins/RegExp/prototype/exec/failure-lastindex-access.js fails
@@ -249,8 +253,6 @@ built-ins/String/prototype/toLocaleLowerCase/special_casing_conditional.js fails
built-ins/String/prototype/toLowerCase/Final_Sigma_U180E.js fails
built-ins/String/prototype/toLowerCase/special_casing_conditional.js fails
built-ins/TypedArray/prototype/constructor.js fails
-built-ins/TypedArray/prototype/fill/fill-values-conversion-operations-consistent-nan.js fails
-built-ins/TypedArray/prototype/slice/bit-precision.js fails
built-ins/TypedArray/prototype/sort/arraylength-internal.js fails
built-ins/TypedArray/prototype/sort/comparefn-call-throws.js fails
built-ins/TypedArray/prototype/sort/comparefn-calls.js fails
diff --git a/tests/auto/qml/ecmascripttests/qjstest/CMakeLists.txt b/tests/auto/qml/ecmascripttests/qjstest/CMakeLists.txt
deleted file mode 100644
index 86ca5f97a3..0000000000
--- a/tests/auto/qml/ecmascripttests/qjstest/CMakeLists.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
-
-# Generated from qjstest.pro.
-
-#####################################################################
-## qjstest Tool:
-#####################################################################
-
-qt_get_tool_target_name(target_name qjstest)
-qt_internal_add_tool(${target_name}
- TARGET_DESCRIPTION "Javascript test runner"
- SOURCES
- main.cpp
- test262runner.cpp test262runner.h
- DEFINES
- QT_DEPRECATED_WARNINGS
- INCLUDE_DIRECTORIES
- .
- LIBRARIES
- Qt::Gui
- Qt::QmlPrivate
-)
-qt_internal_return_unless_building_tools()
-
-#### Keys ignored in scope 1:.:.:qjstest.pro:<TRUE>:
-# QMAKE_TARGET_DESCRIPTION = "Javascript" "test" "runner"
-# TEMPLATE = "app"
diff --git a/tests/auto/qml/ecmascripttests/qjstest/main.cpp b/tests/auto/qml/ecmascripttests/qjstest/main.cpp
deleted file mode 100644
index 7bffedae81..0000000000
--- a/tests/auto/qml/ecmascripttests/qjstest/main.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <QJSEngine>
-#include <QCoreApplication>
-#include <QCommandLineParser>
-#include <qdebug.h>
-#include <stdlib.h>
-
-#include "test262runner.h"
-
-int main(int argc, char **argv)
-{
- QCoreApplication app(argc, argv);
-
-
- QCommandLineParser parser;
- parser.addHelpOption();
- parser.addVersionOption();
- QCommandLineOption verbose("verbose", "Verbose output");
- parser.addOption(verbose);
- QCommandLineOption commandOption("command", "Javascript command line interpreter", "command");
- parser.addOption(commandOption);
- QCommandLineOption testDir("tests", "path to the tests", "tests", "test262");
- parser.addOption(testDir);
- QCommandLineOption cat("cat", "Print packaged test code that would be run");
- parser.addOption(cat);
- QCommandLineOption parallel("parallel", "Run tests in parallel");
- parser.addOption(parallel);
- QCommandLineOption jit("jit", "JIT all code");
- parser.addOption(jit);
- QCommandLineOption bytecode("interpret", "Run using the bytecode interpreter");
- parser.addOption(bytecode);
- QCommandLineOption withExpectations("with-test-expectations", "Parse TestExpectations to deal with known failures");
- parser.addOption(withExpectations);
- QCommandLineOption updateExpectations("update-expectations", "Update TestExpectations to remove unexepected passes");
- parser.addOption(updateExpectations);
- QCommandLineOption writeExpectations("write-expectations", "Generate a new TestExpectations file based on the results of the run");
- parser.addOption(writeExpectations);
- parser.addPositionalArgument("[filter]", "Only run tests that contain filter in their name");
-
- parser.process(app);
-
- Test262Runner testRunner(parser.value(commandOption), parser.value(testDir), QStringLiteral("TestExpectations"));
-
- QStringList otherArgs = parser.positionalArguments();
- if (otherArgs.size() > 1) {
- qWarning() << "too many arguments";
- return 1;
- } else if (otherArgs.size()) {
- testRunner.setFilter(otherArgs.at(0));
- }
-
- if (parser.isSet(cat)) {
- testRunner.cat();
- return 0;
- }
-
- if (parser.isSet(updateExpectations) && parser.isSet(writeExpectations)) {
- qWarning() << "Can only specify one of --update-expectations and --write-expectations.";
- exit(1);
- }
-
- if (parser.isSet(jit) && parser.isSet(bytecode)) {
- qWarning() << "Can only specify one of --jit and --interpret.";
- exit(1);
- }
-
- int flags = 0;
- if (parser.isSet(verbose))
-
- flags |= Test262Runner::Verbose;
- if (parser.isSet(parallel))
- flags |= Test262Runner::Parallel;
- if (parser.isSet(jit))
- flags |= Test262Runner::ForceJIT;
- if (parser.isSet(bytecode))
- flags |= Test262Runner::ForceBytecode;
- if (parser.isSet(withExpectations))
- flags |= Test262Runner::WithTestExpectations;
- if (parser.isSet(updateExpectations))
- flags |= Test262Runner::UpdateTestExpectations;
- if (parser.isSet(writeExpectations))
- flags |= Test262Runner::WriteTestExpectations;
- testRunner.setFlags(flags);
-
- if (testRunner.run())
- return EXIT_SUCCESS;
- else
- return EXIT_FAILURE;
-}
diff --git a/tests/auto/qml/ecmascripttests/test262.py b/tests/auto/qml/ecmascripttests/test262.py
deleted file mode 100755
index 01c990950c..0000000000
--- a/tests/auto/qml/ecmascripttests/test262.py
+++ /dev/null
@@ -1,611 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2017 The Qt Company Ltd.
-# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-# Copyright 2009 the Sputnik authors. All rights reserved.
-# This code is governed by the BSD license found in the LICENSE file.
-
-# This is derived from sputnik.py, the Sputnik console test runner,
-# with elements from packager.py, which is separately
-# copyrighted. TODO: Refactor so there is less duplication between
-# test262.py and packager.py.
-
-import sys
-from os import path
-rootDir = path.dirname(path.realpath(__file__))
-sys.path.insert(0, path.abspath(rootDir + "/test262/tools/packaging"))
-
-import logging
-import optparse
-import os
-import platform
-import re
-import subprocess
-import tempfile
-import time
-import xml.dom.minidom
-import datetime
-import shutil
-import json
-import stat
-import multiprocessing
-import signal
-
-
-from parseTestRecord import parseTestRecord, stripHeader
-
-from packagerConfig import *
-
-# excluded features that are still experimental and not part of any official standard
-# see also the features.txt file in test262/
-excludedFeatures = [
- "BigInt",
- "class-fields-public",
- "class-fields-private",
- "Promise.prototype.finally",
- "async-iteration",
- "Symbol.asyncIterator",
- "object-rest",
- "object-spread",
- "optional-catch-binding",
- "regexp-dotall",
- "regexp-lookbehind",
- "regexp-named-groups",
- "regexp-unicode-property-escapes",
- "Atomics",
- "SharedArrayBuffer",
- "Array.prototype.flatten",
- "Array.prototype.flatMap",
- "string-trimming",
- "String.prototype.trimEnd",
- "String.prototype.trimStart",
- "numeric-separator-literal",
-
- # optional features, not supported by us
- "caller"
-]
-
-# ############# Helpers needed for parallel multi-process test execution ############
-
-def runTest(case, args):
- return case.Run(args)
-
-def runTestVarArgs(args):
- return runTest(*args)
-
-def initWorkerProcess():
- signal.signal(signal.SIGINT, signal.SIG_IGN)
-
-# #############
-
-class Test262Error(Exception):
- def __init__(self, message):
- self.message = message
-
-def ReportError(s):
- raise Test262Error(s)
-
-
-class TestExpectations:
- def __init__(self, enabled):
- self.testsToSkip = []
- self.failingTests = []
- f = open(rootDir + "/TestExpectations")
- if not enabled:
- return
- for line in f.read().splitlines():
- line = line.strip()
- if len(line) == 0 or line[0] == "#":
- continue
- record = line.split()
- if len(record) == 1:
- self.failingTests.append(record[0])
- else:
- test = record[0]
- expectation = record[1]
- if expectation == "skip":
- self.testsToSkip.append(test)
- f.close()
-
- def update(self, progress):
- unexpectedPasses = [c.case.name for c in progress.failed_tests if c.case.IsNegative()]
-
- # If a test fails that we expected to fail, then it actually passed unexpectedly.
- failures = [c.case.name for c in progress.failed_tests if not c.case.IsNegative()]
- for failure in failures:
- if failure in self.failingTests:
- unexpectedPasses.append(failure)
-
- f = open(rootDir + "/TestExpectations")
- lines = f.read().splitlines()
- oldLen = len(lines)
- for result in unexpectedPasses:
- expectationLine = result
- try:
- lines.remove(expectationLine)
- except ValueError:
- pass
-
- f.close()
- if len(lines) != oldLen:
- f = open(rootDir + "/TestExpectations", "w")
- f.write("\n".join(lines))
- f.close()
- print "Changes to TestExpectations written!"
-
-
-if not os.path.exists(EXCLUDED_FILENAME):
- print "Cannot generate (JSON) test262 tests without a file," + \
- " %s, showing which tests have been disabled!" % EXCLUDED_FILENAME
- sys.exit(1)
-EXCLUDE_LIST = xml.dom.minidom.parse(EXCLUDED_FILENAME)
-EXCLUDE_LIST = EXCLUDE_LIST.getElementsByTagName("test")
-EXCLUDE_LIST = [x.getAttribute("id") for x in EXCLUDE_LIST]
-
-
-def BuildOptions():
- result = optparse.OptionParser()
- result.add_option("--command", default="qmljs", help="The command-line to run")
- result.add_option("--tests", default=path.abspath(rootDir + '/test262'),
- help="Path to the tests")
- result.add_option("--cat", default=False, action="store_true",
- help="Print packaged test code that would be run")
- result.add_option("--summary", default=True, action="store_true",
- help="Print summary after running tests")
- result.add_option("--full-summary", default=False, action="store_true",
- help="Print summary and test output after running tests")
- result.add_option("--strict_only", default=False, action="store_true",
- help="Test only strict mode")
- result.add_option("--non_strict_only", default=False, action="store_true",
- help="Test only non-strict mode")
- result.add_option("--parallel", default=False, action="store_true",
- help="Run tests in parallel")
- result.add_option("--with-test-expectations", default=False, action="store_true",
- help="Parse TestExpectations to deal with tests known to fail")
- result.add_option("--update-expectations", default=False, action="store_true",
- help="Update test expectations fail when a test passes that was expected to fail")
- # TODO: Once enough tests are made strict compat, change the default
- # to "both"
- result.add_option("--unmarked_default", default="non_strict",
- help="default mode for tests of unspecified strictness")
- return result
-
-
-def ValidateOptions(options):
- if not options.command:
- ReportError("A --command must be specified.")
- if not path.exists(options.tests):
- ReportError("Couldn't find test path '%s'" % options.tests)
-
-
-placeHolderPattern = re.compile(r"\{\{(\w+)\}\}")
-
-
-def IsWindows():
- p = platform.system()
- return (p == 'Windows') or (p == 'Microsoft')
-
-
-class TempFile(object):
-
- def __init__(self, suffix="", prefix="tmp", text=False):
- self.suffix = suffix
- self.prefix = prefix
- self.text = text
- self.fd = None
- self.name = None
- self.is_closed = False
- self.Open()
-
- def Open(self):
- (self.fd, self.name) = tempfile.mkstemp(
- suffix = self.suffix,
- prefix = self.prefix,
- text = self.text)
-
- def Write(self, str):
- os.write(self.fd, str)
-
- def Read(self):
- f = file(self.name)
- result = f.read()
- f.close()
- return result
-
- def Close(self):
- if not self.is_closed:
- self.is_closed = True
- os.close(self.fd)
-
- def Dispose(self):
- try:
- self.Close()
- os.unlink(self.name)
- except OSError, e:
- logging.error("Error disposing temp file: %s", str(e))
-
-
-class TestResult(object):
-
- def __init__(self, exit_code, stdout, stderr, case):
- self.exit_code = exit_code
- self.stdout = stdout
- self.stderr = stderr
- self.case = case
-
- def ReportOutcome(self, long_format):
- name = self.case.GetName()
- mode = self.case.GetMode()
- if self.HasUnexpectedOutcome():
- if self.case.IsNegative():
- print "=== %s was expected to fail in %s, but didn't ===" % (name, mode)
- else:
- if long_format:
- print "=== %s failed in %s ===" % (name, mode)
- else:
- print "%s in %s: " % (name, mode)
- out = self.stdout.strip()
- if len(out) > 0:
- print "--- output ---"
- print out
- err = self.stderr.strip()
- if len(err) > 0:
- print "--- errors ---"
- print err
- if long_format:
- print "==="
- elif self.case.IsNegative():
- print "%s failed in %s as expected" % (name, mode)
- else:
- print "%s passed in %s" % (name, mode)
-
- def HasFailed(self):
- return self.exit_code != 0
-
- def HasUnexpectedOutcome(self):
- if self.case.IsNegative():
- return not self.HasFailed()
- else:
- return self.HasFailed()
-
-
-class TestCase(object):
-
- def __init__(self, suite, name, full_path, strict_mode):
- self.suite = suite
- self.name = name
- self.full_path = full_path
- self.strict_mode = strict_mode
- f = open(self.full_path)
- self.contents = f.read()
- f.close()
- testRecord = parseTestRecord(self.contents, name)
- self.test = testRecord["test"]
- if 'features' in testRecord:
- self.features = testRecord["features"];
- else:
- self.features = []
- del testRecord["test"]
- del testRecord["header"]
- self.testRecord = testRecord;
-
-
- def GetName(self):
- return self.name
-
- def GetMode(self):
- if self.strict_mode:
- return "strict mode"
- else:
- return "non-strict mode"
-
- def GetPath(self):
- return self.name
-
- def NegateResult(self):
- if self.IsNegative():
- del self.testRecord['negative']
- else:
- self.testRecord['negative'] = "Some failure";
-
- def IsNegative(self):
- return 'negative' in self.testRecord
-
- def IsOnlyStrict(self):
- return 'onlyStrict' in self.testRecord
-
- def IsNoStrict(self):
- return 'noStrict' in self.testRecord
-
- def IsExperimental(self):
- for f in self.features:
- if excludedFeatures.count(f) >= 1:
- return True;
- return False
-
- def GetSource(self):
- # "var testDescrip = " + str(self.testRecord) + ';\n\n' + \
- source = self.suite.GetInclude("assert.js") + \
- self.suite.GetInclude("sta.js") + \
- self.test + '\n'
- if 'includes' in self.testRecord:
- for inc in self.testRecord['includes']:
- source += self.suite.GetInclude(inc);
-
- if self.strict_mode:
- source = '"use strict";\nvar strict_mode = true;\n' + source
- else:
- source = "var strict_mode = false; \n" + source
- return source
-
- def InstantiateTemplate(self, template, params):
- def GetParameter(match):
- key = match.group(1)
- return params.get(key, match.group(0))
- return placeHolderPattern.sub(GetParameter, template)
-
- def Execute(self, command):
- if IsWindows():
- args = '%s' % command
- else:
- args = command.split(" ")
- stdout = TempFile(prefix="test262-out-")
- stderr = TempFile(prefix="test262-err-")
- try:
- logging.info("exec: %s", str(args))
- process = subprocess.Popen(
- args,
- shell = IsWindows(),
- stdout = stdout.fd,
- stderr = stderr.fd
- )
- code = process.wait()
- out = stdout.Read()
- err = stderr.Read()
- finally:
- stdout.Dispose()
- stderr.Dispose()
- return (code, out, err)
-
- def RunTestIn(self, command_template, tmp):
- tmp.Write(self.GetSource())
- tmp.Close()
- command = self.InstantiateTemplate(command_template, {
- 'path': tmp.name
- })
- (code, out, err) = self.Execute(command)
- return TestResult(code, out, err, self)
-
- def Run(self, command_template):
- tmp = TempFile(suffix=".js", prefix="test262-", text=True)
- try:
- result = self.RunTestIn(command_template, tmp)
- finally:
- tmp.Dispose()
- return result
-
- def Print(self):
- print self.GetSource()
-
-
-class ProgressIndicator(object):
-
- def __init__(self, count):
- self.count = count
- self.succeeded = 0
- self.failed = 0
- self.failed_tests = []
-
- def HasRun(self, result):
- result.ReportOutcome(True)
- if result.HasUnexpectedOutcome():
- self.failed += 1
- self.failed_tests.append(result)
- else:
- self.succeeded += 1
-
-
-def MakePlural(n):
- if (n == 1):
- return (n, "")
- else:
- return (n, "s")
-
-
-class TestSuite(object):
-
- def __init__(self, root, strict_only, non_strict_only, unmarked_default, load_expectations):
- # TODO: derive from packagerConfig.py
- self.test_root = path.join(root, 'test')
- self.lib_root = path.join(root, 'harness')
- self.strict_only = strict_only
- self.non_strict_only = non_strict_only
- self.unmarked_default = unmarked_default
- self.include_cache = { }
- self.expectations = TestExpectations(load_expectations)
-
- def IsExcludedTest(self, path):
- if path.startswith('annexB'):
- return True;
- if path.startswith('harness'):
- return True;
- if path.startswith('intl402'):
- return True;
- return False;
-
- def Validate(self):
- if not path.exists(self.test_root):
- ReportError("No test repository found")
- if not path.exists(self.lib_root):
- ReportError("No test library found")
-
- def IsHidden(self, path):
- return path.startswith('.') or path == 'CVS'
-
- def IsTestCase(self, path):
- return path.endswith('.js')
-
- def ShouldRun(self, rel_path, tests):
- if len(tests) == 0:
- return True
- for test in tests:
- if test in rel_path:
- return True
- return False
-
- def GetInclude(self, name):
- if not name in self.include_cache:
- static = path.join(self.lib_root, name)
- if path.exists(static):
- f = open(static)
- contents = stripHeader(f.read())
- contents = re.sub(r'\r\n', '\n', contents)
- self.include_cache[name] = contents + "\n"
- f.close()
- else:
- ReportError("Can't find: " + static)
- return self.include_cache[name]
-
- def EnumerateTests(self, tests):
- logging.info("Listing tests in %s", self.test_root)
- cases = []
- for root, dirs, files in os.walk(self.test_root):
- for f in [x for x in dirs if self.IsHidden(x)]:
- dirs.remove(f)
- dirs.sort()
- for f in sorted(files):
- if self.IsTestCase(f):
- full_path = path.join(root, f)
- if full_path.startswith(self.test_root):
- rel_path = full_path[len(self.test_root)+1:]
- else:
- logging.warning("Unexpected path %s", full_path)
- rel_path = full_path
- if self.ShouldRun(rel_path, tests) and not self.IsExcludedTest(rel_path):
- basename = path.basename(full_path)[:-3]
- name = rel_path.replace('.js', '')
- if EXCLUDE_LIST.count(basename) >= 1 or self.expectations.testsToSkip.count(name) >= 1:
- print 'Excluded: ' + rel_path
- else:
- if not self.non_strict_only:
- strict_case = TestCase(self, name, full_path, True)
- if self.expectations.failingTests.count(name) >= 1:
- strict_case.NegateResult()
- if not strict_case.IsNoStrict() and not strict_case.IsExperimental():
- if strict_case.IsOnlyStrict() or \
- self.unmarked_default in ['both', 'strict']:
- cases.append(strict_case)
- if not self.strict_only:
- non_strict_case = TestCase(self, name, full_path, False)
- if self.expectations.failingTests.count(name) >= 1:
- non_strict_case.NegateResult()
- if not non_strict_case.IsOnlyStrict() and not non_strict_case.IsExperimental():
- if non_strict_case.IsNoStrict() or \
- self.unmarked_default in ['both', 'non_strict']:
- cases.append(non_strict_case)
- logging.info("Done listing tests")
- return cases
-
- def PrintSummary(self, progress):
- print
- print "=== Summary ==="
- count = progress.count
- succeeded = progress.succeeded
- failed = progress.failed
- print " - Ran %i test%s" % MakePlural(count)
- if progress.failed == 0:
- print " - All tests succeeded"
- else:
- percent = ((100.0 * succeeded) / count,)
- print " - Passed %i test%s (%.1f%%)" % (MakePlural(succeeded) + percent)
- percent = ((100.0 * failed) / count,)
- print " - Failed %i test%s (%.1f%%)" % (MakePlural(failed) + percent)
- positive = [c for c in progress.failed_tests if not c.case.IsNegative()]
- negative = [c for c in progress.failed_tests if c.case.IsNegative()]
- if len(positive) > 0:
- print
- print "Failed tests"
- for result in positive:
- print " %s in %s" % (result.case.GetName(), result.case.GetMode())
- if len(negative) > 0:
- print
- print "Expected to fail but passed ---"
- for result in negative:
- print " %s in %s" % (result.case.GetName(), result.case.GetMode())
-
- def PrintFailureOutput(self, progress):
- for result in progress.failed_tests:
- print
- result.ReportOutcome(False)
-
- def Run(self, command_template, tests, print_summary, full_summary, parallel, update_expectations):
- if not "{{path}}" in command_template:
- command_template += " {{path}}"
- cases = self.EnumerateTests(tests)
- if len(cases) == 0:
- ReportError("No tests to run")
- progress = ProgressIndicator(len(cases))
-
- if parallel:
- pool = multiprocessing.Pool(processes=multiprocessing.cpu_count(), initializer=initWorkerProcess)
- results = pool.imap_unordered(func=runTestVarArgs, iterable=[(case, command_template) for case in cases], chunksize=multiprocessing.cpu_count() * 8)
- for result in results:
- progress.HasRun(result)
- else:
- for case in cases:
- result = case.Run(command_template)
- progress.HasRun(result)
- if print_summary:
- self.PrintSummary(progress)
- if full_summary:
- self.PrintFailureOutput(progress)
- else:
- print
- print "Use --full-summary to see output from failed tests"
- print
- if update_expectations:
- self.expectations.update(progress)
- return progress.failed == 0
-
- def Print(self, tests):
- cases = self.EnumerateTests(tests)
- if len(cases) > 0:
- cases[0].Print()
-
-
-def Main():
- # Uncomment the next line for more logging info.
- #logging.basicConfig(level=logging.DEBUG)
- # Some date tests rely on being run in pacific time and the USA's locale:
- os.environ["TZ"] = "America/Los_Angeles" # it *matters* that this is (7m8s) *East* of PST's nominal meridian !
- os.environ["LANG"] = "en_US.UTF-8"
- os.environ["LC_TIME"] = "en_US.UTF-8"
- parser = BuildOptions()
- (options, args) = parser.parse_args()
- ValidateOptions(options)
- test_suite = TestSuite(options.tests,
- options.strict_only,
- options.non_strict_only,
- options.unmarked_default,
- options.with_test_expectations)
- test_suite.Validate()
- if options.cat:
- test_suite.Print(args)
- return 0
- else:
- if test_suite.Run(options.command, args,
- options.summary or options.full_summary,
- options.full_summary,
- options.parallel,
- options.update_expectations):
- return 0
- else:
- return 1
-
-
-if __name__ == '__main__':
- try:
- sys.exit(Main())
- except Test262Error, e:
- print "Error: %s" % e.message
- sys.exit(1)
diff --git a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp b/tests/auto/qml/ecmascripttests/test262runner.cpp
index fc09182f19..ff45b1b657 100644
--- a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp
+++ b/tests/auto/qml/ecmascripttests/test262runner.cpp
@@ -1,22 +1,26 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "test262runner.h"
-#include <qfile.h>
+#include <qdebug.h>
#include <qdir.h>
#include <qdiriterator.h>
-#include <qdebug.h>
+#include <qfile.h>
+#include <qjsondocument.h>
+#include <qjsonobject.h>
+#include <qlibraryinfo.h>
#include <qprocess.h>
#include <qtemporaryfile.h>
+#include <qthread.h>
-#include <private/qv4script_p.h>
-#include "private/qv4globalobject_p.h"
#include "private/qqmlbuiltinfunctions_p.h"
#include "private/qv4arraybuffer_p.h"
+#include "private/qv4globalobject_p.h"
#include <QtCore/QLoggingCategory>
+#include <private/qv4script_p.h>
-#include "qrunnable.h"
+using namespace Qt::StringLiterals;
static const char *excludedFeatures[] = {
"BigInt",
@@ -72,7 +76,7 @@ static ReturnedValue method_detachArrayBuffer(const FunctionObject *f, const Val
return Encode::null();
}
-static void initD262(ExecutionEngine *e)
+void initD262(ExecutionEngine *e)
{
Scope scope(e);
ScopedObject d262(scope, e->newObject());
@@ -85,10 +89,7 @@ static void initD262(ExecutionEngine *e)
}
-QT_END_NAMESPACE
-
-Q_DECLARE_LOGGING_CATEGORY(lcJsTest);
-Q_LOGGING_CATEGORY(lcJsTest, "qt.v4.ecma262.tests", QtWarningMsg);
+Q_STATIC_LOGGING_CATEGORY(lcJsTest, "qt.v4.ecma262.tests", QtWarningMsg);
Test262Runner::Test262Runner(const QString &command, const QString &dir, const QString &expectationsFile)
: command(command), testDir(dir), expectationsFile(expectationsFile)
@@ -99,7 +100,8 @@ Test262Runner::Test262Runner(const QString &command, const QString &dir, const Q
Test262Runner::~Test262Runner()
{
- delete threadPool;
+ if (threadPool)
+ delete threadPool;
}
void Test262Runner::cat()
@@ -113,18 +115,282 @@ void Test262Runner::cat()
printf("%s", data.content.constData());
}
+void Test262Runner::assignTaskOrTerminate(int processIndex)
+{
+ if (tasks.isEmpty()) {
+ sendDone(processIndex);
+ return;
+ }
+
+ currentTasks[processIndex] = tasks.dequeue();
+ TestData &task = currentTasks[processIndex];
+
+ // Sloppy run + maybe strict run later
+ if (task.runInSloppyMode) {
+ if (task.runInStrictMode)
+ task.stillNeedStrictRun = true;
+ assignSloppy(processIndex);
+ return;
+ }
+
+ // Only strict run
+ if (task.runInStrictMode) {
+ assignStrict(processIndex);
+ return;
+ }
+
+ // TODO: Start a timer for timeouts?
+}
+
+void Test262Runner::assignSloppy(int processIndex)
+{
+ QProcess &p = *processes[processIndex];
+ TestData &task = currentTasks[processIndex];
+
+ QJsonObject json;
+ json.insert("mode", "sloppy");
+ json.insert("testData", QString::fromUtf8(task.content));
+ json.insert("runAsModule", false);
+ json.insert("testCasePath", "");
+ json.insert("harnessForModules", "");
+ p.write(QJsonDocument(json).toJson(QJsonDocument::Compact));
+ p.write("\r\n");
+}
+
+void Test262Runner::assignStrict(int processIndex)
+{
+ QProcess &p = *processes[processIndex];
+ TestData &task = currentTasks[processIndex];
+
+ QJsonObject json;
+ json.insert("mode", "strict");
+ QString strictContent = "'use strict';\n" + QString::fromUtf8(task.content);
+ json.insert("testData", strictContent);
+ json.insert("runAsModule", task.runAsModuleCode);
+ json.insert("testCasePath", QFileInfo(testDir + "/test/" + task.test).absoluteFilePath());
+ json.insert("harnessForModules", QString::fromUtf8(task.harness));
+ p.write(QJsonDocument(json).toJson(QJsonDocument::Compact));
+ p.write("\r\n");
+}
+
+void Test262Runner::sendDone(int processIndex)
+{
+ QProcess &p = *processes[processIndex];
+
+ QJsonObject json;
+ json.insert("done", true);
+ p.write(QJsonDocument(json).toJson(QJsonDocument::Compact));
+ p.write("\r\n");
+}
+
+void Test262Runner::createProcesses()
+{
+ const int processCount = QThread::idealThreadCount();
+ qDebug() << "Running in parallel with" << processCount << "processes";
+ for (int i = 0; i < processCount; ++i) {
+ processes.emplace_back(std::make_unique<QProcess>());
+ QProcess &p = *processes[i];
+ QProcess::connect(&p, &QProcess::started, this, [&, i]() {
+ assignTaskOrTerminate(i);
+ });
+
+ QProcess::connect(&p, &QIODevice::readyRead, this, [&, i]() {
+ QProcess &p = *processes[i];
+ QString output;
+ while (output.isEmpty())
+ output = p.readLine();
+ QJsonDocument response = QJsonDocument::fromJson(output.toUtf8());
+
+ TestData &testData(currentTasks[i]);
+ auto mode = response["mode"].toString();
+ auto state = TestCase::State(response["resultState"].toInt(int(TestCase::State::Fails)));
+ auto errorMessage = response["resultErrorMessage"].toString();
+
+ auto &result = mode == "strict" ? testData.strictResult : testData.sloppyResult;
+ result = TestCase::Result(state, errorMessage);
+ if (testData.negative)
+ result.negateResult();
+
+ if (testData.stillNeedStrictRun) {
+ testData.stillNeedStrictRun = false;
+ assignStrict(i);
+ } else {
+ addResult(testData);
+ assignTaskOrTerminate(i);
+ }
+ });
+
+ QObject::connect(&p, &QProcess::finished, this,
+ [this, processCount, i](int exitCode, QProcess::ExitStatus status) {
+ if (status != QProcess::NormalExit || exitCode != 0) {
+ TestData &testData(currentTasks[i]);
+
+ auto &result = testData.stillNeedStrictRun
+ ? testData.sloppyResult
+ : testData.strictResult;
+ result = TestCase::Result(
+ TestCase::Crashes,
+ QStringLiteral("Process %1 of %2 exited with a non-normal status")
+ .arg(i).arg(processCount - 1));
+
+ addResult(testData);
+ }
+
+ --runningCount;
+ if (runningCount == 0)
+ loop.exit();
+ });
+
+ p.setProgram(QCoreApplication::applicationFilePath());
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ env.insert(u"runnerProcess"_s, u"1"_s);
+ p.setProcessEnvironment(env);
+ ++runningCount;
+ p.start();
+ }
+}
+
+class SingleTest : public QRunnable
+{
+public:
+ SingleTest(Test262Runner *runner, const TestData &data)
+ : runner(runner), data(data)
+ {}
+ void run() override;
+
+ Test262Runner *runner;
+ TestData data;
+};
+
+TestCase::Result getTestExecutionResult(QV4::ExecutionEngine &vm)
+{
+ TestCase::State state;
+ QString errorMessage;
+ if (vm.hasException) {
+ state = TestCase::State::Fails;
+ QV4::Scope scope(&vm);
+ QV4::ScopedValue val(scope, vm.catchException());
+ errorMessage = val->toQString();
+ } else {
+ state = TestCase::State::Passes;
+ }
+ return TestCase::Result(state, errorMessage);
+}
+
+void SingleTest::run()
+{
+ if (data.runInSloppyMode) {
+ QV4::ExecutionEngine vm;
+ Test262Runner::executeTest(vm, data.content);
+ TestCase::Result ok = getTestExecutionResult(vm);
+
+ if (data.negative)
+ ok.negateResult();
+
+ data.sloppyResult = ok;
+ } else {
+ data.sloppyResult = TestCase::Result(TestCase::Skipped);
+ }
+ if (data.runInStrictMode) {
+ QString testCasePath = QFileInfo(runner->testDirectory() + "/test/" + data.test).absoluteFilePath();
+ QByteArray c = "'use strict';\n" + data.content;
+
+ QV4::ExecutionEngine vm;
+ Test262Runner::executeTest(vm, c, testCasePath, data.harness, data.runAsModuleCode);
+ TestCase::Result ok = getTestExecutionResult(vm);
+
+ if (data.negative)
+ ok.negateResult();
+
+ data.strictResult = ok;
+ } else {
+ data.strictResult = TestCase::Result(TestCase::Skipped);
+ }
+ runner->addResult(data);
+}
+
+void Test262Runner::executeTest(QV4::ExecutionEngine &vm, const QString &testData,
+ const QString &testCasePath, const QString &harnessForModules,
+ bool runAsModule)
+{
+ QV4::Scope scope(&vm);
+ QV4::GlobalExtensions::init(vm.globalObject,
+ QJSEngine::ConsoleExtension | QJSEngine::GarbageCollectionExtension);
+ QV4::initD262(&vm);
+
+ if (runAsModule) {
+ const QUrl rootModuleUrl = QUrl::fromLocalFile(testCasePath);
+ // inject all modules with the harness
+ QVector<QUrl> modulesToLoad = { rootModuleUrl };
+ while (!modulesToLoad.isEmpty()) {
+ QUrl url = modulesToLoad.takeFirst();
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> module;
+
+ QFile f(url.toLocalFile());
+ if (f.open(QIODevice::ReadOnly)) {
+ QByteArray content = harnessForModules.toLocal8Bit() + f.readAll();
+ module = vm.compileModule(url.toString(),
+ QString::fromUtf8(content.constData(),content.size()),
+ QFileInfo(f).lastModified());
+ if (vm.hasException)
+ break;
+ } else {
+ vm.throwError(QStringLiteral("Could not load module"));
+ break;
+ }
+
+ const QStringList moduleRequests = module->baseCompilationUnit()->moduleRequests();
+ for (const QString &request: moduleRequests) {
+ const QUrl absoluteRequest = module->finalUrl().resolved(QUrl(request));
+ const auto module = vm.moduleForUrl(absoluteRequest);
+ if (module.native == nullptr && module.compiled == nullptr)
+ modulesToLoad << absoluteRequest;
+ }
+ }
+
+ if (!vm.hasException) {
+ const auto rootModule = vm.loadModule(rootModuleUrl);
+ if (rootModule.compiled && rootModule.compiled->instantiate())
+ rootModule.compiled->evaluate();
+ }
+ } else {
+ QV4::ScopedContext ctx(scope, vm.rootContext());
+
+ QV4::Script script(ctx, QV4::Compiler::ContextType::Global, testData);
+ script.parse();
+
+ if (!vm.hasException)
+ script.run();
+ }
+}
+
+void Test262Runner::runWithThreadPool()
+{
+ threadPool = new QThreadPool();
+ threadPool->setStackSize(16*1024*1024);
+ qDebug() << "Running in parallel with" << QThread::idealThreadCount() << "threads";
+
+ for (const TestCase &testCase : std::as_const(testCases)) {
+ TestData testData = getTestData(testCase);
+ if (testData.isExcluded || testData.async)
+ continue;
+ SingleTest *test = new SingleTest(this, testData);
+ threadPool->start(test);
+ }
+
+ while (!threadPool->waitForDone(10'000)) {
+ if (lcJsTest().isEnabled(QtDebugMsg)) {
+ // heartbeat, only needed when there is no other debug output
+ qDebug("test262: in progress...");
+ }
+ }
+}
+
bool Test262Runner::run()
{
if (!loadTests())
return false;
- if (flags & Parallel) {
- threadPool = new QThreadPool;
- threadPool->setStackSize(16*1024*1024);
- if (flags & Verbose)
- qDebug() << "Running in parallel with" << QThread::idealThreadCount() << "threads.";
- }
-
if (flags & ForceJIT)
qputenv("QV4_JIT_CALL_THRESHOLD", QByteArray("0"));
else if (flags & ForceBytecode)
@@ -136,14 +402,24 @@ bool Test262Runner::run()
for (auto it = testCases.constBegin(); it != testCases.constEnd(); ++it) {
auto c = it.value();
if (!c.skipTestCase) {
- int result = runSingleTest(c);
- if (result == -2)
- return false;
+ TestData data = getTestData(c);
+ if (data.isExcluded || data.async)
+ continue;
+
+ tasks.append(data);
}
}
- if (threadPool)
- threadPool->waitForDone();
+ if (command.isEmpty()) {
+#if QT_CONFIG(process)
+ createProcesses();
+ loop.exec();
+#else
+ runWithThreadPool();
+#endif
+ } else {
+ runAsExternalTests();
+ }
const bool testsOk = report();
@@ -167,7 +443,7 @@ bool Test262Runner::report()
if (c.strictResult.state == c.strictExpectation.state
&& c.sloppyResult.state == c.sloppyExpectation.state)
continue;
- auto report = [&](TestCase::Result expected, TestCase::Result result, const char *s) {
+ auto report = [&](const TestCase::Result &expected, const TestCase::Result &result, const char *s) {
if (result.state == TestCase::Crashes)
crashes << (it.key() + " crashed in " + s + " mode");
if (result.state == TestCase::Fails && expected.state == TestCase::Passes)
@@ -420,7 +696,10 @@ void Test262Runner::updateTestExpectations()
}
QTemporaryFile updatedExpectations;
- updatedExpectations.open();
+ if (!updatedExpectations.open()) {
+ qFatal("Could not open temporary TestExpectations file: %s",
+ qPrintable(updatedExpectations.errorString()));
+ }
while (!file.atEnd()) {
QByteArray originalLine = file.readLine();
@@ -458,9 +737,12 @@ void Test262Runner::writeTestExpectations()
QFile file(expectationsFile);
QTemporaryFile expectations;
- expectations.open();
+ if (!expectations.open()) {
+ qFatal("Could not open temporary TestExpectations file: %s",
+ qPrintable(expectations.errorString()));
+ }
- for (auto c : std::as_const(testCases)) {
+ for (const auto &c : std::as_const(testCases)) {
TestExpectationLine line = TestExpectationLine::fromTestCase(c);
expectations.write(line.toLine());
}
@@ -474,175 +756,50 @@ void Test262Runner::writeTestExpectations()
qWarning() << "Could not write new TestExpectations file at" << expectationsFile;
}
-static TestCase::Result executeTest(const QByteArray &data, bool runAsModule = false,
- const QString &testCasePath = QString(),
- const QByteArray &harnessForModules = QByteArray())
+void Test262Runner::runAsExternalTests()
{
- QString testData = QString::fromUtf8(data.constData(), data.size());
-
- QV4::ExecutionEngine vm;
-
- QV4::Scope scope(&vm);
-
- QV4::GlobalExtensions::init(vm.globalObject, QJSEngine::ConsoleExtension | QJSEngine::GarbageCollectionExtension);
- QV4::initD262(&vm);
-
- if (runAsModule) {
- const QUrl rootModuleUrl = QUrl::fromLocalFile(testCasePath);
- // inject all modules with the harness
- QVector<QUrl> modulesToLoad = { rootModuleUrl };
- while (!modulesToLoad.isEmpty()) {
- QUrl url = modulesToLoad.takeFirst();
- QQmlRefPointer<QV4::ExecutableCompilationUnit> module;
-
- QFile f(url.toLocalFile());
- if (f.open(QIODevice::ReadOnly)) {
- QByteArray content = harnessForModules + f.readAll();
- module = vm.compileModule(url.toString(), QString::fromUtf8(content.constData(), content.size()), QFileInfo(f).lastModified());
- if (vm.hasException)
- break;
- vm.injectCompiledModule(module);
- } else {
- vm.throwError(QStringLiteral("Could not load module"));
- break;
+ for (TestData &testData : tasks) {
+ auto runTest = [&] (const char *header, TestCase::Result *result) {
+ QTemporaryFile tempFile;
+ if (!tempFile.open()) {
+ qFatal("Could not open temporary test data file: %s",
+ qPrintable(tempFile.errorString()));
}
-
- for (const QString &request: module->moduleRequests()) {
- const QUrl absoluteRequest = module->finalUrl().resolved(QUrl(request));
- const auto module = vm.moduleForUrl(absoluteRequest);
- if (module.native == nullptr && module.compiled == nullptr)
- modulesToLoad << absoluteRequest;
+ tempFile.write(header);
+ tempFile.write(testData.content);
+ tempFile.close();
+
+ QProcess process;
+ process.start(command, QStringList(tempFile.fileName()));
+ if (!process.waitForFinished(-1) || process.error() == QProcess::FailedToStart) {
+ qWarning() << "Could not execute" << command;
+ *result = TestCase::Result(TestCase::Crashes);
}
- }
-
- if (!vm.hasException) {
- const auto rootModule = vm.loadModule(rootModuleUrl);
- if (rootModule.compiled && rootModule.compiled->instantiate(&vm))
- rootModule.compiled->evaluate();
- }
- } else {
- QV4::ScopedContext ctx(scope, vm.rootContext());
-
- QV4::Script script(ctx, QV4::Compiler::ContextType::Global, testData);
- script.parse();
-
- if (!vm.hasException)
- script.run();
- }
-
- if (vm.hasException) {
- QV4::Scope scope(&vm);
- QV4::ScopedValue val(scope, vm.catchException());
- return TestCase::Result(TestCase::Fails, val->toQString());
- }
- return TestCase::Result(TestCase::Passes);
-}
-
-class SingleTest : public QRunnable
-{
-public:
- SingleTest(Test262Runner *runner, const TestData &data)
- : runner(runner), data(data)
- {
- command = runner->command;
- }
- void run() override;
-
- void runExternalTest();
-
- QString command;
- Test262Runner *runner;
- TestData data;
-};
-
-void SingleTest::run()
-{
- if (!command.isEmpty()) {
- runExternalTest();
- return;
- }
-
- if (data.runInSloppyMode) {
- TestCase::Result ok = ::executeTest(data.content);
- if (data.negative)
- ok.negateResult();
-
- data.sloppyResult = ok;
- } else {
- data.sloppyResult = TestCase::Result(TestCase::Skipped);
- }
- if (data.runInStrictMode) {
- const QString testCasePath = QFileInfo(runner->testDir + "/test/" + data.test).absoluteFilePath();
- QByteArray c = "'use strict';\n" + data.content;
- TestCase::Result ok = ::executeTest(c, data.runAsModuleCode, testCasePath, data.harness);
- if (data.negative)
- ok.negateResult();
-
- data.strictResult = ok;
- } else {
- data.strictResult = TestCase::Result(TestCase::Skipped);
- }
- runner->addResult(data);
-}
-
-void SingleTest::runExternalTest()
-{
- auto runTest = [this] (const char *header, TestCase::Result *result) {
- QTemporaryFile tempFile;
- tempFile.open();
- tempFile.write(header);
- tempFile.write(data.content);
- tempFile.close();
-
- QProcess process;
-// if (flags & Verbose)
-// process.setReadChannelMode(QProcess::ForwardedChannels);
-
- process.start(command, QStringList(tempFile.fileName()));
- if (!process.waitForFinished(-1) || process.error() == QProcess::FailedToStart) {
- qWarning() << "Could not execute" << command;
- *result = TestCase::Result(TestCase::Crashes);
- }
- if (process.exitStatus() != QProcess::NormalExit) {
- *result = TestCase::Result(TestCase::Crashes);
- }
- bool ok = (process.exitCode() == EXIT_SUCCESS);
- if (data.negative)
- ok = !ok;
- *result = ok ? TestCase::Result(TestCase::Passes)
- : TestCase::Result(TestCase::Fails, process.readAllStandardError());
- };
-
- if (data.runInSloppyMode)
- runTest("", &data.sloppyResult);
- if (data.runInStrictMode)
- runTest("'use strict';\n", &data.strictResult);
-
- runner->addResult(data);
-}
-
-int Test262Runner::runSingleTest(TestCase testCase)
-{
- TestData data = getTestData(testCase);
-// qDebug() << "starting test" << data.test;
+ if (process.exitStatus() != QProcess::NormalExit) {
+ *result = TestCase::Result(TestCase::Crashes);
+ }
+ bool ok = (process.exitCode() == EXIT_SUCCESS);
+ if (testData.negative)
+ ok = !ok;
+ *result = ok ? TestCase::Result(TestCase::Passes)
+ : TestCase::Result(TestCase::Fails, process.readAllStandardError());
+ };
- if (data.isExcluded || data.async)
- return 0;
+ if (testData.runInSloppyMode)
+ runTest("", &testData.sloppyResult);
+ if (testData.runInStrictMode)
+ runTest("'use strict';\n", &testData.strictResult);
- if (threadPool) {
- SingleTest *test = new SingleTest(this, data);
- threadPool->start(test);
- return 0;
+ addResult(testData);
}
- SingleTest test(this, data);
- test.run();
- return 0;
}
void Test262Runner::addResult(TestCase result)
{
{
+#if !QT_CONFIG(process)
QMutexLocker locker(&mutex);
+#endif
Q_ASSERT(result.strictExpectation.state == testCases[result.test].strictExpectation.state);
Q_ASSERT(result.sloppyExpectation.state == testCases[result.test].sloppyExpectation.state);
testCases[result.test] = result;
@@ -847,3 +1004,5 @@ QByteArray Test262Runner::harness(const QByteArray &name)
harnessFiles.insert(name, content);
return content;
}
+
+QT_END_NAMESPACE
diff --git a/tests/auto/qml/ecmascripttests/qjstest/test262runner.h b/tests/auto/qml/ecmascripttests/test262runner.h
index e2bf26296f..a989ac5188 100644
--- a/tests/auto/qml/ecmascripttests/qjstest/test262runner.h
+++ b/tests/auto/qml/ecmascripttests/test262runner.h
@@ -1,14 +1,24 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#ifndef TEST262RUNNER_H
#define TEST262RUNNER_H
-#include <qstring.h>
-#include <qstringlist.h>
-#include <qset.h>
+
+#include <qeventloop.h>
#include <qmap.h>
#include <qmutex.h>
+#include <qprocess.h>
+#include <qqueue.h>
+#include <qset.h>
#include <qthreadpool.h>
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+struct ExecutionEngine;
+void initD262(ExecutionEngine *e);
+}
+
struct TestCase {
TestCase() = default;
TestCase(const QString &test)
@@ -40,16 +50,18 @@ struct TestCase {
}
};
- bool skipTestCase = false;
Result strictExpectation = Result(Passes);
Result sloppyExpectation = Result(Passes);
Result strictResult = Result(Skipped);
Result sloppyResult = Result(Skipped);
+ bool skipTestCase = false;
+ bool stillNeedStrictRun = false;
QString test;
};
struct TestData : TestCase {
+ TestData() = default;
TestData(const TestCase &testCase)
: TestCase(testCase) {}
// flags
@@ -67,8 +79,12 @@ struct TestData : TestCase {
QByteArray content;
};
-class Test262Runner
+class SingleTest;
+
+class Test262Runner : public QObject
{
+ Q_OBJECT
+
public:
Test262Runner(const QString &command, const QString &testDir, const QString &expectationsFile);
~Test262Runner();
@@ -95,6 +111,12 @@ public:
bool run();
bool report();
+ QString testDirectory() const { return testDir; }
+
+ static void executeTest(QV4::ExecutionEngine &vm, const QString &testData,
+ const QString &testCasePath = QString(),
+ const QString &harnessForModules = QString(),
+ bool runAsModule = false);
private:
friend class SingleTest;
@@ -102,7 +124,16 @@ private:
void loadTestExpectations();
void updateTestExpectations();
void writeTestExpectations();
- int runSingleTest(TestCase testCase);
+
+ void runWithThreadPool();
+
+ void runAsExternalTests();
+ void createProcesses();
+ void assignTaskOrTerminate(int processIndex);
+ void assignSloppy(int processIndex);
+ void assignStrict(int processIndex);
+ void sendDone(int processIndex);
+ QString readUntilNull(QProcess &p);
TestData getTestData(const TestCase &testCase);
void parseYaml(const QByteArray &content, TestData *data);
@@ -116,14 +147,21 @@ private:
QString expectationsFile;
int flags = 0;
- QMutex mutex;
QString filter;
QMap<QString, TestCase> testCases;
QHash<QByteArray, QByteArray> harnessFiles;
QThreadPool *threadPool = nullptr;
+ QMutex mutex;
+
+ QEventLoop loop;
+ std::vector<std::unique_ptr<QProcess>> processes;
+ int runningCount = 0;
+ QQueue<TestData> tasks;
+ QHash<int, TestData> currentTasks;
};
+QT_END_NAMESPACE
#endif
diff --git a/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp b/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
index 03c5b18474..11d724f795 100644
--- a/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
+++ b/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
@@ -1,11 +1,22 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-#include <QtTest/QtTest>
-#include <QProcess>
+#include <QFileInfo>
+#include <QJSEngine>
+#include <QJsonDocument>
+#include <QJsonObject>
#include <QLibraryInfo>
-#include <qjstest/test262runner.h>
+#include <QProcess>
#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtTest/QtTest>
+
+#include "test262runner.h"
+#include "private/qqmlbuiltinfunctions_p.h"
+#include "private/qv4arraybuffer_p.h"
+#include "private/qv4globalobject_p.h"
+#include "private/qv4script_p.h"
+
+#include <stdio.h>
class tst_EcmaScriptTests : public QQmlDataTest
{
@@ -40,7 +51,7 @@ static inline bool isNoise(QByteArrayView name)
#ifdef QT_V4_WANT_ES262_WARNINGS
return false;
#else
- const QByteArrayView noisy("qt.qml.compiler");
+ const QByteArrayView noisy("qt.qml.usedbeforedeclared");
return name.startsWith(noisy) && (name.size() <= noisy.size() || name[noisy.size()] == '.');
#endif
}
@@ -59,7 +70,7 @@ void tst_EcmaScriptTests::filterCategories(QLoggingCategory *category)
void tst_EcmaScriptTests::initTestCase()
{
QQmlDataTest::initTestCase();
- /* Suppress lcQmlCompiler's "qt.qml.compiler" warnings; we aren't in a
+ /* Suppress lcQmlCompiler's "qt.qml.usedbeforedeclared" warnings; we aren't in a
position to fix test262's many warnings and they flood messages so we
didn't get to see actual failures unless we passed -maxwarnings with a
huge value on the command-line (resulting in huge log output).
@@ -94,7 +105,74 @@ void tst_EcmaScriptTests::runJitted()
QVERIFY(result);
}
-QTEST_GUILESS_MAIN(tst_EcmaScriptTests)
+//// v RUNNER PROCESS MODE v ////
-#include "tst_ecmascripttests.moc"
+void readInput(bool &done, QString &mode, QString &testData, QString &testCasePath,
+ QString &harnessForModules, bool &runAsModule)
+{
+ QTextStream in(stdin);
+ QString input;
+ while (input.isEmpty())
+ input = in.readLine();
+
+ QJsonDocument json = QJsonDocument::fromJson(input.toUtf8());
+ done = json["done"].toBool(false);
+ mode = json["mode"].toString();
+ testData = json["testData"].toString();
+ testCasePath = json["testCasePath"].toString();
+ harnessForModules = json["harnessForModules"].toString();
+ runAsModule = json["runAsModule"].toBool(false);
+}
+
+void printResult(QV4::ExecutionEngine &vm, const QString &mode)
+{
+ QJsonObject result;
+ result.insert("mode", mode);
+ if (vm.hasException) {
+ QV4::Scope scope(&vm);
+ QV4::ScopedValue val(scope, vm.catchException());
+
+ result.insert("resultState", int(TestCase::State::Fails));
+ result.insert("resultErrorMessage", val->toQString());
+ } else {
+ result.insert("resultState", int(TestCase::State::Passes));
+ }
+ QTextStream(stdout) << QJsonDocument(result).toJson(QJsonDocument::Compact) << "\r\n";
+}
+
+void doRunnerProcess()
+{
+ bool done = false;
+ QString mode;
+ QString testData;
+ QString testCasePath;
+ QString harnessForModules;
+ bool runAsModule = false;
+
+ while (!done) {
+ QV4::ExecutionEngine vm;
+ readInput(done, mode, testData, testCasePath, harnessForModules, runAsModule);
+ if (done)
+ break;
+ Test262Runner::executeTest(vm, testData, testCasePath, harnessForModules, runAsModule);
+ printResult(vm, mode);
+ }
+}
+
+//// ^ RUNNER PROCESS MODE ^ ////
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+
+ if (qEnvironmentVariableIntValue("runnerProcess") == 1) {
+ doRunnerProcess();
+ } else {
+ tst_EcmaScriptTests tc;
+ QTEST_SET_MAIN_SOURCE_PATH
+ return QTest::qExec(&tc, argc, argv);
+ }
+}
+
+#include "tst_ecmascripttests.moc"
diff --git a/tests/auto/qml/linebylinelex/BLACKLIST b/tests/auto/qml/linebylinelex/BLACKLIST
deleted file mode 100644
index 0fd7f604e3..0000000000
--- a/tests/auto/qml/linebylinelex/BLACKLIST
+++ /dev/null
@@ -1,5 +0,0 @@
-# QTBUG-105697
-[testFormatter]
-android
-[testLineByLineLex]
-android
diff --git a/tests/auto/qml/linebylinelex/CMakeLists.txt b/tests/auto/qml/linebylinelex/CMakeLists.txt
index 868d13d7a7..92d956a972 100644
--- a/tests/auto/qml/linebylinelex/CMakeLists.txt
+++ b/tests/auto/qml/linebylinelex/CMakeLists.txt
@@ -2,14 +2,20 @@
## tst_linebylinelex Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_linebylinelex LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect linebyline test data
file(GLOB_RECURSE test_data_glob
- RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/..
- linebylinelex/data/*)
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ data/*)
# Collect qmlformat test data
file(GLOB_RECURSE test_data_glob2
- RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/..
- qmlformat/data/*)
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ ../qmlformat/data/*)
list(APPEND test_data ${test_data_glob} ${test_data_glob2})
qt_internal_add_test(tst_linebylinelex
@@ -19,17 +25,5 @@ qt_internal_add_test(tst_linebylinelex
Qt::Qml
Qt::QuickTestUtilsPrivate
TESTDATA ${test_data}
-)
-
-## Scopes:
-#####################################################################
-
-qt_internal_extend_target(tst_linebylinelex CONDITION ANDROID OR IOS
- DEFINES
- QT_QMLTEST_DATADIR=":/"
-)
-
-qt_internal_extend_target(tst_linebylinelex CONDITION NOT ANDROID AND NOT IOS
- DEFINES
- QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/.."
+ BUILTIN_TESTDATA
)
diff --git a/tests/auto/qml/linebylinelex/tst_linebylinelex.cpp b/tests/auto/qml/linebylinelex/tst_linebylinelex.cpp
index 02ce1f33f3..040ccfa9a6 100644
--- a/tests/auto/qml/linebylinelex/tst_linebylinelex.cpp
+++ b/tests/auto/qml/linebylinelex/tst_linebylinelex.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -13,7 +13,7 @@ QT_USE_NAMESPACE
using namespace Qt::StringLiterals;
using namespace QQmlJS;
-class TestLineByLineLex : public QQmlDataTest
+class TestLineByLineLex : public QObject
{
Q_OBJECT
@@ -21,7 +21,7 @@ public:
TestLineByLineLex();
private Q_SLOTS:
- void initTestCase() override;
+ void initTestCase();
void testLineByLineLex_data();
void testLineByLineLex();
@@ -34,17 +34,14 @@ private:
QString m_qmljsrootgenPath;
QString m_qmltyperegistrarPath;
- QString m_baseDir;
};
TestLineByLineLex::TestLineByLineLex()
- : QQmlDataTest(QT_QMLTEST_DATADIR), m_baseDir(QString::fromLocal8Bit(QT_QMLTEST_DATADIR))
{
}
void TestLineByLineLex::initTestCase()
{
- QQmlDataTest::initTestCase();
}
void TestLineByLineLex::testLineByLineLex_data()
@@ -59,22 +56,18 @@ void TestLineByLineLex::testLineByLineLex()
{
QFETCH(QString, filename);
- QString filePath = m_baseDir + u"/linebylinelex/data/"_s + filename;
+ QString filePath = QFINDTESTDATA("data/" + filename);
runLex(filePath);
}
void TestLineByLineLex::testFormatter_data()
{
QTest::addColumn<QString>("filename");
- QDir formatData(m_baseDir + u"/qmlformat/data"_s);
- bool hasTestData = false; // ### TODO: fix test to always have data
+ QDir formatData(QFINDTESTDATA("qmlformat/data"));
for (const QFileInfo &fInfo :
formatData.entryInfoList(QStringList({ u"*.qml"_s, u"*.js"_s }), QDir::Files)) {
QTest::newRow(qPrintable(fInfo.fileName())) << fInfo.absoluteFilePath();
- hasTestData = true;
}
- if (!hasTestData)
- QSKIP("No test data found!");
}
void TestLineByLineLex::testFormatter()
diff --git a/tests/auto/qml/parserstress/CMakeLists.txt b/tests/auto/qml/parserstress/CMakeLists.txt
index 876e8e30ee..5a2751504b 100644
--- a/tests/auto/qml/parserstress/CMakeLists.txt
+++ b/tests/auto/qml/parserstress/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_parserstress Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_parserstress LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/parserstress/tst_parserstress.cpp b/tests/auto/qml/parserstress/tst_parserstress.cpp
index 99af0247a8..a881d12294 100644
--- a/tests/auto/qml/parserstress/tst_parserstress.cpp
+++ b/tests/auto/qml/parserstress/tst_parserstress.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -41,9 +41,9 @@ QFileInfoList tst_parserstress::findJSFiles(const QDir &d)
rv << fileInfo;
}
- QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
+ const QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
QDir::NoSymLinks);
- foreach (const QString &dir, dirs) {
+ for (const QString &dir : dirs) {
QDir sub = d;
sub.cd(dir);
rv << findJSFiles(sub);
diff --git a/tests/auto/qml/qjsengine/CMakeLists.txt b/tests/auto/qml/qjsengine/CMakeLists.txt
index 84c738c34f..452eafa3ad 100644
--- a/tests/auto/qml/qjsengine/CMakeLists.txt
+++ b/tests/auto/qml/qjsengine/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qjsengine Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qjsengine LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -28,6 +34,7 @@ qt_internal_add_test(tst_qjsengine
Qt::GuiPrivate
Qt::Qml
Qt::QmlPrivate
+ Qt::QuickTestUtilsPrivate
LIBRARIES # special case
Threads::Threads # special case
TESTDATA ${test_data} "dummy_imports.qml"
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 21f4ff033b..7bf3b34f86 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -17,6 +17,9 @@
#include <QScopeGuard>
#include <QUrl>
#include <QModelIndex>
+#include <QtQml/qqmllist.h>
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <private/qv4functionobject_p.h>
#ifdef Q_CC_MSVC
#define NO_INLINE __declspec(noinline)
@@ -107,6 +110,8 @@ private slots:
void collectGarbageNestedWrappersTwoEngines();
void gcWithNestedDataStructure();
void stacktrace();
+ void unshiftAndSort();
+ void unshiftAndPushAndSort();
void numberParsing_data();
void numberParsing();
void automaticSemicolonInsertion();
@@ -136,7 +141,10 @@ private slots:
void reentrancy_Array();
void reentrancy_objectCreation();
void jsIncDecNonObjectProperty();
- void JSONparse();
+ void JSON_Parse();
+ void JSON_Stringify_data();
+ void JSON_Stringify();
+ void JSON_Stringify_WithReplacer_QTBUG_95324();
void arraySort();
void lookupOnDisappearingProperty();
void arrayConcat();
@@ -290,6 +298,8 @@ private slots:
void staticInNestedClasses();
void callElement();
+ void functionCtorGeneratedCUIsNotCollectedByGc();
+
void tdzViolations_data();
void tdzViolations();
@@ -301,6 +311,15 @@ private slots:
void callWithSpreadOnElement();
void spreadNoOverflow();
+ void symbolToVariant();
+
+ void garbageCollectedObjectMethodBase();
+
+ void optionalChainWithElementLookup();
+
+ void deleteDefineCycle();
+ void deleteFromSparseArray();
+
public:
Q_INVOKABLE QJSValue throwingCppMethod1();
Q_INVOKABLE void throwingCppMethod2();
@@ -377,7 +396,7 @@ void tst_QJSEngine::callQObjectSlot()
}
{
- QSignalSpy spy(&dummy, SIGNAL(slotWithArgumentsCalled(QString, QString, QString)));
+ QSignalSpy spy(&dummy, SIGNAL(slotWithArgumentsCalled(QString,QString,QString)));
eng.evaluate("dummy.slotToCall('arg', 'arg2');");
QCOMPARE(spy.size(), 1);
@@ -388,7 +407,7 @@ void tst_QJSEngine::callQObjectSlot()
}
{
- QSignalSpy spy(&dummy, SIGNAL(slotWithArgumentsCalled(QString, QString, QString)));
+ QSignalSpy spy(&dummy, SIGNAL(slotWithArgumentsCalled(QString,QString,QString)));
eng.evaluate("dummy.slotToCall('arg', 'arg2', 'arg3');");
QCOMPARE(spy.size(), 1);
@@ -399,7 +418,7 @@ void tst_QJSEngine::callQObjectSlot()
}
{
- QSignalSpy spy(&dummy, SIGNAL(slotWithOverloadedArgumentsCalled(QString, Qt::KeyboardModifier, Qt::KeyboardModifiers)));
+ QSignalSpy spy(&dummy, SIGNAL(slotWithOverloadedArgumentsCalled(QString,Qt::KeyboardModifier,Qt::KeyboardModifiers)));
eng.evaluate(QStringLiteral("dummy.slotToCall('arg', %1);").arg(QString::number(Qt::ControlModifier)));
QCOMPARE(spy.size(), 1);
@@ -411,7 +430,7 @@ void tst_QJSEngine::callQObjectSlot()
}
{
- QSignalSpy spy(&dummy, SIGNAL(slotWithTwoOverloadedArgumentsCalled(QString, Qt::KeyboardModifiers, Qt::KeyboardModifier)));
+ QSignalSpy spy(&dummy, SIGNAL(slotWithTwoOverloadedArgumentsCalled(QString,Qt::KeyboardModifiers,Qt::KeyboardModifier)));
QJSValue v = eng.evaluate(QStringLiteral("dummy.slotToCallTwoDefault('arg', %1);").arg(QString::number(Qt::MetaModifier | Qt::KeypadModifier)));
QCOMPARE(spy.size(), 1);
@@ -432,7 +451,7 @@ void tst_QJSEngine::callQObjectSlot()
eng.globalObject().setProperty(QStringLiteral("Qt"), value);
{
- QSignalSpy spy(&dummy, SIGNAL(slotWithOverloadedArgumentsCalled(QString, Qt::KeyboardModifier, Qt::KeyboardModifiers)));
+ QSignalSpy spy(&dummy, SIGNAL(slotWithOverloadedArgumentsCalled(QString,Qt::KeyboardModifier,Qt::KeyboardModifiers)));
QJSValue v = eng.evaluate(QStringLiteral("dummy.slotToCall('arg', Qt.ControlModifier);"));
QCOMPARE(spy.size(), 1);
@@ -443,7 +462,7 @@ void tst_QJSEngine::callQObjectSlot()
}
{
- QSignalSpy spy(&dummy, SIGNAL(slotWithTwoOverloadedArgumentsCalled(QString, Qt::KeyboardModifiers, Qt::KeyboardModifier)));
+ QSignalSpy spy(&dummy, SIGNAL(slotWithTwoOverloadedArgumentsCalled(QString,Qt::KeyboardModifiers,Qt::KeyboardModifier)));
QJSValue v = eng.evaluate(QStringLiteral("dummy.slotToCallTwoDefault('arg', Qt.MetaModifier | Qt.KeypadModifier);"));
QCOMPARE(spy.size(), 1);
@@ -905,7 +924,7 @@ void tst_QJSEngine::newQObjectRace()
{
int newObjectCount = 1000;
#if defined(Q_OS_QNX)
- newObjectCount = 256;
+ newObjectCount = 128;
#endif
for (int i=0;i<newObjectCount;++i)
{
@@ -932,7 +951,7 @@ void tst_QJSEngine::newQObject_ownership()
{
QJSValue v = eng.newQObject(ptr);
}
- eng.collectGarbage();
+ gc(*eng.handle(), GCFlags::DontSendPostedEvents);
if (ptr)
QGuiApplication::sendPostedEvents(ptr, QEvent::DeferredDelete);
QVERIFY(ptr.isNull());
@@ -944,16 +963,16 @@ void tst_QJSEngine::newQObject_ownership()
QJSValue v = eng.newQObject(ptr);
}
QObject *before = ptr;
- eng.collectGarbage();
+ gc(*eng.handle(), GCFlags::DontSendPostedEvents);
QCOMPARE(ptr.data(), before);
delete ptr;
}
{
- QObject *parent = new QObject();
- QObject *child = new QObject(parent);
+ std::unique_ptr<QObject> parent = std::make_unique<QObject>();
+ QObject *child = new QObject(parent.get());
QJSValue v = eng.newQObject(child);
QCOMPARE(v.toQObject(), child);
- delete parent;
+ parent.reset();
QCOMPARE(v.toQObject(), (QObject *)nullptr);
}
{
@@ -962,23 +981,22 @@ void tst_QJSEngine::newQObject_ownership()
{
QJSValue v = eng.newQObject(ptr);
}
- eng.collectGarbage();
+ gc(*eng.handle(), GCFlags::DontSendPostedEvents);
// no parent, so it should be like ScriptOwnership
if (ptr)
QGuiApplication::sendPostedEvents(ptr, QEvent::DeferredDelete);
QVERIFY(ptr.isNull());
}
{
- QObject *parent = new QObject();
- QPointer<QObject> child = new QObject(parent);
+ std::unique_ptr<QObject> parent = std::make_unique<QObject>();
+ QPointer<QObject> child = new QObject(parent.get());
QVERIFY(child != nullptr);
{
QJSValue v = eng.newQObject(child);
}
- eng.collectGarbage();
+ gc(*eng.handle(), GCFlags::DontSendPostedEvents);
// has parent, so it should be like QtOwnership
QVERIFY(child != nullptr);
- delete parent;
}
{
QPointer<QObject> ptr = new QObject();
@@ -987,7 +1005,7 @@ void tst_QJSEngine::newQObject_ownership()
QQmlEngine::setObjectOwnership(ptr.data(), QQmlEngine::CppOwnership);
QJSValue v = eng.newQObject(ptr);
}
- eng.collectGarbage();
+ gc(*eng.handle(), GCFlags::DontSendPostedEvents);
if (ptr)
QGuiApplication::sendPostedEvents(ptr, QEvent::DeferredDelete);
QVERIFY(!ptr.isNull());
@@ -1038,6 +1056,17 @@ private:
int m_called = 1;
};
+class TestQMetaObject2 : public QObject
+{
+ Q_OBJECT
+public:
+ Q_INVOKABLE TestQMetaObject2(int a) : m_called(a) {}
+ int called() const { return m_called; }
+
+private:
+ int m_called = 1;
+};
+
void tst_QJSEngine::newQObjectPropertyCache()
{
QScopedPointer<QObject> obj(new QObject);
@@ -1113,6 +1142,18 @@ void tst_QJSEngine::newQMetaObject() {
QCOMPARE(metaObject.property("C").toInt(), 2);
}
+ {
+ QJSEngine engine;
+ const QJSValue metaObject = engine.newQMetaObject(&TestQMetaObject2::staticMetaObject);
+ engine.globalObject().setProperty("Example"_L1, metaObject);
+
+ const QJSValue invalid = engine.evaluate("new Example()"_L1);
+ QVERIFY(invalid.isError());
+ QCOMPARE(invalid.toString(), "Error: Insufficient arguments"_L1);
+
+ const QJSValue valid = engine.evaluate("new Example(123)"_L1);
+ QCOMPARE(qjsvalue_cast<TestQMetaObject2 *>(valid)->called(), 123);
+ }
}
void tst_QJSEngine::exceptionInSlot()
@@ -1642,6 +1683,8 @@ void tst_QJSEngine::valueConversion_basic()
QCOMPARE(eng.fromScriptValue<unsigned short>(num), (unsigned short)(123));
QCOMPARE(eng.fromScriptValue<float>(num), float(123));
QCOMPARE(eng.fromScriptValue<double>(num), double(123));
+ QCOMPARE(eng.fromScriptValue<long>(num), long(123));
+ QCOMPARE(eng.fromScriptValue<ulong>(num), ulong(123));
QCOMPARE(eng.fromScriptValue<qlonglong>(num), qlonglong(123));
QCOMPARE(eng.fromScriptValue<qulonglong>(num), qulonglong(123));
}
@@ -1653,6 +1696,8 @@ void tst_QJSEngine::valueConversion_basic()
QCOMPARE(eng.fromScriptValue<unsigned short>(num), (unsigned short)(123));
QCOMPARE(eng.fromScriptValue<float>(num), float(123));
QCOMPARE(eng.fromScriptValue<double>(num), double(123));
+ QCOMPARE(eng.fromScriptValue<long>(num), long(123));
+ QCOMPARE(eng.fromScriptValue<ulong>(num), ulong(123));
QCOMPARE(eng.fromScriptValue<qlonglong>(num), qlonglong(123));
QCOMPARE(eng.fromScriptValue<qulonglong>(num), qulonglong(123));
}
@@ -1672,11 +1717,20 @@ void tst_QJSEngine::valueConversion_basic()
QCOMPARE(eng.fromScriptValue<QChar>(eng.toScriptValue(c)), c);
}
+ {
+ QList<QObject *> list = {this};
+ QQmlListProperty<QObject> prop(this, &list);
+ QJSValue jsVal = eng.toScriptValue(prop);
+ QCOMPARE(eng.fromScriptValue<QQmlListProperty<QObject>>(jsVal), prop);
+ }
+
QVERIFY(eng.toScriptValue(static_cast<void *>(nullptr)).isNull());
}
void tst_QJSEngine::valueConversion_QVariant()
{
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_DEPRECATED
QJSEngine eng;
// qScriptValueFromValue() should be "smart" when the argument is a QVariant
{
@@ -1686,6 +1740,8 @@ void tst_QJSEngine::valueConversion_QVariant()
}
// Checking nested QVariants
{
+ // ### Qt 7: QVariant nesting is evil; we should check if we can get rid of it
+ // main use case for it was QSignalSpy
QVariant tmp1;
QVariant tmp2(QMetaType::fromType<QVariant>(), &tmp1);
QCOMPARE(QMetaType::Type(tmp2.userType()), QMetaType::QVariant);
@@ -1764,6 +1820,7 @@ void tst_QJSEngine::valueConversion_QVariant()
QVERIFY(val.isObject());
QCOMPARE(val.property(42).toString(), map.value(QStringLiteral("42")).toString());
}
+ QT_WARNING_POP
}
void tst_QJSEngine::valueConversion_basic2()
@@ -1884,7 +1941,7 @@ void tst_QJSEngine::collectGarbage()
QPointer<QObject> ptr = new QObject();
QVERIFY(ptr != nullptr);
(void)eng.newQObject(ptr);
- eng.collectGarbage();
+ gc(*eng.handle(), GCFlags::DontSendPostedEvents);
if (ptr)
QGuiApplication::sendPostedEvents(ptr, QEvent::DeferredDelete);
QVERIFY(ptr.isNull());
@@ -1919,8 +1976,8 @@ void tst_QJSEngine::collectGarbageNestedWrappersTwoEngines()
QCOMPARE(engine1.evaluate("foobar.dummy.baz").toInt(), 42);
QCOMPARE(engine2.evaluate("foobar.dummy.baz").toInt(), 43);
- engine1.collectGarbage();
- engine2.collectGarbage();
+ gc(*engine1.handle());
+ gc(*engine2.handle());
// The GC should not collect dummy object wrappers neither in engine1 nor engine2, we
// verify that by checking whether the baz property still has its previous value.
@@ -2058,6 +2115,81 @@ void tst_QJSEngine::stacktrace()
}
}
+void tst_QJSEngine::unshiftAndSort()
+{
+ QJSEngine engine;
+ QJSValue func = engine.evaluate(R"""(
+ (function (objectArr, currIdx) {
+ objectArr.unshift({"sortIndex": currIdx});
+ objectArr.sort(function(a, b) {
+ if (a.sortIndex > b.sortIndex)
+ return 1;
+ if (a.sortIndex < b.sortIndex)
+ return -1;
+ return 0;
+ });
+ return objectArr;
+ })
+ )""");
+ QVERIFY(func.isCallable());
+ QJSValue objectArr = engine.newArray();
+
+ for (int i = 0; i < 5; ++i) {
+ objectArr = func.call({objectArr, i});
+ QVERIFY2(!objectArr.isError(), qPrintable(objectArr.toString()));
+ const int length = objectArr.property("length").toInt();
+
+ // It did add one element
+ QCOMPARE(length, i + 1);
+
+ for (int x = 0; x < length; ++x) {
+ // We didn't sort cruft into the array.
+ QVERIFY(!objectArr.property(x).isUndefined());
+
+ // The array is actually sorted.
+ QCOMPARE(objectArr.property(x).property("sortIndex").toInt(), x);
+ }
+ }
+}
+
+void tst_QJSEngine::unshiftAndPushAndSort()
+{
+ QJSEngine engine;
+ QJSValue func = engine.evaluate(R"""(
+ (function (objectArr, currIdx) {
+ objectArr.unshift({"sortIndex": currIdx});
+ objectArr.push({"sortIndex": currIdx + 1});
+ objectArr.sort(function(a, b) {
+ if (a.sortIndex > b.sortIndex)
+ return 1;
+ if (a.sortIndex < b.sortIndex)
+ return -1;
+ return 0;
+ });
+ return objectArr;
+ })
+ )""");
+ QVERIFY(func.isCallable());
+ QJSValue objectArr = engine.newArray();
+
+ for (int i = 0; i < 20; i += 2) {
+ objectArr = func.call({objectArr, i});
+ QVERIFY2(!objectArr.isError(), qPrintable(objectArr.toString()));
+ const int length = objectArr.property("length").toInt();
+
+ // It did add 2 elements
+ QCOMPARE(length, i + 2);
+
+ for (int x = 0; x < length; ++x) {
+ // We didn't sort cruft into the array.
+ QVERIFY(!objectArr.property(x).isUndefined());
+
+ // The array is actually sorted.
+ QCOMPARE(objectArr.property(x).property("sortIndex").toInt(), x);
+ }
+ }
+}
+
void tst_QJSEngine::numberParsing_data()
{
QTest::addColumn<QString>("string");
@@ -3305,13 +3437,65 @@ void tst_QJSEngine::jsIncDecNonObjectProperty()
}
}
-void tst_QJSEngine::JSONparse()
+void tst_QJSEngine::JSON_Parse()
{
QJSEngine eng;
QJSValue ret = eng.evaluate("var json=\"{\\\"1\\\": null}\"; JSON.parse(json);");
QVERIFY(ret.isObject());
}
+void tst_QJSEngine::JSON_Stringify_data()
+{
+ QTest::addColumn<QString>("object");
+ QTest::addColumn<QString>("json");
+
+ // Basic "smoke" test. More tests are provided by test262 suite.
+ // Don't test with multiple key-value pairs on the same level,
+ // because serialization order might not be deterministic.
+ // Note: parenthesis are required, otherwise objects will be interpretted as code blocks.
+ QTest::newRow("empty") << "({})" << "{}";
+ QTest::newRow("string") << "({a: 'b'})" << "{\"a\":\"b\"}";
+ QTest::newRow("number") << "({c: 42})" << "{\"c\":42}";
+ QTest::newRow("boolean") << "({d: true})" << "{\"d\":true}";
+ QTest::newRow("key is array") << "({[[12, 34]]: 56})" << "{\"12,34\":56}";
+ QTest::newRow("value is date") << "({d: new Date('2000-01-20T12:00:00.000Z')})" << "{\"d\":\"2000-01-20T12:00:00.000Z\"}";
+}
+
+void tst_QJSEngine::JSON_Stringify()
+{
+ QFETCH(QString, object);
+ QFETCH(QString, json);
+
+ QJSEngine eng;
+
+ QJSValue obj = eng.evaluate(object);
+ QVERIFY(obj.isObject());
+
+ QJSValue func = eng.evaluate("(function(obj) { return JSON.stringify(obj); })");
+ QVERIFY(func.isCallable());
+
+ QJSValue ret = func.call(QJSValueList{obj});
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), json);
+}
+
+void tst_QJSEngine::JSON_Stringify_WithReplacer_QTBUG_95324()
+{
+ QJSEngine eng;
+ QJSValue json = eng.evaluate(R"(
+ function replacer(k, v) {
+ if (this[k] instanceof Date) {
+ return Math.floor(this[k].getTime() / 1000.0);
+ }
+ return v;
+ }
+ const obj = {d: new Date('2000-01-20T12:00:00.000Z')};
+ JSON.stringify(obj, replacer);
+ )");
+ QVERIFY(json.isString());
+ QCOMPARE(json.toString(), QString::fromLatin1("{\"d\":948369600}"));
+}
+
void tst_QJSEngine::arraySort()
{
// tests that calling Array.sort with a bad sort function doesn't cause issues
@@ -3480,9 +3664,6 @@ void tst_QJSEngine::qRegularExpressionExport()
// effect at a given date (QTBUG-9770).
void tst_QJSEngine::dateRoundtripJSQtJS()
{
-#ifdef Q_OS_WIN
- QSKIP("This test fails on Windows due to a bug in QDateTime.");
-#endif
qint64 secs = QDate(2009, 1, 1).startOfDay(QTimeZone::UTC).toSecsSinceEpoch();
QJSEngine eng;
for (int i = 0; i < 8000; ++i) {
@@ -3497,9 +3678,6 @@ void tst_QJSEngine::dateRoundtripJSQtJS()
void tst_QJSEngine::dateRoundtripQtJSQt()
{
-#ifdef Q_OS_WIN
- QSKIP("This test fails on Windows due to a bug in QDateTime.");
-#endif
QDateTime qtDate = QDate(2009, 1, 1).startOfDay();
QJSEngine eng;
for (int i = 0; i < 8000; ++i) {
@@ -3513,9 +3691,6 @@ void tst_QJSEngine::dateRoundtripQtJSQt()
void tst_QJSEngine::dateConversionJSQt()
{
-#ifdef Q_OS_WIN
- QSKIP("This test fails on Windows due to a bug in QDateTime.");
-#endif
qint64 secs = QDate(2009, 1, 1).startOfDay(QTimeZone::UTC).toSecsSinceEpoch();
QJSEngine eng;
for (int i = 0; i < 8000; ++i) {
@@ -3740,7 +3915,7 @@ void tst_QJSEngine::prototypeChainGc()
QJSValue factory = engine.evaluate("(function() { return Object.create(Object.create({})); })");
QVERIFY(factory.isCallable());
QJSValue obj = factory.call();
- engine.collectGarbage();
+ gc(*engine.handle());
QJSValue proto = getProto.call(QJSValueList() << obj);
proto = getProto.call(QJSValueList() << proto);
@@ -3759,7 +3934,7 @@ void tst_QJSEngine::prototypeChainGc_QTBUG38299()
"delete mapping.prop1\n"
"\n");
// Don't hang!
- engine.collectGarbage();
+ gc(*engine.handle());
}
void tst_QJSEngine::dynamicProperties()
@@ -4403,6 +4578,12 @@ void tst_QJSEngine::tracing()
QTest::ignoreMessage(QtDebugMsg, "a (:1)\nb (:1)\nc (:1)\n%entry (:1)");
engine.evaluate("function a() { console.trace(); } function b() { a(); } function c() { b(); }");
engine.evaluate("c()");
+
+ QQmlTestMessageHandler messageHandler;
+ messageHandler.setIncludeCategoriesEnabled(true);
+ engine.evaluate("c()");
+ QCOMPARE(messageHandler.messageString(),
+ QLatin1String("js: a (:1)\nb (:1)\nc (:1)\n%entry (:1)"));
}
void tst_QJSEngine::asserts()
@@ -4497,7 +4678,6 @@ void tst_QJSEngine::privateMethods()
}
QVERIFY(privateMethods.contains("myPrivateMethod"));
- QVERIFY(privateMethods.contains("_q_reregisterTimers"));
privateMethods << QStringLiteral("deleteLater") << QStringLiteral("destroyed");
QJSValueIterator it(jsWrapper);
@@ -4571,7 +4751,7 @@ public:
bool called = false;
- Q_INVOKABLE void callMe(QQmlV4Function *) {
+ Q_INVOKABLE void callMe(QQmlV4FunctionPtr) {
called = true;
}
};
@@ -5749,6 +5929,38 @@ void tst_QJSEngine::callElement()
QCOMPARE(engine.evaluate(program).toString(), u"a"_s);
}
+void tst_QJSEngine::functionCtorGeneratedCUIsNotCollectedByGc()
+{
+ QJSEngine engine;
+ auto v4 = engine.handle();
+ QVERIFY(!v4->isGCOngoing);
+
+ // run gc until roots are collected
+ // we run the gc steps manually, so use "Forever" as the dealine to avoid interference
+ v4->memoryManager->gcStateMachine->deadline = QDeadlineTimer(QDeadlineTimer::Forever);
+ auto sm = v4->memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::InitMarkPersistentValues) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+
+ const QString program = "new Function('a', 'b', 'let x = \"Hello\"; return a + b');";
+ auto sumFunc = engine.evaluate(program);
+ QVERIFY(sumFunc.isCallable());
+ auto *function = QJSValuePrivate::asManagedType<QV4::JavaScriptFunctionObject>(&sumFunc);
+ auto *cu = function->d()->function->executableCompilationUnit();
+ QVERIFY(cu->runtimeStrings); // should exist for "Hello"
+ QVERIFY(cu->runtimeStrings[0]->isMarked());
+ while (sm->state != QV4::GCState::Invalid) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+
+ auto sum = sumFunc.call({QJSValue(12), QJSValue(13)});
+ QCOMPARE(sum.toInt(), 25);
+}
+
void tst_QJSEngine::tdzViolations_data()
{
QTest::addColumn<QString>("type");
@@ -6028,6 +6240,184 @@ void tst_QJSEngine::spreadNoOverflow()
QCOMPARE(result.errorType(), QJSValue::RangeError);
}
+void tst_QJSEngine::symbolToVariant()
+{
+ QJSEngine engine;
+ const QJSValue val = engine.newSymbol("asymbol");
+ QCOMPARE(val.toVariant(), QStringLiteral("Symbol(asymbol)"));
+
+ const QVariant retained = val.toVariant(QJSValue::RetainJSObjects);
+ QCOMPARE(retained.metaType(), QMetaType::fromType<QJSValue>());
+ QVERIFY(retained.value<QJSValue>().strictlyEquals(val));
+
+ QCOMPARE(val.toVariant(QJSValue::ConvertJSObjects), QStringLiteral("Symbol(asymbol)"));
+}
+
+class PACHelper : public QObject {
+ Q_OBJECT
+public:
+ Q_INVOKABLE bool shExpMatch(const QString &, const QString &) { return false; }
+ Q_INVOKABLE QString dnsResolve(const QString &) { return QString{}; }
+};
+
+class ProxyAutoConf {
+public:
+ void exposeQObjectMethodsAsGlobal(QJSEngine *engine, QObject *object)
+ {
+ QJSValue helper = engine->newQObject(object);
+ QJSValue g = engine->globalObject();
+ QJSValueIterator it(helper);
+ while (it.hasNext()) {
+ it.next();
+ if (!it.value().isCallable())
+ continue;
+ g.setProperty(it.name(), it.value());
+ }
+ }
+
+ bool parse(const QString & pacBytes)
+ {
+ jsFindProxyForURL = QJSValue();
+ engine = std::make_unique<QJSEngine>();
+ exposeQObjectMethodsAsGlobal(engine.get(), new PACHelper);
+ engine->evaluate(pacBytes);
+ jsFindProxyForURL = engine->globalObject().property(QStringLiteral("FindProxyForURL"));
+ return true;
+ }
+
+ QString findProxyForUrl(const QString &url, const QString &host)
+ {
+ QJSValueList args;
+ args << url << host;
+ gc(*engine->handle(), GCFlags::DontSendPostedEvents);
+ QJSValue callResult = jsFindProxyForURL.call(args);
+ return callResult.toString().trimmed();
+ }
+
+private:
+ std::unique_ptr<QJSEngine> engine;
+ QJSValue jsFindProxyForURL;
+};
+
+QString const pacstring = R"js(
+function FindProxyForURL(host) {
+ list_split_all = Array(
+ "oneoneoneoneo.oneo.oneo.oneoneo.one",
+ "twotwotwotwotw.otwo.twot.wotwotw.otw",
+ "threethreethr.eeth.reet.hreethr.eet",
+ "fourfourfourfo.urfo.urfo.urfourf.our",
+ "fivefivefivef.ivef.ivef.ivefive.fiv",
+ "sixsixsixsixsi.xsix.sixs.ixsixsi.xsi",
+ "sevensevenseve.nsev.ense.venseve.nse",
+ "eight.eighteigh.tei",
+ "*.nin.eninen.ine"
+ )
+ list_myip_direct =
+ "10.254.0.0/255.255.0.0"
+ for (i = 0; i < list_split_all.length; ++i)
+ for (j = 0; j < list_myip_direct.length; ++j)
+ shExpMatch(host, list_split_all)
+ shExpMatch()
+ dnsResolve()}
+)js";
+
+void tst_QJSEngine::garbageCollectedObjectMethodBase()
+{
+ ProxyAutoConf proxyConf;
+ bool pac_read = false;
+
+ const auto processUrl = [&](QString const &url, QString const &host)
+ {
+ if (!pac_read) {
+ proxyConf.parse(pacstring);
+ pac_read = true;
+ }
+ return proxyConf.findProxyForUrl(url, host);
+ };
+
+ const QString url = QStringLiteral("https://servername.domain.test");
+ const QString host = QStringLiteral("servername.domain.test");
+
+ for (size_t i = 0; i < 5; ++i) {
+ auto future = std::async(processUrl, url, host);
+ QCOMPARE(future.get(), QLatin1String("Error: Insufficient arguments"));
+ }
+}
+
+void tst_QJSEngine::optionalChainWithElementLookup()
+{
+ QJSEngine engine;
+
+ const QString program = R"js(
+ (function(xxx) { return xxx?.title["en"] ?? "A" })
+ )js";
+
+ QJSManagedValue func = QJSManagedValue(engine.evaluate(program), &engine);
+ QVERIFY(func.isFunction());
+
+ QCOMPARE(func.call({QJSValue::NullValue}).toString(), "A");
+ QCOMPARE(func.call({QJSValue::UndefinedValue}).toString(), "A");
+
+ const QJSValue nice
+ = engine.toScriptValue(QVariantMap { {"title", QVariantMap { {"en", "B"} } } });
+ QCOMPARE(func.call({nice}).toString(), "B");
+
+ const QJSValue naughty1
+ = engine.toScriptValue(QVariantMap { {"title", QVariantMap { {"fr", "B"} } } });
+ QCOMPARE(func.call({naughty1}).toString(), "A");
+
+ const QJSValue naughty2
+ = engine.toScriptValue(QVariantMap { {"foos", QVariantMap { {"en", "B"} } } });
+ QVERIFY(func.call({naughty2}).isUndefined());
+ QVERIFY(engine.hasError());
+ QCOMPARE(engine.catchError().toString(), "TypeError: Cannot read property 'en' of undefined");
+ QVERIFY(!engine.hasError());
+
+ QVERIFY(func.call({ QJSValue(4) }).isUndefined());
+ QVERIFY(engine.hasError());
+ QCOMPARE(engine.catchError().toString(), "TypeError: Cannot read property 'en' of undefined");
+ QVERIFY(!engine.hasError());
+}
+
+void tst_QJSEngine::deleteDefineCycle()
+{
+ QJSEngine engine;
+ QStringList stackTrace;
+
+ QJSValue result = engine.evaluate(QString::fromLatin1(R"(
+ let global = ({})
+
+ for (let j = 0; j < 1000; j++) {
+ for (let i = 0; i < 2; i++) {
+ const name = "test" + i
+ delete global[name]
+ Object.defineProperty(global, name, { get() { return 0 }, configurable: true })
+ }
+ }
+ )"), {}, 1, &stackTrace);
+ QVERIFY(stackTrace.isEmpty());
+}
+
+void tst_QJSEngine::deleteFromSparseArray()
+{
+ QJSEngine engine;
+
+ // Should not crash
+ const QJSValue result = engine.evaluate(QLatin1String(R"((function() {
+ let o = [];
+ o[10000] = 10;
+ o[20000] = 20;
+ for (let k in o)
+ delete o[k];
+ return o;
+ })())"));
+
+ QVERIFY(result.isArray());
+ QCOMPARE(result.property("length").toNumber(), 20001);
+ QVERIFY(result.property(10000).isUndefined());
+ QVERIFY(result.property(20000).isUndefined());
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"
diff --git a/tests/auto/qml/qjsmanagedvalue/CMakeLists.txt b/tests/auto/qml/qjsmanagedvalue/CMakeLists.txt
index 7400bc5f1f..3bc5c39bf9 100644
--- a/tests/auto/qml/qjsmanagedvalue/CMakeLists.txt
+++ b/tests/auto/qml/qjsmanagedvalue/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qjsmanagedvalue Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qjsmanagedvalue LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qjsmanagedvalue
SOURCES
tst_qjsmanagedvalue.cpp tst_qjsmanagedvalue.h
diff --git a/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.cpp b/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.cpp
index f11ae73a59..35f5bbadc4 100644
--- a/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.cpp
+++ b/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_qjsmanagedvalue.h"
@@ -542,7 +542,7 @@ void tst_QJSManagedValue::toVariant()
}
- // array
+ // variant list
{
auto handler = qInstallMessageHandler([](QtMsgType type, const QMessageLogContext &, const QString &) {
if (type == QtMsgType::QtWarningMsg)
@@ -553,12 +553,10 @@ void tst_QJSManagedValue::toVariant()
QVariantList listIn;
listIn << 123 << QStringLiteral("hello");
QJSManagedValue array(eng.toManagedValue(listIn));
- QVERIFY(array.isArray());
QCOMPARE(array.property(QStringLiteral("length")).toInt(), 2);
QVariant retained = array.toVariant();
- QCOMPARE(retained.metaType(), QMetaType::fromType<QJSValue>());
- QVERIFY(QJSManagedValue(retained.value<QJSValue>(), &eng).strictlyEquals(array));
+ QCOMPARE(retained.metaType(), QMetaType::fromType<QVariantList>());
QVariantList listOut = retained.toList();
QCOMPARE(listOut.size(), listIn.size());
@@ -566,7 +564,6 @@ void tst_QJSManagedValue::toVariant()
QCOMPARE(listOut.at(i), listIn.at(i));
// round-trip conversion
QJSManagedValue array2(eng.toManagedValue(retained));
- QVERIFY(array2.isArray());
QCOMPARE(array2.property(QStringLiteral("length")).toInt(), array.property(QStringLiteral("length")).toInt());
for (int i = 0; i < array.property(QStringLiteral("length")).toInt(); ++i)
QVERIFY(array2.property(i).strictlyEquals(array.property(i)));
@@ -1525,8 +1522,6 @@ void tst_QJSManagedValue::strictlyEquals()
{
QJSManagedValue var1(eng.toManagedValue(QVariant(QStringList() << QStringLiteral("a"))));
QJSManagedValue var2(eng.toManagedValue(QVariant(QStringList() << QStringLiteral("a"))));
- QVERIFY(var1.isArray());
- QVERIFY(var2.isArray());
QVERIFY(!var1.strictlyEquals(var2));
}
{
@@ -1582,22 +1577,22 @@ void tst_QJSManagedValue::castToPointer()
void tst_QJSManagedValue::engineDeleted()
{
- QJSEngine *eng = new QJSEngine;
+ std::unique_ptr<QJSEngine> eng = std::make_unique<QJSEngine>();
QObject *temp = new QObject(); // Owned by JS engine, as newQObject() sets JS ownership explicitly
QJSManagedValue v1(eng->toManagedValue(123));
QCOMPARE(v1.type(), QJSManagedValue::Number);
QJSManagedValue v2(eng->toManagedValue(QStringLiteral("ciao")));
QCOMPARE(v2.type(), QJSManagedValue::String);
- QJSManagedValue v3(eng->newObject(), eng);
+ QJSManagedValue v3(eng->newObject(), eng.get());
QCOMPARE(v3.type(), QJSManagedValue::Object);
QVERIFY(!v3.isNull());
- QJSManagedValue v4(eng->newQObject(temp), eng);
+ QJSManagedValue v4(eng->newQObject(temp), eng.get());
QCOMPARE(v4.type(), QJSManagedValue::Object);
QVERIFY(!v4.isNull());
- QJSManagedValue v5(QStringLiteral("Hello"), eng);
+ QJSManagedValue v5(QStringLiteral("Hello"), eng.get());
QCOMPARE(v2.type(), QJSManagedValue::String);
- delete eng;
+ eng.reset();
// You can still check the type, but anything involving the engine is obviously prohibited.
QCOMPARE(v1.type(), QJSManagedValue::Undefined);
@@ -1742,7 +1737,7 @@ void tst_QJSManagedValue::stringByIndex()
const QString testString = QStringLiteral("foobar");
QJSManagedValue str(testString, &engine);
- for (uint i = 0; i < testString.size(); ++i) {
+ for (qsizetype i = 0; i < testString.size(); ++i) {
QVERIFY(str.hasOwnProperty(i));
QVERIFY(str.hasProperty(i));
diff --git a/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.h b/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.h
index 6f6add433e..bb5a6be3ca 100644
--- a/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.h
+++ b/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.h
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TST_QJSMANAGEDVALUE_H
#define TST_QJSMANAGEDVALUE_H
diff --git a/tests/auto/qml/qjsonbinding/CMakeLists.txt b/tests/auto/qml/qjsonbinding/CMakeLists.txt
index 66f3e94e4c..fa80e764ef 100644
--- a/tests/auto/qml/qjsonbinding/CMakeLists.txt
+++ b/tests/auto/qml/qjsonbinding/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qjsonbinding Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qjsonbinding LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qjsonbinding/tst_qjsonbinding.cpp b/tests/auto/qml/qjsonbinding/tst_qjsonbinding.cpp
index 6235ff376d..450560833f 100644
--- a/tests/auto/qml/qjsonbinding/tst_qjsonbinding.cpp
+++ b/tests/auto/qml/qjsonbinding/tst_qjsonbinding.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQml/QtQml>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -67,7 +67,8 @@ private:
QByteArray tst_qjsonbinding::readAsUtf8(const QString &fileName)
{
QFile file(testFile(fileName));
- file.open(QIODevice::ReadOnly);
+ if (!file.open(QIODevice::ReadOnly))
+ qFatal("Cannot open file %s", qPrintable(fileName));
QTextStream stream(&file);
return stream.readAll().trimmed().toUtf8();
}
@@ -144,7 +145,11 @@ void tst_qjsonbinding::cppJsConversion()
{
QJSValue jsValue = eng.toScriptValue(jsonValue);
+#if QT_DEPRECATED_SINCE(6, 9)
+ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
QVERIFY(!jsValue.isVariant());
+ QT_WARNING_POP
+#endif
switch (jsonValue.type()) {
case QJsonValue::Null:
QVERIFY(jsValue.isNull());
@@ -193,7 +198,6 @@ void tst_qjsonbinding::cppJsConversion()
if (jsonValue.isObject()) {
QJsonObject jsonObject = jsonValue.toObject();
QJSValue jsObject = eng.toScriptValue(jsonObject);
- QVERIFY(!jsObject.isVariant());
QVERIFY(jsObject.isObject());
QJSValue stringified = stringify.call(QJSValueList() << jsObject);
@@ -205,7 +209,6 @@ void tst_qjsonbinding::cppJsConversion()
} else if (jsonValue.isArray()) {
QJsonArray jsonArray = jsonValue.toArray();
QJSValue jsArray = eng.toScriptValue(jsonArray);
- QVERIFY(!jsArray.isVariant());
QVERIFY(jsArray.isArray());
QJSValue stringified = stringify.call(QJSValueList() << jsArray);
diff --git a/tests/auto/qml/qjsprimitivevalue/CMakeLists.txt b/tests/auto/qml/qjsprimitivevalue/CMakeLists.txt
index 18b3ee938c..c709a5aa56 100644
--- a/tests/auto/qml/qjsprimitivevalue/CMakeLists.txt
+++ b/tests/auto/qml/qjsprimitivevalue/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qjsprimitivevalue Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qjsprimitivevalue LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qjsprimitivevalue
SOURCES
tst_qjsprimitivevalue.cpp
diff --git a/tests/auto/qml/qjsprimitivevalue/tst_qjsprimitivevalue.cpp b/tests/auto/qml/qjsprimitivevalue/tst_qjsprimitivevalue.cpp
index 7609842f17..232200e633 100644
--- a/tests/auto/qml/qjsprimitivevalue/tst_qjsprimitivevalue.cpp
+++ b/tests/auto/qml/qjsprimitivevalue/tst_qjsprimitivevalue.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qobject.h>
#include <QtQml/qjsengine.h>
@@ -19,6 +19,7 @@ private slots:
void unaryOperators();
void toFromVariant();
+ void coercion();
void ctor_invalid();
void ctor_undefinedWithEngine();
@@ -313,25 +314,37 @@ void tst_QJSPrimitiveValue::toFromVariant()
switch (operand.type()) {
case QJSPrimitiveValue::Undefined:
QVERIFY(!var.isValid());
+ QCOMPARE(operand.metaType(), QMetaType());
+ QCOMPARE(operand.data(), nullptr);
break;
case QJSPrimitiveValue::Null:
QCOMPARE(var.typeId(), QMetaType::Nullptr);
+ QCOMPARE(operand.metaType(), QMetaType::fromType<std::nullptr_t>());
+ QCOMPARE(operand.data(), nullptr);
break;
case QJSPrimitiveValue::Boolean:
QCOMPARE(var.typeId(), QMetaType::Bool);
QCOMPARE(var.toBool(), operand.toBoolean());
+ QCOMPARE(operand.metaType(), QMetaType::fromType<bool>());
+ QCOMPARE(*static_cast<const bool *>(operand.data()), operand.toBoolean());
break;
case QJSPrimitiveValue::Integer:
QCOMPARE(var.typeId(), QMetaType::Int);
QCOMPARE(var.toInt(), operand.toInteger());
+ QCOMPARE(operand.metaType(), QMetaType::fromType<int>());
+ QCOMPARE(*static_cast<const int *>(operand.data()), operand.toInteger());
break;
case QJSPrimitiveValue::Double:
QCOMPARE(var.typeId(), QMetaType::Double);
QCOMPARE(var.toDouble(), operand.toDouble());
+ QCOMPARE(operand.metaType(), QMetaType::fromType<double>());
+ QCOMPARE(*static_cast<const double *>(operand.data()), operand.toDouble());
break;
case QJSPrimitiveValue::String:
QCOMPARE(var.typeId(), QMetaType::QString);
QCOMPARE(var.toString(), operand.toString());
+ QCOMPARE(operand.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(*static_cast<const QString *>(operand.data()), operand.toString());
break;
}
@@ -344,6 +357,25 @@ void tst_QJSPrimitiveValue::toFromVariant()
}
}
+void tst_QJSPrimitiveValue::coercion()
+{
+ for (const QJSPrimitiveValue &operand : operands) {
+ QCOMPARE(operand.to<QJSPrimitiveValue::Undefined>(), QJSPrimitiveUndefined());
+ QCOMPARE(operand.to<QJSPrimitiveValue::Null>(), QJSPrimitiveNull());
+ QCOMPARE(operand.to<QJSPrimitiveValue::Boolean>(), operand.toBoolean());
+ QCOMPARE(operand.to<QJSPrimitiveValue::Integer>(), operand.toInteger());
+ QCOMPARE(operand.to<QJSPrimitiveValue::String>(), operand.toString());
+
+ const QJSPrimitiveValue lhs = operand.to<QJSPrimitiveValue::Double>();
+ QCOMPARE(lhs.type(), QJSPrimitiveValue::Double);
+ const double rhs = operand.toDouble();
+ if (std::isnan(rhs))
+ QVERIFY(std::isnan(lhs.toDouble()));
+ else
+ QCOMPARE(lhs.toDouble(), rhs);
+ }
+}
+
void tst_QJSPrimitiveValue::ctor_invalid()
{
QJSPrimitiveValue v;
diff --git a/tests/auto/qml/qjsvalue/CMakeLists.txt b/tests/auto/qml/qjsvalue/CMakeLists.txt
index fcd51fff44..212109c878 100644
--- a/tests/auto/qml/qjsvalue/CMakeLists.txt
+++ b/tests/auto/qml/qjsvalue/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qjsvalue Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qjsvalue LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# special case begin
# TODO: Prepare for removal, once Platform brings in Threads.
if(NOT TARGET Threads::Threads)
diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
index 516abed9e8..6a10b5910d 100644
--- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
+++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_qjsvalue.h"
@@ -19,11 +19,6 @@ tst_QJSValue::tst_QJSValue()
{
}
-tst_QJSValue::~tst_QJSValue()
-{
- delete engine;
-}
-
void tst_QJSValue::ctor_invalid()
{
QJSEngine eng;
@@ -369,10 +364,11 @@ void tst_QJSValue::toString()
// variant should use internal valueOf(), then fall back to QVariant::toString(),
// then fall back to "QVariant(typename)"
QJSValue variant = eng.toScriptValue(QPoint(10, 20));
+ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
QVERIFY(!variant.isVariant());
+ QT_WARNING_POP
QCOMPARE(variant.toString(), QString::fromLatin1("QPoint(10, 20)"));
variant = eng.toScriptValue(QUrl());
- QVERIFY(!variant.isVariant());
QVERIFY(variant.isUrl());
QVERIFY(variant.toString().isEmpty());
@@ -1085,13 +1081,8 @@ void tst_QJSValue::toVariant()
QVariantList listIn;
listIn << 123 << "hello";
QJSValue array = eng.toScriptValue(listIn);
- QVERIFY(array.isArray());
QCOMPARE(array.property("length").toInt(), 2);
- QVariant retained = array.toVariant(QJSValue::RetainJSObjects);
- QCOMPARE(retained.metaType(), QMetaType::fromType<QJSValue>());
- QVERIFY(retained.value<QJSValue>().strictlyEquals(array));
-
QVariant ret = array.toVariant();
QCOMPARE(ret.typeId(), QMetaType::QVariantList);
QVariantList listOut = ret.toList();
@@ -1100,7 +1091,6 @@ void tst_QJSValue::toVariant()
QCOMPARE(listOut.at(i), listIn.at(i));
// round-trip conversion
QJSValue array2 = eng.toScriptValue(ret);
- QVERIFY(array2.isArray());
QCOMPARE(array2.property("length").toInt(), array.property("length").toInt());
for (int i = 0; i < array.property("length").toInt(); ++i)
QVERIFY(array2.property(i).strictlyEquals(array.property(i)));
@@ -1124,6 +1114,25 @@ void tst_QJSValue::toVariant()
QCOMPARE(func.toVariant().metaType(), QMetaType::fromType<QJSValue>());
}
+
+ // object with custom prototype
+ {
+ QJSValue object = eng.evaluate(R"js(
+ (function(){
+ function Person(firstName, lastName) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
+ return new Person("John", "Doe");
+ })();
+ )js");
+ QVERIFY(object.isObject());
+ auto asVariant = object.toVariant();
+ QCOMPARE(asVariant.metaType(), QMetaType::fromType<QVariantMap>());
+ auto variantMap = asVariant.value<QVariantMap>();
+ QVERIFY(variantMap.contains("firstName"));
+ QCOMPARE(variantMap["firstName"].toString(), "John");
+ }
}
void tst_QJSValue::toPrimitive_data()
@@ -2345,8 +2354,6 @@ void tst_QJSValue::strictlyEquals()
{
QJSValue var1 = eng.toScriptValue(QVariant(QStringList() << "a"));
QJSValue var2 = eng.toScriptValue(QVariant(QStringList() << "a"));
- QVERIFY(var1.isArray());
- QVERIFY(var2.isArray());
QVERIFY(!var1.strictlyEquals(var2));
}
{
@@ -2586,7 +2593,7 @@ void tst_QJSValue::prettyPrinter()
void tst_QJSValue::engineDeleted()
{
- QJSEngine *eng = new QJSEngine;
+ std::unique_ptr<QJSEngine> eng = std::make_unique<QJSEngine>();
QObject *temp = new QObject(); // Owned by JS engine, as newQObject() sets JS ownership explicitly
QJSValue v1 = eng->toScriptValue(123);
QVERIFY(v1.isNumber());
@@ -2599,7 +2606,7 @@ void tst_QJSValue::engineDeleted()
QJSValue v5 = "Hello";
QVERIFY(v2.isString());
- delete eng;
+ eng.reset();
QVERIFY(!v1.isUndefined()); // Primitive value is stored inline
QVERIFY(v2.isUndefined());
@@ -2810,6 +2817,7 @@ void tst_QJSValue::deleteFromDifferentThread()
thread->start();
condition.wait(&mutex);
QTRY_VERIFY(thread->isFinished());
+ storage.clearFreePageHint();
QTRY_COMPARE(storage.firstPage, nullptr);
#endif
}
diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.h b/tests/auto/qml/qjsvalue/tst_qjsvalue.h
index 5b77bc2e15..459c0535c0 100644
--- a/tests/auto/qml/qjsvalue/tst_qjsvalue.h
+++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TST_QJSVALUE_H
#define TST_QJSVALUE_H
@@ -16,7 +16,6 @@ class tst_QJSValue : public QObject
public:
tst_QJSValue();
- virtual ~tst_QJSValue();
private slots:
void ctor_invalid();
@@ -129,11 +128,9 @@ private slots:
private:
void newEngine()
{
- if (engine)
- delete engine;
- engine = new QJSEngine();
+ engine = std::make_unique<QJSEngine>();
}
- QJSEngine *engine;
+ std::unique_ptr<QJSEngine> engine;
};
#endif
diff --git a/tests/auto/qml/qjsvalueiterator/CMakeLists.txt b/tests/auto/qml/qjsvalueiterator/CMakeLists.txt
index 85ac6c7a58..961674e50d 100644
--- a/tests/auto/qml/qjsvalueiterator/CMakeLists.txt
+++ b/tests/auto/qml/qjsvalueiterator/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qjsvalueiterator Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qjsvalueiterator LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qjsvalueiterator
SOURCES
tst_qjsvalueiterator.cpp
diff --git a/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp b/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp
index e329cf948f..a671bf42e2 100644
--- a/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp
+++ b/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -447,7 +447,7 @@ void tst_QJSValueIterator::iterateNonObject()
void tst_QJSValueIterator::iterateOverObjectFromDeletedEngine()
{
- QJSEngine *engine = new QJSEngine;
+ std::unique_ptr<QJSEngine> engine = std::make_unique<QJSEngine>();
QJSValue objet = engine->newObject();
// populate object with properties
@@ -465,7 +465,7 @@ void tst_QJSValueIterator::iterateOverObjectFromDeletedEngine()
it.next();
QVERIFY(properties.contains(it.name()));
- delete engine;
+ engine.reset();
QVERIFY(objet.isUndefined());
QVERIFY(it.name().isEmpty());
diff --git a/tests/auto/qml/qml/CMakeLists.txt b/tests/auto/qml/qml/CMakeLists.txt
index a696d80c4d..39056384de 100644
--- a/tests/auto/qml/qml/CMakeLists.txt
+++ b/tests/auto/qml/qml/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qml LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -15,4 +21,6 @@ qt_internal_add_test(tst_qml
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
LIBRARIES
Qt::QuickTestUtilsPrivate
+ Qt::Gui
+ Qt::GuiPrivate
)
diff --git a/tests/auto/qml/qml/data/resizeItem.qml b/tests/auto/qml/qml/data/resizeItem.qml
new file mode 100644
index 0000000000..c416451ccc
--- /dev/null
+++ b/tests/auto/qml/qml/data/resizeItem.qml
@@ -0,0 +1,28 @@
+import QtQuick
+
+Rectangle {
+ id: rect
+ color: "green"
+
+ Timer {
+ id: exitTimer
+ running: false
+ onTriggered: Qt.quit()
+ }
+
+ Timer {
+ id: resizeTimer
+ running: false
+ onTriggered: {
+ rect.width = 100
+ rect.height = 50
+ exitTimer.start()
+ }
+ }
+
+ Window.onHeightChanged: {
+ if (rect.Window.width > 0)
+ console.info("window", rect.Window.width, rect.Window.height, "content", rect.width, rect.height)
+ resizeTimer.start()
+ }
+}
diff --git a/tests/auto/qml/qml/data/sizedItem.qml b/tests/auto/qml/qml/data/sizedItem.qml
new file mode 100644
index 0000000000..edcb0e8629
--- /dev/null
+++ b/tests/auto/qml/qml/data/sizedItem.qml
@@ -0,0 +1,19 @@
+import QtQuick
+
+Rectangle {
+ id: rect
+ color: "blue"
+ width: 200; height: 150
+
+ Timer {
+ id: exitTimer
+ running: false
+ onTriggered: Qt.quit()
+ }
+
+ Window.onHeightChanged: {
+ if (rect.Window.width > 0)
+ console.info("window", rect.Window.width, rect.Window.height, "content", rect.width, rect.height)
+ exitTimer.restart()
+ }
+}
diff --git a/tests/auto/qml/qml/data/unsizedItem.qml b/tests/auto/qml/qml/data/unsizedItem.qml
new file mode 100644
index 0000000000..e32784762f
--- /dev/null
+++ b/tests/auto/qml/qml/data/unsizedItem.qml
@@ -0,0 +1,18 @@
+import QtQuick
+
+Rectangle {
+ id: rect
+ color: "green"
+
+ Timer {
+ id: exitTimer
+ running: false
+ onTriggered: Qt.quit()
+ }
+
+ Window.onHeightChanged: {
+ if (rect.Window.width > 0)
+ console.info("window", rect.Window.width, rect.Window.height, "content", rect.width, rect.height)
+ exitTimer.restart()
+ }
+}
diff --git a/tests/auto/qml/qml/tst_qml.cpp b/tests/auto/qml/qml/tst_qml.cpp
index de884d8257..befc68d443 100644
--- a/tests/auto/qml/qml/tst_qml.cpp
+++ b/tests/auto/qml/qml/tst_qml.cpp
@@ -1,11 +1,16 @@
// Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtCore/qlibraryinfo.h>
#include <QtCore/qprocess.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpa/qplatformintegration.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
+Q_LOGGING_CATEGORY(lcQml, "qt.qml.tests");
+
class tst_qml : public QQmlDataTest
{
Q_OBJECT
@@ -15,6 +20,8 @@ public:
private slots:
void initTestCase() override;
void nonWindow();
+ void itemAndWindowGeometry_data();
+ void itemAndWindowGeometry();
private:
QString qmlPath;
@@ -42,6 +49,124 @@ void tst_qml::nonWindow()
QCOMPARE(qml.exitCode(), 0); // Should not exit with code 2
}
+void tst_qml::itemAndWindowGeometry_data()
+{
+ QTest::addColumn<QString>("config");
+ QTest::addColumn<QString>("geometry");
+ QTest::addColumn<QString>("qmlfile");
+ QTest::addColumn<QSize>("expectedWindowSize");
+ QTest::addColumn<QSize>("expectedContentSize");
+
+ const QString none; // empty string
+
+ auto sizeOrInvalid = [](int w, int h) {
+ static const bool wm = QGuiApplicationPrivate::platformIntegration()->
+ hasCapability(QPlatformIntegration::WindowManagement);
+ return wm ? QSize(w, h) : QSize();
+ };
+
+ QTest::newRow("default: unsized")
+ << none << none << "unsizedItem.qml"
+ << QSize() << QSize(); // default size depends on window system
+ QTest::newRow("default: unsized with geometry")
+ << none << "100x100+50+50" << "unsizedItem.qml"
+ << sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
+ QTest::newRow("resizeToItem: unsized")
+ << "resizeToItem" << none << "unsizedItem.qml"
+ << QSize() << QSize(0, 0);
+ QTest::newRow("resizeToItem: unsized with geometry")
+ << "resizeToItem" << "100x100+50+50" << "unsizedItem.qml"
+ << sizeOrInvalid(100, 100) << QSize(0, 0);
+
+ QTest::newRow("default: sized")
+ << none << none << "sizedItem.qml"
+ << QSize() << QSize();
+ QTest::newRow("default: sized with geometry")
+ << none << "100x100+50+50" << "sizedItem.qml"
+ << sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
+ QTest::newRow("resizeToItem: sized")
+ << "resizeToItem" << none << "sizedItem.qml"
+ << sizeOrInvalid(200, 150) << sizeOrInvalid(200, 150);
+ QTest::newRow("resizeToItem: sized with geometry")
+ << "resizeToItem" << "320x240+50+50" << "sizedItem.qml"
+ << sizeOrInvalid(320, 240) << QSize(200, 150);
+
+ QTest::newRow("default: resizing")
+ << none << none << "resizeItem.qml"
+ << QSize() << QSize();
+ QTest::newRow("default: resizing with geometry")
+ << none << "100x100+50+50" << "resizeItem.qml"
+ << sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
+ QTest::newRow("resizeToItem: resizing")
+ << "resizeToItem" << none << "resizeItem.qml"
+ << sizeOrInvalid(100, 50) << sizeOrInvalid(100, 50);
+ QTest::newRow("resizeToItem: resizing with geometry")
+ << "resizeToItem" << "320x240+50+50" << "resizeItem.qml"
+ << sizeOrInvalid(100, 50) << sizeOrInvalid(100, 50);
+}
+
+/*
+ - A root Item will get put into a Window depending on config (implementations in
+ tools/qml/ResizeItemToWindow.qml and ResizeWindowToItem.qml).
+ - The window system will enforce a minimum size.
+ - In the default configuration, the root Item should then get resized to fit
+ (QTBUG-114068 / QTBUG-116753).
+ - In resizeToItem configuration, if the item width/height are not set, the window would
+ try to be 0x0, but the window system won't allow it.
+ - This also tests the `--qwindowgeometry` argument: with the default config, the
+ item should be resized to fit, but not with `-c resizeToItem`.
+*/
+void tst_qml::itemAndWindowGeometry()
+{
+#ifdef Q_OS_WIN
+ QSKIP("console.info does not go to stderr on Windows.");
+#endif
+
+ QFETCH(QString, config);
+ QFETCH(QString, geometry);
+ QFETCH(QString, qmlfile);
+ QFETCH(QSize, expectedWindowSize);
+ QFETCH(QSize, expectedContentSize);
+
+ QStringList args;
+ if (!config.isEmpty())
+ args << "-c" << config;
+ if (!geometry.isEmpty())
+ args << "--qwindowgeometry" << geometry;
+ args << testFile(qmlfile);
+ QProcess qml;
+ qml.start(qmlPath, args);
+ QVERIFY(qml.waitForFinished());
+ QCOMPARE(qml.exitStatus(), QProcess::NormalExit);
+ const QByteArray output = qml.readAllStandardError();
+ const auto sizeLineIndex = output.lastIndexOf("window");
+ QCOMPARE_GE(sizeLineIndex, 0);
+ const auto newlineIndex = output.indexOf('\n', sizeLineIndex);
+ QCOMPARE_GT(newlineIndex, sizeLineIndex);
+ // expect a line like "window 120 120 content 120 120"
+ const auto sizes = output.sliced(sizeLineIndex, newlineIndex - sizeLineIndex).split(' ');
+ QCOMPARE_GE(sizes.size(), 6);
+ QCOMPARE(sizes[0], "window");
+ QCOMPARE(sizes[3], "content");
+ const QSize windowSize(sizes[1].toInt(), sizes[2].toInt());
+ const QSize contentSize(sizes[4].toInt(), sizes[5].toInt());
+ qCDebug(lcQml) << sizes
+ << "window" << windowSize << "expect" << expectedWindowSize
+ << "content" << contentSize << "expect" << expectedContentSize;
+ QVERIFY(!windowSize.isEmpty());
+ if (config != "resizeToItem") {
+ // default config:
+ // ResizeItemToWindow.qml should have resized the item to its window
+ QCOMPARE(contentSize, windowSize);
+ }
+ // windowSize can be off-by-one on hidpi (e.g. QT_SCALE_FACTOR=2 on xcb);
+ // perhaps that's a bug somewhere, but so far we aren't testing hidpi on CI
+ if (expectedWindowSize.isValid())
+ QCOMPARE(windowSize, expectedWindowSize);
+ if (expectedContentSize.isValid())
+ QCOMPARE(contentSize, expectedContentSize);
+}
+
QTEST_MAIN(tst_qml)
#include <tst_qml.moc>
diff --git a/tests/auto/qml/qmlbasicapp/CMakeLists.txt b/tests/auto/qml/qmlbasicapp/CMakeLists.txt
index 8328a6b3f4..add4c560a8 100644
--- a/tests/auto/qml/qmlbasicapp/CMakeLists.txt
+++ b/tests/auto/qml/qmlbasicapp/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlbasicapp LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qmlbasicapp
SOURCES
tst_qmlbasicapp.cpp
diff --git a/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.cpp b/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.cpp
index 7f2736a76b..f3846569cb 100644
--- a/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.cpp
+++ b/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "timemodel.h"
diff --git a/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.h b/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.h
index b42542be31..2cc8f2e756 100644
--- a/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.h
+++ b/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TIMEMODEL_H
#define TIMEMODEL_H
diff --git a/tests/auto/qml/qmlbasicapp/main.qml b/tests/auto/qml/qmlbasicapp/main.qml
index 37598a5235..8c10b0881f 100644
--- a/tests/auto/qml/qmlbasicapp/main.qml
+++ b/tests/auto/qml/qmlbasicapp/main.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import TimeExample2 // import types from the plugin
import BasicExtension
diff --git a/tests/auto/qml/qmlbasicapp/manual_imports.cpp b/tests/auto/qml/qmlbasicapp/manual_imports.cpp
index 61df826af4..57adb572dd 100644
--- a/tests/auto/qml/qmlbasicapp/manual_imports.cpp
+++ b/tests/auto/qml/qmlbasicapp/manual_imports.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlextensionplugin.h>
diff --git a/tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp b/tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp
index fd72a0910f..3b9028154c 100644
--- a/tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp
+++ b/tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QQmlEngine>
#include <QQmlComponent>
diff --git a/tests/auto/qml/qmlcachegen/CMakeLists.txt b/tests/auto/qml/qmlcachegen/CMakeLists.txt
index d92d5e6166..d88de460e9 100644
--- a/tests/auto/qml/qmlcachegen/CMakeLists.txt
+++ b/tests/auto/qml/qmlcachegen/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmlcachegen Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlcachegen LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -22,6 +28,7 @@ qt_internal_add_test(tst_qmlcachegen
Qt::Gui
Qt::QmlPrivate
Qt::QuickTestUtilsPrivate
+ Qt::QmlCompilerPrivate
TESTDATA ${test_data}
)
diff --git a/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsClean.qml b/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsClean.qml
new file mode 100644
index 0000000000..b48004dc87
--- /dev/null
+++ b/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsClean.qml
@@ -0,0 +1,11 @@
+import QtQml
+
+QtObject {
+ property int i: 100
+ property int j: i * 2
+
+ function s() : string {
+ let s = "abc"
+ return s + "def "
+ }
+}
diff --git a/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsMixed.qml b/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsMixed.qml
new file mode 100644
index 0000000000..3d96760e96
--- /dev/null
+++ b/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsMixed.qml
@@ -0,0 +1,7 @@
+import QtQml
+
+QtObject {
+ property int i: Math.max(1, 2) // OK
+ function f() { return 1 } // Error: No specified return type
+ property string s: g() // Error: g?
+}
diff --git a/tests/auto/qml/qmlcachegen/data/aotstats/cachegentest.qrc b/tests/auto/qml/qmlcachegen/data/aotstats/cachegentest.qrc
new file mode 100644
index 0000000000..4f156ad2ef
--- /dev/null
+++ b/tests/auto/qml/qmlcachegen/data/aotstats/cachegentest.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/cachegentest">
+ <file alias="qmldir">qmldir</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/qml/qmlcachegen/data/aotstats/qmldir b/tests/auto/qml/qmlcachegen/data/aotstats/qmldir
new file mode 100644
index 0000000000..72047cc99d
--- /dev/null
+++ b/tests/auto/qml/qmlcachegen/data/aotstats/qmldir
@@ -0,0 +1,3 @@
+module cachegentest
+AotstatsClean 254.0 AotstatsClean.qml
+AotstatsMixed 254.0 AotstatsMixed.qml
diff --git a/tests/auto/qml/qmlcachegen/data/truncateTest.qml b/tests/auto/qml/qmlcachegen/data/truncateTest.qml
new file mode 100644
index 0000000000..fee768cf77
--- /dev/null
+++ b/tests/auto/qml/qmlcachegen/data/truncateTest.qml
@@ -0,0 +1,764 @@
+import QtQuick 2.15
+import QtQuick.Layouts 2.15
+
+Item {
+ width: 400
+ height: 400
+
+ component Button : Item {
+ property string text
+ property Item background
+ }
+
+ ColumnLayout {
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+
+ }
+}
diff --git a/tests/auto/qml/qmlcachegen/scriptstringprops.h b/tests/auto/qml/qmlcachegen/scriptstringprops.h
index 521455c098..96c86f1c59 100644
--- a/tests/auto/qml/qmlcachegen/scriptstringprops.h
+++ b/tests/auto/qml/qmlcachegen/scriptstringprops.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef SCRIPT_STRING_PROPS_H
#define SCRIPT_STRING_PROPS_H
diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
index 60d4a5df32..34ad3bbc98 100644
--- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
+++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
@@ -1,8 +1,9 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
+#include <QJsonDocument>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QProcess>
@@ -11,6 +12,7 @@
#include <QSysInfo>
#include <QLoggingCategory>
#include <private/qqmlcomponent_p.h>
+#include <private/qqmljscompilerstats_p.h>
#include <private/qqmlscriptdata_p.h>
#include <private/qv4compileddata_p.h>
#include <qtranslator.h>
@@ -63,8 +65,14 @@ private slots:
void inlineComponent();
void posthocRequired();
+ void gracefullyHandleTruncatedCacheFile();
+
void scriptStringCachegenInteraction();
void saveableUnitPointer();
+
+ void aotstatsSerialization();
+ void aotstatsGeneration_data();
+ void aotstatsGeneration();
};
// A wrapper around QQmlComponent to ensure the temporary reference counts
@@ -349,7 +357,7 @@ void tst_qmlcachegen::signalHandlerParameters()
};
QVERIFY(isStringIndexInStringTable(compilationUnit->objectAt(0)->signalAt(0)->parameterAt(0)->nameIndex));
- QVERIFY(!compilationUnit->dynamicStrings.isEmpty());
+ QVERIFY(!compilationUnit->baseCompilationUnit()->dynamicStrings.isEmpty());
}
}
@@ -714,7 +722,8 @@ void tst_qmlcachegen::moduleScriptImport()
{
auto componentPrivate = QQmlComponentPrivate::get(&component);
QVERIFY(componentPrivate);
- auto compilationUnit = componentPrivate->compilationUnit->dependentScripts.first()->compilationUnit();
+ auto compilationUnit = componentPrivate->compilationUnit->dependentScriptsPtr()
+ ->first()->compilationUnit();
QVERIFY(compilationUnit);
auto unitData = compilationUnit->unitData();
QVERIFY(unitData);
@@ -839,6 +848,23 @@ void tst_qmlcachegen::posthocRequired()
qPrintable(component.errorString()));
}
+void tst_qmlcachegen::gracefullyHandleTruncatedCacheFile()
+{
+#if defined(QTEST_CROSS_COMPILED)
+ QSKIP("Cannot call qmlcachegen on cross-compiled target.");
+#endif
+
+ bool ok = generateCache(testFile("truncateTest.qml"));
+ QVERIFY(ok);
+ const QString qmlcFile = testFile("truncateTest.qmlc");
+ QVERIFY(QFile::exists(qmlcFile));
+ QFile::resize(qmlcFile, QFileInfo(qmlcFile).size() / 2);
+ QQmlEngine engine;
+ CleanlyLoadingComponent component(&engine, testFileUrl("truncateTest.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+}
+
void tst_qmlcachegen::scriptStringCachegenInteraction()
{
#if defined(QTEST_CROSS_COMPILED)
@@ -875,6 +901,133 @@ void tst_qmlcachegen::saveableUnitPointer()
QCOMPARE(unit.flags, flags);
}
+void tst_qmlcachegen::aotstatsSerialization()
+{
+ const auto createEntry = [](const auto &d, const auto &n, const auto &e, const auto &l,
+ const auto &c, const auto &s) -> QQmlJS::AotStatsEntry {
+ QQmlJS::AotStatsEntry entry;
+ entry.codegenDuration = d;
+ entry.functionName = n;
+ entry.errorMessage = e;
+ entry.line = l;
+ entry.column = c;
+ entry.codegenSuccessful = s;
+ return entry;
+ };
+
+ const auto equal = [](const auto &e1, const auto &e2) -> bool {
+ return e1.codegenDuration == e2.codegenDuration && e1.functionName == e2.functionName
+ && e1.errorMessage == e2.errorMessage && e1.line == e2.line
+ && e1.column == e2.column && e1.codegenSuccessful == e2.codegenSuccessful;
+ };
+
+ // AotStats
+ // +-ModuleA
+ // | +-File1
+ // | | +-e1
+ // | | +-e2
+ // | +-File2
+ // | | +-e3
+ // +-ModuleB
+ // | +-File3
+ // | | +-e4
+
+ QQmlJS::AotStats original;
+ QQmlJS::AotStatsEntry e1 = createEntry(std::chrono::microseconds(500), "f1", "", 1, 1, true);
+ QQmlJS::AotStatsEntry e2 = createEntry(std::chrono::microseconds(200), "f2", "err1", 5, 4, false);
+ QQmlJS::AotStatsEntry e3 = createEntry(std::chrono::microseconds(750), "f3", "", 20, 4, true);
+ QQmlJS::AotStatsEntry e4 = createEntry(std::chrono::microseconds(300), "f4", "err2", 5, 8, false);
+ original.addEntry("ModuleA", "File1", e1);
+ original.addEntry("ModuleA", "File1", e2);
+ original.addEntry("ModuleA", "File2", e3);
+ original.addEntry("ModuleB", "File3", e4);
+
+ const auto parsed = QQmlJS::AotStats::fromJsonDocument(original.toJsonDocument());
+ QCOMPARE(parsed.entries().size(), original.entries().size());
+
+ const auto &parsedA = parsed.entries()["ModuleA"];
+ const auto &originalA = original.entries()["ModuleA"];
+ QCOMPARE(parsedA.size(), originalA.size());
+ QCOMPARE(parsedA["File1"].size(), originalA["File1"].size());
+ QVERIFY(equal(parsedA["File1"][0], originalA["File1"][0]));
+ QVERIFY(equal(parsedA["File1"][1], originalA["File1"][1]));
+ QCOMPARE(parsedA["File2"].size(), originalA["File2"].size());
+ QVERIFY(equal(parsedA["File2"][0], originalA["File2"][0]));
+
+ const auto &parsedB = parsed.entries()["ModuleB"];
+ const auto &originalB = original.entries()["ModuleB"];
+ QCOMPARE(parsedB.size(), originalB.size());
+ QCOMPARE(parsedB["File3"].size(), originalB["File3"].size());
+ QVERIFY(equal(parsedB["File3"][0], originalB["File3"][0]));
+}
+
+struct FunctionEntry
+{
+ QString name;
+ QString errorMessage;
+ bool codegenSuccessful;
+};
+
+void tst_qmlcachegen::aotstatsGeneration_data()
+{
+ QTest::addColumn<QString>("qmlFile");
+ QTest::addColumn<QList<FunctionEntry>>("entries");
+
+ QTest::addRow("clean") << "AotstatsClean.qml"
+ << QList<FunctionEntry>{ { "j", "", true }, { "s", "", true } };
+
+ const QString fError = "function without return type annotation returns int. This may prevent "
+ "proper compilation to Cpp.";
+ const QString sError = "method g cannot be resolved.";
+ QTest::addRow("mixed") << "AotstatsMixed.qml"
+ << QList<FunctionEntry>{ { "i", "", true },
+ { "f", fError, false },
+ { "s", sError, false } };
+}
+
+void tst_qmlcachegen::aotstatsGeneration()
+{
+#if defined(QTEST_CROSS_COMPILED)
+ QSKIP("Cannot call qmlcachegen on cross-compiled target.");
+#endif
+ QFETCH(QString, qmlFile);
+ QFETCH(QList<FunctionEntry>, entries);
+
+ QTemporaryDir dir;
+ QProcess proc;
+ proc.setProgram(QLibraryInfo::path(QLibraryInfo::LibraryExecutablesPath) + "/qmlcachegen"_L1);
+ const QString cppOutput = dir.filePath(qmlFile + ".cpp");
+ const QString aotstatsOutput = cppOutput + ".aotstats";
+ proc.setArguments({ "--bare",
+ "--resource-path", "/cachegentest/data/aotstats/" + qmlFile,
+ "-i", testFile("aotstats/qmldir"),
+ "--resource", testFile("aotstats/cachegentest.qrc"),
+ "--dump-aot-stats",
+ "--module-id=Aotstats",
+ "-o", cppOutput,
+ testFile("aotstats/" + qmlFile) });
+ proc.start();
+ QVERIFY(proc.waitForFinished() && proc.exitStatus() == QProcess::NormalExit);
+
+ QVERIFY(QFileInfo::exists(aotstatsOutput));
+ QFile aotstatsFile(aotstatsOutput);
+ QVERIFY(aotstatsFile.open(QIODevice::Text | QIODevice::ReadOnly));
+ const auto document = QJsonDocument::fromJson(aotstatsFile.readAll());
+ const auto aotstats = QQmlJS::AotStats::fromJsonDocument(document);
+ QVERIFY(aotstats.entries().size() == 1); // One module
+ const auto &moduleEntries = aotstats.entries()["Aotstats"];
+ QVERIFY(moduleEntries.size() == 1); // Only one qml file was compiled
+ const auto &fileEntries = moduleEntries[moduleEntries.keys().first()];
+
+ for (const auto &entry : entries) {
+ const auto it = std::find_if(fileEntries.cbegin(), fileEntries.cend(),
+ [&](const auto &e) { return e.functionName == entry.name; });
+ QVERIFY(it != fileEntries.cend());
+ QVERIFY(it->codegenSuccessful == entry.codegenSuccessful);
+ QVERIFY(it->errorMessage == entry.errorMessage);
+ }
+}
+
const QQmlScriptString &ScriptStringProps::undef() const
{
return m_undef;
diff --git a/tests/auto/qml/qmlcppcodegen/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/CMakeLists.txt
index 8644e00cde..715ad6162a 100644
--- a/tests/auto/qml/qmlcppcodegen/CMakeLists.txt
+++ b/tests/auto/qml/qmlcppcodegen/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlcppcodegen LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
add_subdirectory(data)
qt_internal_add_test(tst_qmlcppcodegen
@@ -8,9 +14,13 @@ qt_internal_add_test(tst_qmlcppcodegen
tst_qmlcppcodegen.cpp
LIBRARIES
Qt::QmlPrivate
- Qt::Gui
+ Qt::GuiPrivate
codegen_test_module
codegen_test_moduleplugin
+ codegen_test_hidden
+ codegen_test_hiddenplugin
+ codegen_test_stringbuilder
+ codegen_test_stringbuilderplugin
)
qt_internal_add_test(tst_qmlcppcodegen_interpreted
@@ -18,9 +28,13 @@ qt_internal_add_test(tst_qmlcppcodegen_interpreted
tst_qmlcppcodegen.cpp
LIBRARIES
Qt::QmlPrivate
- Qt::Gui
+ Qt::GuiPrivate
codegen_test_module
codegen_test_moduleplugin
+ codegen_test_hidden
+ codegen_test_hiddenplugin
+ codegen_test_stringbuilder
+ codegen_test_stringbuilderplugin
DEFINES
QT_TEST_FORCE_INTERPRETER
)
diff --git a/tests/auto/qml/qmlcppcodegen/data/Action.qml b/tests/auto/qml/qmlcppcodegen/data/Action.qml
new file mode 100644
index 0000000000..99b86fb31c
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/Action.qml
@@ -0,0 +1,7 @@
+import QtQuick
+import QtQuick.Controls as QQC2
+import QtQuick.Templates as T
+
+QQC2.Action {
+ property bool visible: true
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/B.qml b/tests/auto/qml/qmlcppcodegen/data/B.qml
new file mode 100644
index 0000000000..97e895ecad
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/B.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property rect r
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/BaseConstraint.qml b/tests/auto/qml/qmlcppcodegen/data/BaseConstraint.qml
new file mode 100644
index 0000000000..2615778f6a
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/BaseConstraint.qml
@@ -0,0 +1,9 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property int satisfaction: Satisfaction.NONE
+ property QtObject output
+
+ function inputsKnown(mark: int) : bool { return true }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
index 0737d77005..7f2e6ad967 100644
--- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
+++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
@@ -4,41 +4,61 @@
set(cpp_sources
ambiguous.h
birthdayparty.cpp birthdayparty.h
+ convertQJSPrimitiveValueToIntegral.h
cppbaseclass.h
druggeljug.h
+ dummyobjekt.h
dynamicmeta.h
enumproblems.h
enumProperty.h
+ getOptionalLookup.h
gadgetwithenum.h
invisible.h
+ listprovider.h
multiforeign.h
objectwithmethod.h
person.cpp person.h
+ resettable.h
+ sequenceToIterable.h
sequencetypeexample.cpp sequencetypeexample.h
state.h
theme.cpp theme.h
timelinetheme.cpp timelinetheme.h
+ variantMapLookup.h
+ variantreturn.h
+ weathermoduleurl.h
wrapwithvariant.h
withlength.h
)
set(qml_files
AccessModelMethodsFromOutside.qml
+ Action.qml
ArraySequenceLengthInterop.qml
+ B.qml
BadType.qml
+ BaseConstraint.qml
BaseMember.qml
BindingExpression.qml
+ CxxTypeFromDir.qml
+ CxxTypeFromImplicit.qml
Cycle1.qml
Cycle2.qml
Cycle3.qml
- CxxTypeFromDir.qml
- CxxTypeFromImplicit.qml
+ CppMethodListReturnType.qml
Dummy.qml
+ Dummy2.qml
+ EditConstraint.qml
Enums.qml
Foozle.qml
+ GetOptionalLookupOnQJSValueNonStrict.qml
+ GetOptionalLookupShadowed.qml
Loopy.qml
+ NotificationItem.qml
+ NotificationsUtils.js
OkType.qml
Panel.qml
+ Planner.qml
ProgressBar/Keyframe.qml
ProgressBar/KeyframeGroup.qml
ProgressBar/ProgressBar.ui.qml
@@ -46,98 +66,145 @@ set(qml_files
ProgressBar/Timeline.qml
ProgressBar/TimelineAnimation.qml
RootWithoutId.qml
+ Satisfaction.qml
SelectionRectangle.qml
+ ShadowedObjectName.qml
+ ShadowedObjectNameDerived.qml
+ StoreMetaEnum.qml
Test.qml
TestCase.qml
+ Variable.qml
WindowDerived.qml
aliasLookup.qml
ambiguous1/Ambiguous.qml
ambiguous2/Ambiguous.qml
+ ambiguousAs.qml
ambiguousSignals.qml
anchorsFill.qml
argumentConversion.qml
array.qml
+ arrayCtor.qml
asCast.qml
attachedBaseEnum.qml
badSequence.qml
+ basicBlocksWithBackJump.qml
+ basicBlocksWithBackJump_infinite.qml
+ basicDTZ.qml
bindToValueType.qml
blockComments.qml
+ boolCoercions.qml
+ boolPointerMerge.qml
boundComponents.qml
callContextPropertyLookupResult.qml
callWithSpread.qml
childobject.qml
colorAsVariant.qml
colorString.qml
- consoleObject.qml
+ compareOriginals.qml
+ comparisonTypes.qml
componentReturnType.qml
compositeTypeMethod.qml
compositesingleton.qml
+ consoleObject.qml
+ consoleTrace.qml
construct.qml
contextParam.qml
conversionDecrement.qml
+ conversionInDeadCode.qml
conversions.qml
conversions2.qml
+ convertPrimitiveToVar.qml
+ convertQJSPrimitiveValueToIntegral.qml
+ convertToOriginalReadAcumulatorForUnaryOperators.qml
curlygrouped.qml
cycleHead.qml
+ dateConstruction.qml
dateConversions.qml
deadShoeSize.qml
deadStoreLoop.qml
dialog.qml
+ dialogButtonBox.qml
dynamicscene.qml
+ enforceSignature.qml
enumConversion.qml
+ enumFromBadSingleton.qml
enumInvalid.qml
enumLookup.qml
+ enumMarkedAsFlag.qml
enumProblems.qml
enumScope.qml
enumsInOtherObject.qml
enumsUser.qml
equalityQObjects.qml
+ equalityQUrl.qml
+ equalityTestsWithNullOrUndefined.qml
equalityVarAndNonStorable.qml
equalsUndefined.qml
+ exceptionFromInner.qml
excessiveParameters.qml
extendedTypes.qml
+ extra/extra.qml
failures.qml
fallbacklookups.qml
+ fallbackresettable.qml
fileDialog.qml
+ flagEnum.qml
fromBoolValue.qml
- functionLookup.qml
funcWithParams.qml
+ functionLookup.qml
functionReturningVoid.qml
functionTakingVar.qml
+ getOptionalLookup.qml
globals.qml
- hidden/Main.qml
- hidden/Style.qml
idAccess.qml
+ ignoredFunctionReturn.qml
immediateQuit.qml
imports/QmlBench/Globals.qml
importsFromImportPath.qml
+ indirectlyShadowable.qml
infinities.qml
infinitiesToInt.qml
- invisibleBase.qml
- invisibleTypes.qml
- invisibleListElementType.qml
intEnumCompare.qml
intOverflow.qml
+ intToEnum.qml
interactive.qml
interceptor.qml
+ internalConversion.qml
+ invisibleBase.qml
+ invisibleListElementType.qml
+ invisibleTypes.qml
isnan.qml
+ iteration.qml
javaScriptArgument.qml
+ jsArrayMethods.qml
+ jsArrayMethodsUntyped.qml
+ jsArrayMethodsWithParams.qml
+ jsArrayMethodsWithParamsUntyped.qml
jsMathObject.qml
jsimport.qml
jsmoduleimport.qml
layouts.qml
- library.js
letAndConst.qml
+ library.js
listAsArgument.qml
+ listConversion.qml
listIndices.qml
+ listOfInvisible.qml
listPropertyAsModel.qml
+ listToString.qml
listlength.qml
math.qml
+ mathMinMax.qml
mathOperations.qml
+ mathStaticProperties.qml
+ mergedObjectRead.qml
+ mergedObjectWrite.qml
+ methodOnListLookup.qml
methods.qml
modulePrefix.qml
moveRegVoid.qml
multiforeign.qml
+ multipleCtors.qml
namespaceWithEnum.qml
noBindingLoop.qml
noQQmlData.qml
@@ -146,9 +213,14 @@ set(qml_files
notEqualsInt.qml
notNotString.qml
nullAccess.qml
+ nullAccessInsideSignalHandler.qml
nullComparison.qml
+ nullishCoalescing.qml
numbersInJsPrimitive.qml
objectInVar.qml
+ objectLookupOnListElement.qml
+ objectWithStringListMethod.qml
+ optionalComparison.qml
outOfBounds.qml
overriddenMember.qml
ownProperty.qml
@@ -157,48 +229,76 @@ set(qml_files
popContextAfterRet.qml
prefixedMetaType.qml
pressAndHoldButton.qml
- registerelimination.qml
+ qtbug113150.qml
+ reduceWithNullThis.qml
+ readEnumFromInstance.qml
+ readonlyListProperty.qml
registerPropagation.qml
+ registerelimination.qml
+ renameAdjust.qml
+ resettable.qml
+ returnAfterReject.qml
revisions.qml
+ scopeIdLookup.qml
scopeVsObject.qml
+ scopedEnum.qml
script.js
script.mjs
+ sequenceToIterable.qml
+ setLookupConversion.qml
+ setLookupOriginalScope.qml
+ shadowedAsCasts.qml
+ shadowedMethod.qml
+ shadowedPrimitiveCmpEqNull.qml
shared/Slider.qml
shifts.qml
signal.qml
signalHandler.qml
signalIndexMismatch.qml
+ signalsWithLists.qml
signatureIgnored.qml
specificParent.qml
storeElementSideEffects.qml
stringArg.qml
stringLength.qml
stringToByteArray.qml
+ structuredValueType.qml
testlogger.js
text.qml
themerbad.qml
themergood.qml
+ thisObject.qml
throwObjectName.qml
toString.qml
+ topLevelComponent.qml
translation.qml
+ trigraphs.qml
trivialSignalHandler.qml
typePropagationLoop.qml
typePropertyClash.qml
typedArray.qml
undefinedResets.qml
+ undefinedToDouble.qml
unknownAttached.qml
unknownParameter.qml
unstoredUndefined.qml
unusedAttached.qml
urlString.qml
usingCxxTypesFromFileImports.qml
+ valueTypeCast.qml
valueTypeCopy.qml
+ valueTypeDefault.qml
valueTypeLists.qml
valueTypeProperty.qml
valueTypeReference.qml
+ variantMap.qml
+ variantMapLookup.qml
+ variantReturn.qml
variantlist.qml
versionmismatch.qml
+ voidConversion.qml
voidfunction.qml
+ writeback.qml
dummy_imports.qml
)
@@ -214,21 +314,88 @@ set_source_files_properties("shared/Slider.qml"
set_source_files_properties("hidden/Style.qml"
PROPERTIES QT_QML_SINGLETON_TYPE TRUE)
+qt_policy(SET QTP0001 NEW)
+
+# Add the module for the hidden files before setting QTP0004, so that we don't add a qmldir in
+# "hidden". That would defeat the purpose.
+
+qt_add_library(codegen_test_hidden STATIC)
+qt_autogen_tools_initial_setup(codegen_test_hidden)
+
+set_target_properties(codegen_test_hidden PROPERTIES
+ # We really want qmlcachegen here, even if qmlsc is available
+ QT_QMLCACHEGEN_EXECUTABLE qmlcachegen
+ QT_QMLCACHEGEN_ARGUMENTS --validate-basic-blocks
+)
+
+target_compile_definitions(codegen_test_hidden PUBLIC
+ -DGENERATED_CPP_FOLDER="${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache"
+)
+
+qt_policy(SET QTP0004 OLD)
+qt6_add_qml_module(codegen_test_hidden
+ URI HiddenTestTypes
+ QML_FILES
+ hidden/Main.qml
+ hidden/Style.qml
+ OUTPUT_DIRECTORY HiddenTestTypes
+ __QT_INTERNAL_DISAMBIGUATE_QMLDIR_RESOURCE
+)
+
+add_dependencies(codegen_test_hidden Qt::Quick)
+
+qt_autogen_tools_initial_setup(codegen_test_hiddenplugin)
+
+qt_policy(SET QTP0004 NEW)
+
+qt_add_library(codegen_test_stringbuilder STATIC)
+qt_autogen_tools_initial_setup(codegen_test_stringbuilder)
+
+set_target_properties(codegen_test_stringbuilder PROPERTIES
+ # We really want qmlcachegen here, even if qmlsc is available
+ QT_QMLCACHEGEN_EXECUTABLE qmlcachegen
+ QT_QMLCACHEGEN_ARGUMENTS --validate-basic-blocks
+)
+
+target_compile_definitions(codegen_test_stringbuilder PRIVATE
+ -DGENERATED_CPP_FOLDER="${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache"
+ QT_USE_QSTRINGBUILDER
+)
+
+qt6_add_qml_module(codegen_test_stringbuilder
+ URI StringBuilderTestTypes
+ SOURCES
+ writableVariantMap.h
+ QML_FILES
+ writeVariantMap.qml
+ OUTPUT_DIRECTORY stringbuilderTestTypes
+ __QT_INTERNAL_DISAMBIGUATE_QMLDIR_RESOURCE
+)
+
+qt_autogen_tools_initial_setup(codegen_test_stringbuilderplugin)
+
qt_add_library(codegen_test_module STATIC)
qt_autogen_tools_initial_setup(codegen_test_module)
set_target_properties(codegen_test_module PROPERTIES
# We really want qmlcachegen here, even if qmlsc is available
QT_QMLCACHEGEN_EXECUTABLE qmlcachegen
+ QT_QMLCACHEGEN_ARGUMENTS --validate-basic-blocks
+)
+
+
+
+target_compile_definitions(codegen_test_module PUBLIC
+ -DGENERATED_CPP_FOLDER="${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache"
)
qt6_add_qml_module(codegen_test_module
VERSION 1.5
URI TestTypes
IMPORT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/imports/"
- AUTO_RESOURCE_PREFIX
DEPENDENCIES
QtQuick
+ QtQuick.Controls
QtQuick.Templates
QtQuick.Shapes
SOURCES
@@ -238,8 +405,96 @@ qt6_add_qml_module(codegen_test_module
RESOURCES
${resource_files}
OUTPUT_DIRECTORY TestTypes # Make sure tst_qmlcachegen doesn't see our output
+ __QT_INTERNAL_DISAMBIGUATE_QMLDIR_RESOURCE
)
+if(${CMAKE_VERSION} GREATER_EQUAL "3.19.0")
+ qt_target_qml_sources(codegen_test_module
+ QML_FILES extra2/extra.qml
+ )
+else()
+ target_compile_definitions(codegen_test_module PUBLIC
+ -DVERY_OLD_CMAKE=1
+ )
+endif()
+
add_dependencies(codegen_test_module Qt::Quick Qt::QuickTemplates2 Qt::QuickShapesPrivate)
qt_autogen_tools_initial_setup(codegen_test_moduleplugin)
+
+
+qt_add_library(codegen_test_module_verify STATIC)
+qt_autogen_tools_initial_setup(codegen_test_module_verify)
+
+set_target_properties(codegen_test_module_verify PROPERTIES
+ # We really want qmlcachegen here, even if qmlsc is available
+ QT_QMLCACHEGEN_EXECUTABLE qmlcachegen
+ QT_QMLCACHEGEN_ARGUMENTS --validate-basic-blocks
+)
+
+
+qt6_add_qml_module(codegen_test_module_verify
+ VERSION 1.5
+ URI TestTypes
+ IMPORT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/imports/"
+ DEPENDENCIES
+ QtQuick
+ QtQuick.Controls
+ QtQuick.Templates
+ QtQuick.Shapes
+ SOURCES
+ ${cpp_sources}
+ QML_FILES
+ ${qml_files}
+ RESOURCES
+ ${resource_files}
+ OUTPUT_DIRECTORY verify/TestTypes # Make sure tst_qmlcachegen doesn't see our output
+ TARGET_PATH verify/TestTypes # Different target path to avoid resource file name clashes
+ __QT_INTERNAL_DISAMBIGUATE_QMLDIR_RESOURCE
+)
+
+add_dependencies(codegen_test_module_verify Qt::Quick Qt::QuickTemplates2 Qt::QuickShapesPrivate)
+
+qt_autogen_tools_initial_setup(codegen_test_module_verifyplugin)
+
+
+qt_internal_add_test(tst_qmlcppcodegen_verify
+ SOURCES
+ tst_qmlcppcodegen_verify.cpp
+)
+
+add_dependencies(tst_qmlcppcodegen_verify codegen_test_module codegen_test_module_verify)
+
+set(a_files "")
+set(b_files "")
+
+foreach(qml_file IN LISTS qml_files)
+ string(REGEX REPLACE "\\.(js|mjs|qml)$" "_\\1" compiled_file ${qml_file})
+ string(REGEX REPLACE "[$#?]+" "_" compiled_file ${compiled_file})
+
+ list(APPEND
+ a_files
+ "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache/codegen_test_module_${compiled_file}.cpp")
+
+ list(APPEND
+ b_files
+ "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache/codegen_test_module_verify_${compiled_file}.cpp")
+endforeach()
+
+qt_add_resources(tst_qmlcppcodegen_verify "a"
+ PREFIX
+ "/a"
+ FILES
+ ${a_files}
+ BASE
+ "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache/"
+)
+
+qt_add_resources(tst_qmlcppcodegen_verify "b"
+ PREFIX
+ "/b"
+ FILES
+ ${b_files}
+ BASE
+ "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache/"
+)
diff --git a/tests/auto/qml/qmlcppcodegen/data/CppMethodListReturnType.qml b/tests/auto/qml/qmlcppcodegen/data/CppMethodListReturnType.qml
new file mode 100644
index 0000000000..9c3ce4e877
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/CppMethodListReturnType.qml
@@ -0,0 +1,12 @@
+pragma Strict
+
+import QtQuick
+import TestTypes
+
+Item {
+ ListProvider {
+ id: listProvider
+ }
+
+ property var list: listProvider.intList()
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/Dummy2.qml b/tests/auto/qml/qmlcppcodegen/data/Dummy2.qml
new file mode 100644
index 0000000000..a3bbef1888
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/Dummy2.qml
@@ -0,0 +1,18 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+
+import QtQml
+
+QtObject {
+ property int value
+ property Dummy2 child
+ property int dummyEnum
+
+ signal triggered()
+ signal signalWithArg(int one, bool two)
+ property real onValue
+ property real offValue
+
+ function someFunction(a: int, b: bool, c: Dummy2, d: real, e: int) : int { return 42 }
+ property string strProp
+ function concat(a: string, b: string) : string { return a + b }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/EditConstraint.qml b/tests/auto/qml/qmlcppcodegen/data/EditConstraint.qml
new file mode 100644
index 0000000000..ce278fbdf9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/EditConstraint.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property Variable myOutput
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupOnQJSValueNonStrict.qml b/tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupOnQJSValueNonStrict.qml
new file mode 100644
index 0000000000..5a89e996b4
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupOnQJSValueNonStrict.qml
@@ -0,0 +1,7 @@
+import QtQml
+import TestTypes
+
+QtObject {
+ property Action action: Action { }
+ property bool b: action?.visible
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupShadowed.qml b/tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupShadowed.qml
new file mode 100644
index 0000000000..eacefc3017
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupShadowed.qml
@@ -0,0 +1,19 @@
+pragma Strict
+
+import QtQml
+import QtQuick
+
+QtObject {
+ id: root
+
+ component Base : QtObject {
+ property int i: 1
+ }
+
+ component Derived : Base {
+ property string i: "a"
+ }
+
+ property Base base: Derived { }
+ property var res: root.base?.i
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/NotificationItem.qml b/tests/auto/qml/qmlcppcodegen/data/NotificationItem.qml
new file mode 100644
index 0000000000..fba4df6453
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/NotificationItem.qml
@@ -0,0 +1,7 @@
+import QtQml
+import TestTypes as MobileShell
+
+QtObject {
+ id: notificationItem
+ objectName: MobileShell.NotificationsUtils.determineNotificationHeadingText(notificationItem)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/NotificationsUtils.js b/tests/auto/qml/qmlcppcodegen/data/NotificationsUtils.js
new file mode 100644
index 0000000000..079270e1b9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/NotificationsUtils.js
@@ -0,0 +1,3 @@
+function determineNotificationHeadingText(notificationItem) {
+ return "heading";
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/Panel.qml b/tests/auto/qml/qmlcppcodegen/data/Panel.qml
index 84e926b8d2..7f589d23e8 100644
--- a/tests/auto/qml/qmlcppcodegen/data/Panel.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/Panel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qmlcppcodegen/data/Planner.qml b/tests/auto/qml/qmlcppcodegen/data/Planner.qml
new file mode 100644
index 0000000000..ddb2fff053
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/Planner.qml
@@ -0,0 +1,50 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: planner
+ property Variable last: Variable { value: 10 }
+
+ function newMark() : int {
+ return 5;
+ }
+
+ function addPropagate(i: int) : bool {
+ return false;
+ }
+
+ function typeErasedRemoveOne(v: QtObject) { removeOne(v as Variable) }
+
+ // Work with various shadowable members and return values.
+ function removeOne(v: Variable) {
+ let vDeterminedBy = v.determinedBy;
+ for (let i = 0, length = v.length(); i < length; ++i) {
+ let next = v.constraint(i) as BaseConstraint;
+ if (next.satisfaction === Satisfaction.NONE)
+ objectName += "n"
+ else if (next !== vDeterminedBy)
+ objectName += "d"
+ else
+ objectName += "x"
+ }
+ }
+
+ function typeErasedRun(c: QtObject) { run(c as BaseConstraint) }
+
+ function run(initial: BaseConstraint) {
+ let mark = planner.newMark();
+ let c = initial;
+
+ let output = c.output as Variable;
+ if (output.mark !== mark && c.inputsKnown(mark)) {
+ output.mark = mark;
+ }
+ }
+
+ function verify(i: int) {
+ if (last.value !== i)
+ console.error("failed", last.value, i);
+ else
+ console.log("success")
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/ProgressBar/ProgressBar.ui.qml b/tests/auto/qml/qmlcppcodegen/data/ProgressBar/ProgressBar.ui.qml
index 21a3832366..a44af04a50 100644
--- a/tests/auto/qml/qmlcppcodegen/data/ProgressBar/ProgressBar.ui.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/ProgressBar/ProgressBar.ui.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.9
import QtQuick.Window 2.3
diff --git a/tests/auto/qml/qmlcppcodegen/data/ProgressBar/Root.qml b/tests/auto/qml/qmlcppcodegen/data/ProgressBar/Root.qml
index 707f0d9be9..43ff1b62b1 100644
--- a/tests/auto/qml/qmlcppcodegen/data/ProgressBar/Root.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/ProgressBar/Root.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.9
diff --git a/tests/auto/qml/qmlcppcodegen/data/ProgressBar/TimelineAnimation.qml b/tests/auto/qml/qmlcppcodegen/data/ProgressBar/TimelineAnimation.qml
index b97e8956bf..75ad2245f2 100644
--- a/tests/auto/qml/qmlcppcodegen/data/ProgressBar/TimelineAnimation.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/ProgressBar/TimelineAnimation.qml
@@ -2,5 +2,5 @@ import QtQuick
NumberAnimation {
property bool pingPong
- signal finished()
+ signal finishedEvil()
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/Satisfaction.qml b/tests/auto/qml/qmlcppcodegen/data/Satisfaction.qml
new file mode 100644
index 0000000000..74968c65ea
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/Satisfaction.qml
@@ -0,0 +1,10 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ enum Value {
+ NONE = 0,
+ FORWARD = 1,
+ BACKWARD = 2
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectName.qml b/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectName.qml
new file mode 100644
index 0000000000..f079f4a94e
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectName.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property int objectName: 12
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectNameDerived.qml b/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectNameDerived.qml
new file mode 100644
index 0000000000..f988cd6bc9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectNameDerived.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import QtQml
+
+ShadowedObjectName {
+ property double objectName: 17.4
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/StoreMetaEnum.qml b/tests/auto/qml/qmlcppcodegen/data/StoreMetaEnum.qml
new file mode 100644
index 0000000000..eb3da15a3a
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/StoreMetaEnum.qml
@@ -0,0 +1,12 @@
+import QtQml
+
+QtObject {
+ enum Foo {
+ Bar,
+ Baz
+ }
+
+ property var eF: StoreMetaEnum.Foo
+ property int bar: eF.Bar
+ property int baz: eF.Baz
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/Variable.qml b/tests/auto/qml/qmlcppcodegen/data/Variable.qml
new file mode 100644
index 0000000000..f5af97757f
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/Variable.qml
@@ -0,0 +1,22 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: variable
+ property int value: 0
+ property int mark: 0
+ property BaseConstraint determinedBy: null
+ property list<BaseConstraint> constraints: [
+ BaseConstraint {
+ satisfaction: variable.value == 0 ? Satisfaction.NONE : Satisfaction.FORWARD
+ }
+ ]
+
+ function length(): int {
+ return constraints.length
+ }
+
+ function constraint(i: int) : BaseConstraint {
+ return constraints[i];
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/ambiguous.h b/tests/auto/qml/qmlcppcodegen/data/ambiguous.h
index 5ea20dbcd1..8f964d593c 100644
--- a/tests/auto/qml/qmlcppcodegen/data/ambiguous.h
+++ b/tests/auto/qml/qmlcppcodegen/data/ambiguous.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef AMBIGUOUS_H
#define AMBIGUOUS_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/ambiguousAs.qml b/tests/auto/qml/qmlcppcodegen/data/ambiguousAs.qml
new file mode 100644
index 0000000000..2b7cbd593d
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/ambiguousAs.qml
@@ -0,0 +1,15 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: self
+ property bool useSelf: true
+ property QtObject other: {
+ var a;
+ if (useSelf)
+ a = self
+ else
+ a = 15
+ return a as QtObject
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/arrayCtor.qml b/tests/auto/qml/qmlcppcodegen/data/arrayCtor.qml
new file mode 100644
index 0000000000..9886a14cb1
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/arrayCtor.qml
@@ -0,0 +1,11 @@
+pragma Strict
+import QML
+
+QtObject {
+ property list<int> defaultCtor: new Array()
+ property list<int> oneArgCtor: new Array(5)
+ property list<int> multiArgCtor: new Array(2, 3, 3, 4)
+ property list<bool> arrayTrue: new Array(true)
+ property list<bool> arrayFalse: new Array(false)
+ property list<real> arrayNegative: new Array(-14)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/asCast.qml b/tests/auto/qml/qmlcppcodegen/data/asCast.qml
index 1befc08d0a..cb8155ca6c 100644
--- a/tests/auto/qml/qmlcppcodegen/data/asCast.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/asCast.qml
@@ -28,4 +28,14 @@ Item {
property QtObject dummyAsItem: dummy as Item
property QtObject dummyAsRectangle: dummy as Rectangle
property QtObject dummyAsDummy: dummy as Dummy
+
+ property QtObject nullAsObject: null as QtObject
+ property QtObject nullAsItem: null as Item
+ property QtObject nullAsRectangle: null as Rectangle
+ property QtObject nullAsDummy: null as Dummy
+
+ property QtObject undefinedAsObject: undefined as QtObject
+ property QtObject undefinedAsItem: undefined as Item
+ property QtObject undefinedAsRectangle: undefined as Rectangle
+ property QtObject undefinedAsDummy: undefined as Dummy
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump.qml b/tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump.qml
new file mode 100644
index 0000000000..5b254fe494
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump.qml
@@ -0,0 +1,33 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ function t1() {
+ let i = 0
+ let foo = false
+ if (true) {
+ for (i = 0; i < 42 ; ++i) {}
+ } else {
+ console.log(foo)
+ }
+ }
+
+ function t2() {
+ let foo = false
+ if (false) {
+ while(Math.random() < 0.5) {}
+ } else {
+ console.log(foo)
+ }
+ }
+
+ function t3() {
+ let foo = false
+ if (Math.random() < 0.5) {
+ console.log(foo)
+ } else {
+ while(Math.random() < 0.5) {}
+ console.log(foo)
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump_infinite.qml b/tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump_infinite.qml
new file mode 100644
index 0000000000..997ff68736
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump_infinite.qml
@@ -0,0 +1,13 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ function infinite() {
+ let foo = false
+ if (true) {
+ while (true) {}
+ } else {
+ console.log(foo)
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/basicDTZ.qml b/tests/auto/qml/qmlcppcodegen/data/basicDTZ.qml
new file mode 100644
index 0000000000..bc9506a533
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/basicDTZ.qml
@@ -0,0 +1,40 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: win
+ property real width: 640
+ property real height: 480
+ property string title: "none"
+
+ function t1(): void {
+ const w = win.width
+ const h = win.height
+
+ if (w > 0 && h > 0) {
+ const wByH = h / 3.0 * 4.0
+ }
+ }
+
+ function t2(): void {
+ let i = 42
+ win.title = "Foo " + i
+
+ for (let j = 0; j < 10; j++) {
+ win.title = "Bar " + j
+ }
+
+ for (let k = 0; k < i; k++) {
+ win.title = "Baz " + k
+ }
+ }
+
+ function t3(): void {
+ let v1 = 1
+ let v2 = 2
+
+ if (true) {
+ v1 = v2
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/birthdayparty.cpp b/tests/auto/qml/qmlcppcodegen/data/birthdayparty.cpp
index 048459f03a..10a2c90b38 100644
--- a/tests/auto/qml/qmlcppcodegen/data/birthdayparty.cpp
+++ b/tests/auto/qml/qmlcppcodegen/data/birthdayparty.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "birthdayparty.h"
@@ -36,6 +36,23 @@ Person *BirthdayParty::guest(int index) const
return m_guests.at(index);
}
+QStringList BirthdayParty::guestNames() const
+{
+ QStringList names;
+ for (Person *guest: m_guests)
+ names.append(guest->name());
+ return names;
+}
+
+QVariantList BirthdayParty::stuffs() const
+{
+ return QVariantList({
+ QVariant::fromValue(objectName()),
+ QVariant::fromValue(m_guests.size()),
+ QVariant::fromValue(m_host)
+ });
+}
+
void BirthdayParty::invite(const QString &name)
{
auto *person = new Person(this);
diff --git a/tests/auto/qml/qmlcppcodegen/data/birthdayparty.h b/tests/auto/qml/qmlcppcodegen/data/birthdayparty.h
index a6871c39b1..8dd640c67f 100644
--- a/tests/auto/qml/qmlcppcodegen/data/birthdayparty.h
+++ b/tests/auto/qml/qmlcppcodegen/data/birthdayparty.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef BIRTHDAYPARTY_H
#define BIRTHDAYPARTY_H
@@ -52,7 +52,6 @@ private:
};
struct Foozle {
- Q_GADGET
int foo = 1;
};
@@ -61,6 +60,8 @@ class BirthdayParty : public QObject
Q_OBJECT
Q_PROPERTY(Person *host READ host WRITE setHost NOTIFY hostChanged FINAL)
Q_PROPERTY(QQmlListProperty<Person> guests READ guests)
+ Q_PROPERTY(QStringList guestNames READ guestNames FINAL)
+ Q_PROPERTY(QVariantList stuffs READ stuffs FINAL)
QML_ELEMENT
QML_ATTACHED(BirthdayPartyAttached)
QML_EXTENDED(BirthDayPartyExtended)
@@ -74,6 +75,9 @@ public:
int guestCount() const;
Person *guest(int) const;
+ QStringList guestNames() const;
+ QVariantList stuffs() const;
+
Q_INVOKABLE void invite(const QString &name);
static BirthdayPartyAttached *qmlAttachedProperties(QObject *object);
diff --git a/tests/auto/qml/qmlcppcodegen/data/boolCoercions.qml b/tests/auto/qml/qmlcppcodegen/data/boolCoercions.qml
new file mode 100644
index 0000000000..6b8ebb3f38
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/boolCoercions.qml
@@ -0,0 +1,45 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property rect a
+ property bool t1: a
+
+ property int c: 1
+ property bool t2: c
+
+ property url e: "qrc:/ab/c.txt"
+ property bool t3: e
+
+ property string f: "a"
+ property bool t4: f
+
+ property var j: 1
+ property bool t5: j
+
+ id: k
+ property bool t6: k
+
+ property date l
+ property bool t7: l
+
+ property url m
+ property bool t8: m
+
+
+
+ property int b: 0
+ property bool f1: b
+
+ property QtObject d: null
+ property bool f2: d
+
+ property string g
+ property bool f3: g
+
+ property var h: undefined
+ property bool f4: h
+
+ property var i: null
+ property bool f5: i
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/boolPointerMerge.qml b/tests/auto/qml/qmlcppcodegen/data/boolPointerMerge.qml
new file mode 100644
index 0000000000..b2d4d7c5d0
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/boolPointerMerge.qml
@@ -0,0 +1,15 @@
+pragma Strict
+import TestTypes
+import QtQuick
+
+Loader {
+ id: self
+ source: "BaseMember.qml"
+ property int ppp: -99
+
+ onItemChanged: {
+ var base = item as BaseMember;
+ if (base)
+ base.ppp = ppp
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/childobject.qml b/tests/auto/qml/qmlcppcodegen/data/childobject.qml
index 3775ee16bc..76ad8fbbb2 100644
--- a/tests/auto/qml/qmlcppcodegen/data/childobject.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/childobject.qml
@@ -4,6 +4,19 @@ import TestTypes
QtObject {
property ObjectWithMethod child: ObjectWithMethod {
objectName: "kraut"
+
+ function doString() { overloaded("string"); }
+ function doNumber() { overloaded(5.2); }
+ function doArray() { overloaded({a: 2, b: 3, c: 3}); }
+
+ function doString2() { overloaded2("string"); }
+ function doNumber2() { overloaded2(5.2); }
+
+ // Artificially pass an extra argument to avoid choosing the "string" overload.
+ // Unfortunately this is still order-dependent on the metaobject level.
+ function doArray2() { overloaded2({a: 2, b: 3, c: 3}, 1); }
+
+ function doFoo() { foo(this); }
}
objectName: child.objectName
property int doneThing: child.doThing()
diff --git a/tests/auto/qml/qmlcppcodegen/data/compareOriginals.qml b/tests/auto/qml/qmlcppcodegen/data/compareOriginals.qml
new file mode 100644
index 0000000000..3d40ffee62
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/compareOriginals.qml
@@ -0,0 +1,39 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ component Variable: QtObject {
+ property int value: 4
+ }
+
+ property Variable first: Variable {}
+ property Variable last: Variable {
+ id: last
+ }
+
+ property int compareOriginals: {
+ var matches = 0;
+ for (var i = 0; i < 6; i++) {
+ first.value = i; // do a shadowed assignment
+ if (last.value != i)
+ ++matches
+ }
+ return matches;
+ }
+
+ property bool optionalThis: {
+ var a
+ if (2 == 2)
+ a = this
+ else
+ a = undefined
+
+ var b
+ if (2 == 2)
+ b = this
+ else
+ b = undefined
+
+ return a === b
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/comparisonTypes.qml b/tests/auto/qml/qmlcppcodegen/data/comparisonTypes.qml
new file mode 100644
index 0000000000..423cd55ed4
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/comparisonTypes.qml
@@ -0,0 +1,54 @@
+import QtQml
+
+QtObject {
+ component Variable: QtObject {
+ property int value: 4
+ }
+
+ component VariableShadow: Variable {
+ property string value: "1"
+ }
+
+ property Variable last: VariableShadow {}
+
+ function find(n: int) : int {
+ var found = 0
+ for (var i = 0; i < n; i++) {
+ if (last.value == i)
+ ++found
+ }
+ return found;
+ }
+
+ function findStrict(n: int) : int {
+ var found = 0
+ for (var i = 0; i < n; i++) {
+ if (last.value === i)
+ ++found
+ }
+ return found;
+ }
+
+ function findNot(n: int) : int {
+ var found = 0
+ for (var i = 0; i < n; i++) {
+ if (last.value != i)
+ ++found
+ }
+ return found;
+ }
+
+ function findNotStrict(n: int) : int {
+ var found = 0
+ for (var i = 0; i < n; i++) {
+ if (last.value !== i)
+ ++found
+ }
+ return found;
+ }
+
+ property int found: find(3)
+ property int foundStrict: findStrict(10)
+ property int foundNot: findNot(3)
+ property int foundNotStrict: findNotStrict(10)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/consoleTrace.qml b/tests/auto/qml/qmlcppcodegen/data/consoleTrace.qml
new file mode 100644
index 0000000000..a80af89ddd
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/consoleTrace.qml
@@ -0,0 +1,8 @@
+import QtQml
+
+QtObject {
+ function a() { b() }
+ function b() { c() }
+ function c() { console.trace() }
+ Component.onCompleted: a()
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/conversionInDeadCode.qml b/tests/auto/qml/qmlcppcodegen/data/conversionInDeadCode.qml
new file mode 100644
index 0000000000..b2e7b40c00
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/conversionInDeadCode.qml
@@ -0,0 +1,32 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ // This does not look like dead code, but each access to 'result' generates a
+ // DeadTemoralZoneCheck instruction that we ignore when compiling to C++
+ // after checking statically that 'result' is alive throughout the function.
+ // Therefore, this function is a torture test for the dead code elimination.
+ function calc(a: int, b: int) : int {
+ let result = a;
+ if (b < 0) {
+ if (b < -1)
+ result -= b;
+ if (b < -2)
+ result /= b;
+ } else {
+ if (b > 1)
+ result *= b;
+ if (b > 2)
+ result += b;
+ }
+ return result;
+ }
+
+ property int a: calc(10, -3);
+ property int b: calc(10, -2);
+ property int c: calc(10, -1);
+ property int d: calc(10, 0);
+ property int e: calc(10, 1);
+ property int f: calc(10, 2);
+ property int g: calc(10, 3);
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/conversions2.qml b/tests/auto/qml/qmlcppcodegen/data/conversions2.qml
index c3a9414ae2..d0d1fc9b8f 100644
--- a/tests/auto/qml/qmlcppcodegen/data/conversions2.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/conversions2.qml
@@ -94,6 +94,8 @@ Item {
}
function qtest_signalHandlerName(sn) {
+ // Warning: to not test for signal handlers like this in actual code.
+ // Use the helper methods in QQmlSignalNames instead.
if (sn.substr(0, 2) === "on" && sn[2] === sn[2].toUpperCase())
return sn
return "on" + sn.substr(0, 1).toUpperCase() + sn.substr(1)
diff --git a/tests/auto/qml/qmlcppcodegen/data/convertPrimitiveToVar.qml b/tests/auto/qml/qmlcppcodegen/data/convertPrimitiveToVar.qml
new file mode 100644
index 0000000000..f7c2cc4058
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/convertPrimitiveToVar.qml
@@ -0,0 +1,18 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: foo
+
+ property int offsetValue
+
+ function send(data : variant) {
+ }
+
+ Component.onCompleted: () => {
+ let deltaOffset = 42
+ deltaOffset -= 1
+ foo.offsetValue = deltaOffset
+ foo.send({offset: deltaOffset})
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.h b/tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.h
new file mode 100644
index 0000000000..459dd62374
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef CONVERTQJSPRIMITIVEVALUETOINTEGRAL_H
+#define CONVERTQJSPRIMITIVEVALUETOINTEGRAL_H
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+class Moo485 : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(int uid READ uid CONSTANT FINAL)
+
+public:
+ explicit Moo485(QObject *parent = nullptr) : QObject(parent) { }
+ int uid() const { return 4711; }
+};
+
+class Foo485 : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(quint16 uid MEMBER m_uid FINAL)
+
+public:
+ explicit Foo485(QObject *parent = nullptr) : QObject(parent) { }
+ quint16 m_uid = 0;
+};
+
+#endif // CONVERTQJSPRIMITIVEVALUETOINTEGRAL_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.qml b/tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.qml
new file mode 100644
index 0000000000..6a15d6f775
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.qml
@@ -0,0 +1,13 @@
+import QtQuick
+import TestTypes
+
+
+Item {
+ id: root
+
+ property Moo485 moo
+
+ readonly property Foo485 foo: Foo485 {
+ uid: root.moo.uid ?? 0xFFFF
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/convertToOriginalReadAcumulatorForUnaryOperators.qml b/tests/auto/qml/qmlcppcodegen/data/convertToOriginalReadAcumulatorForUnaryOperators.qml
new file mode 100644
index 0000000000..6eb14bba57
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/convertToOriginalReadAcumulatorForUnaryOperators.qml
@@ -0,0 +1,13 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: self
+ property int i: 0
+ property Planner planner: null
+
+ function satisfy(mark: int) {
+ planner.addPropagate(mark);
+ i = +mark;
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/cppbaseclass.h b/tests/auto/qml/qmlcppcodegen/data/cppbaseclass.h
index eecc3d968e..812415ae24 100644
--- a/tests/auto/qml/qmlcppcodegen/data/cppbaseclass.h
+++ b/tests/auto/qml/qmlcppcodegen/data/cppbaseclass.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef CPPBASECLASS_H
#define CPPBASECLASS_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/dateConstruction.qml b/tests/auto/qml/qmlcppcodegen/data/dateConstruction.qml
new file mode 100644
index 0000000000..fc8a34da71
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/dateConstruction.qml
@@ -0,0 +1,20 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property date now: new Date()
+ property date now2: new Date(now)
+ property date fromString: new Date("1995-12-17T03:24:00")
+ property date fromNumber: new Date(777)
+ property date fromPrimitive: new Date(objectName.length === 0 ? 57 : "1997-02-13T13:04:12")
+ property date from2: new Date(1996, 1)
+ property date from3: new Date(1996, 2, 3)
+ property date from4: new Date(1996, 3, 4, 5)
+ property date from5: new Date(1996, 4, 5, 6, 7)
+ property date from6: new Date(1996, 5, 6, 7, 8, 9)
+ property date from7: new Date(1996, 6, 7, 8, 9, 10, 11)
+ property date from8: new Date(1996, 7, 8, 9, 10, 11, 12, 13)
+
+ property date withUnderflow: new Date(-4, -5, -6, -7, -8, -9, -10)
+ property date invalid: new Date("foo", "bar")
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/dateConversions.qml b/tests/auto/qml/qmlcppcodegen/data/dateConversions.qml
index 38a34f7487..5c0a426466 100644
--- a/tests/auto/qml/qmlcppcodegen/data/dateConversions.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/dateConversions.qml
@@ -9,12 +9,17 @@ QtObject {
property string dateString: date
property string timeString: time
+ property real dateNumber: date
+ property real timeNumber: time
+
function shuffle() {
Druggeljug.myDate = date;
Druggeljug.myTime = time;
dateString = Druggeljug.myDate;
timeString = Druggeljug.myTime;
+ dateNumber = Druggeljug.myDate;
+ timeNumber = Druggeljug.myTime;
}
function fool() {
@@ -22,4 +27,9 @@ QtObject {
Druggeljug.myTime = Druggeljug.myDate;
Druggeljug.myDate = tmp;
}
+
+ function invalidate() {
+ date = new Date("foo", "bar");
+ time = new Date("bar", "foo");
+ }
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/dialogButtonBox.qml b/tests/auto/qml/qmlcppcodegen/data/dialogButtonBox.qml
new file mode 100644
index 0000000000..b30e0124c8
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/dialogButtonBox.qml
@@ -0,0 +1,8 @@
+pragma Strict
+import QtQuick.Controls.Basic
+
+ApplicationWindow {
+ footer: DialogButtonBox {
+ standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/dummyobjekt.h b/tests/auto/qml/qmlcppcodegen/data/dummyobjekt.h
new file mode 100644
index 0000000000..ace319f91f
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/dummyobjekt.h
@@ -0,0 +1,29 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef DUMMYOBJEKT_H
+#define DUMMYOBJEKT_H
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+#if QT_DEPRECATED_SINCE(6, 4)
+class DummyObjekt : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+
+public:
+ enum Test {
+ TestA = 1,
+ TestB
+ };
+ Q_ENUM(Test)
+
+ // Deliberately not default constructible
+ explicit DummyObjekt(QObject *parent) : QObject(parent) {}
+};
+#endif
+
+#endif // DUMMYOBJEKT_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h b/tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h
index 64c2850bda..d8358b6a9c 100644
--- a/tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h
+++ b/tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h
@@ -1,38 +1,48 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DYNAMICMETA_H
#define DYNAMICMETA_H
#include <private/qobject_p.h>
+#include <private/qmetaobjectbuilder_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;
+ MetaObjectData()
+ {
+ QMetaObjectBuilder builder;
+ builder.setSuperClass(&T::staticMetaObject);
+ builder.setFlags(builder.flags() | DynamicMetaObject);
+ metaObject = builder.toMetaObject();
+ };
+
+ ~MetaObjectData() {
+ free(metaObject);
+ };
QMetaObject *toDynamicMetaObject(QObject *) override
{
- return const_cast<QMetaObject *>(&T::staticMetaObject);
+ return metaObject;
}
int metaCall(QObject *o, QMetaObject::Call call, int idx, void **argv) override
{
return o->qt_metacall(call, idx, argv);
}
+
+ QMetaObject *metaObject = nullptr;
};
class DynamicMeta : public QObject
{
Q_OBJECT
Q_PROPERTY(int foo READ foo WRITE setFoo NOTIFY fooChanged FINAL)
+ Q_PROPERTY(qreal value READ value WRITE setValue RESET resetValue NOTIFY valueChanged FINAL)
+ Q_PROPERTY(qreal shadowable READ shadowable CONSTANT)
QML_ELEMENT
public:
@@ -54,11 +64,26 @@ public:
Q_INVOKABLE int bar(int baz) { return baz + 12; }
+ qreal value() const { return m_value; }
+ qreal shadowable() const { return 25; }
+
+public slots:
+ void resetValue() { setValue(0); }
+ void setValue(qreal value)
+ {
+ if (m_value == value)
+ return;
+ m_value = value;
+ emit valueChanged();
+ }
+
Q_SIGNALS:
void fooChanged();
+ void valueChanged();
private:
int m_foo = 0;
+ qreal m_value = 0;
};
class DynamicMetaSingleton : public DynamicMeta
diff --git a/tests/auto/qml/qmlcppcodegen/data/enforceSignature.qml b/tests/auto/qml/qmlcppcodegen/data/enforceSignature.qml
new file mode 100644
index 0000000000..571a000199
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/enforceSignature.qml
@@ -0,0 +1,11 @@
+import QtQml
+
+QtObject {
+ id: mainItem
+
+ function arg(item: Binding) : QtObject { return item }
+ function ret(item: QtObject) : Binding { return item }
+
+ property QtObject a: arg(mainItem);
+ property QtObject b: ret(mainItem);
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/enumConversion.qml b/tests/auto/qml/qmlcppcodegen/data/enumConversion.qml
index fee2c50e15..61ddd2162d 100644
--- a/tests/auto/qml/qmlcppcodegen/data/enumConversion.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/enumConversion.qml
@@ -1,7 +1,12 @@
+pragma Strict
import TestTypes
MyType {
id: root
+
+ property alias status: root.a
+
property int test: myEnumType.type
property bool test_1: myEnumType.type
+ objectName: root.status + "m"
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/enumFromBadSingleton.qml b/tests/auto/qml/qmlcppcodegen/data/enumFromBadSingleton.qml
new file mode 100644
index 0000000000..3176fde315
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/enumFromBadSingleton.qml
@@ -0,0 +1,6 @@
+import QtQml
+import TestTypes
+
+QtObject {
+ objectName: "Dummy: " + DummyObjekt.TestA
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/enumMarkedAsFlag.qml b/tests/auto/qml/qmlcppcodegen/data/enumMarkedAsFlag.qml
new file mode 100644
index 0000000000..2ef37cbdf0
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/enumMarkedAsFlag.qml
@@ -0,0 +1,6 @@
+import QML
+import TestTypes
+
+QtObject {
+ property int flagValue: ControlFlags.Both
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/enumProblems.qml b/tests/auto/qml/qmlcppcodegen/data/enumProblems.qml
index f9a4eb144b..6a57b0e64a 100644
--- a/tests/auto/qml/qmlcppcodegen/data/enumProblems.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/enumProblems.qml
@@ -11,4 +11,9 @@ QtObject {
readonly property FooThing fighter: root.f.get(Foo.Fighter)
readonly property FooThing bar: root.f.get(Foo.Component)
}
+
+ property int a: FooFactory.B
+ property int b: f.t8
+ property int c: FooFactory.D
+ property int d: f.t16
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/enumProperty.h b/tests/auto/qml/qmlcppcodegen/data/enumProperty.h
index 8c13e860a3..8d6405a059 100644
--- a/tests/auto/qml/qmlcppcodegen/data/enumProperty.h
+++ b/tests/auto/qml/qmlcppcodegen/data/enumProperty.h
@@ -15,20 +15,87 @@ public:
Tri = 0x04,
};
Q_ENUM(MyEnum)
- Q_PROPERTY(MyEnum type READ type)
+ Q_PROPERTY(MyEnum type READ type CONSTANT)
MyEnum type() const { return MyEnum::Tri; }
};
class MyType : public QObject
{
Q_OBJECT
- Q_PROPERTY(MyEnumType myEnumType READ myEnumType)
+ Q_PROPERTY(MyEnumType myEnumType READ myEnumType CONSTANT)
+ Q_PROPERTY(A a READ a WRITE setA NOTIFY aChanged FINAL)
QML_ELEMENT
public:
+ enum A { B, C, D };
+ Q_ENUM(A)
+
MyEnumType myEnumType() const { return m_type; }
+ A a() const { return m_a; }
+ void setA(A newA)
+ {
+ if (m_a == newA)
+ return;
+ m_a = newA;
+ emit aChanged();
+ }
+
+ Q_INVOKABLE int method(quint16, const QString &) { return 24; }
+ Q_INVOKABLE int method(quint16, MyType::A a) { return int(a); }
+
+Q_SIGNALS:
+ void aChanged();
+
private:
MyEnumType m_type;
+ A m_a = B;
+};
+
+class CommunicationPermission
+{
+ Q_GADGET
+public:
+ enum CommunicationMode : quint8 {
+ Access = 0x01,
+ Advertise = 0x02,
+ Default = Access | Advertise,
+ };
+ Q_DECLARE_FLAGS(CommunicationModes, CommunicationMode)
+ Q_FLAG(CommunicationModes)
+
+ void setCommunicationModes(CommunicationModes modes) { m_modes = modes; }
+ CommunicationModes communicationModes() const { return m_modes; }
+
+private:
+ CommunicationModes m_modes;
+};
+
+struct QQmlCommunicationPermission : public QObject
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(CommunicationPermission)
+ QML_EXTENDED_NAMESPACE(CommunicationPermission)
+ Q_PROPERTY(CommunicationPermission::CommunicationModes communicationModes READ communicationModes WRITE setCommunicationmodes NOTIFY communicationModesChanged)
+
+public:
+ CommunicationPermission::CommunicationModes communicationModes() const
+ {
+ return m_permission.communicationModes();
+ }
+
+ void setCommunicationmodes(const CommunicationPermission::CommunicationModes &newCommunicationModes)
+ {
+ if (communicationModes() == newCommunicationModes)
+ return;
+ m_permission.setCommunicationModes(newCommunicationModes);
+ emit communicationModesChanged();
+ }
+
+signals:
+ void communicationModesChanged();
+
+private:
+ CommunicationPermission m_permission;
};
#endif // ENUMPROPERTY_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/enumproblems.h b/tests/auto/qml/qmlcppcodegen/data/enumproblems.h
index 08a00acf7e..36f97bec5a 100644
--- a/tests/auto/qml/qmlcppcodegen/data/enumproblems.h
+++ b/tests/auto/qml/qmlcppcodegen/data/enumproblems.h
@@ -1,10 +1,11 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef ENUMPROBLEMS_H
#define ENUMPROBLEMS_H
#include <QObject>
+#include <QtCore/qflags.h>
#include <QtQml/qqml.h>
#include <QtQml/qqmlregistration.h>
@@ -45,9 +46,74 @@ class FooThingWrapper {
class FooFactory : public QObject {
Q_OBJECT
QML_ELEMENT
+ Q_PROPERTY(T8 t8 READ t8 CONSTANT FINAL)
+ Q_PROPERTY(T16 t16 READ t16 CONSTANT FINAL)
public:
+ enum T8: qint8 {
+ A, B, C
+ };
+ Q_ENUM(T8)
+
+ enum T16: qint16 {
+ D = 500, E, F
+ };
+ Q_ENUM(T16)
+
+ T8 t8() const { return C; }
+ T16 t16() const { return E; }
+
Q_INVOKABLE Foo* get(Foo::Type type) const { return new Foo(type); }
};
+class ControlFlags : public QObject {
+ Q_OBJECT
+ QML_ELEMENT
+ QML_UNCREATABLE("Flag Container Class")
+public:
+
+ enum Option {
+ ControlA = 0x1,
+ ControlB = 0x2,
+ Both = ControlA | ControlB
+ };
+
+ Q_DECLARE_FLAGS(Options, Option)
+ Q_FLAG(Option)
+};
+
+class ScopedEnum : public QObject {
+ Q_OBJECT
+ QML_NAMED_ELEMENT(Data)
+ Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
+
+public:
+ enum class DType {
+ A = 27, B
+ };
+ Q_ENUM(DType)
+
+ enum EType {
+ C = 7, D
+ };
+ Q_ENUM(EType)
+};
+
+class UnscopedEnum : public QObject {
+ Q_OBJECT
+ QML_NAMED_ELEMENT(Data2)
+ Q_CLASSINFO("RegisterEnumClassesUnscoped", "true")
+
+public:
+ enum class DType {
+ A = 26, B
+ };
+ Q_ENUM(DType)
+
+ enum EType {
+ C = 6, D
+ };
+ Q_ENUM(EType)
+};
+
#endif // ENUMPROBLEMS_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/equalityQUrl.qml b/tests/auto/qml/qmlcppcodegen/data/equalityQUrl.qml
new file mode 100644
index 0000000000..55ac68592c
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/equalityQUrl.qml
@@ -0,0 +1,16 @@
+pragma Strict
+import QtQuick
+
+Item {
+ property url emptyUrl: ""
+ property url sourceUrl: "some/path/file.png"
+
+ property bool emptyUrlStrict: emptyUrl === Qt.resolvedUrl("")
+ property bool emptyUrlWeak: emptyUrl == Qt.resolvedUrl("")
+
+ property bool sourceUrlStrict: sourceUrl === Qt.url("some/path/file.png");
+ property bool sourceUrlWeak: sourceUrl == Qt.url("some/path/file.png");
+
+ property bool sourceIsNotEmptyStrict: sourceUrl !== emptyUrl
+ property bool sourceIsNotEmptyWeak: sourceUrl != emptyUrl
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/equalityTestsWithNullOrUndefined.qml b/tests/auto/qml/qmlcppcodegen/data/equalityTestsWithNullOrUndefined.qml
new file mode 100644
index 0000000000..cd0c433ea9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/equalityTestsWithNullOrUndefined.qml
@@ -0,0 +1,14 @@
+pragma Strict
+
+import QtQml
+import QtQuick
+
+Window {
+ property var foo
+ Component.onCompleted: {
+ console.log(foo !== null)
+ console.log(foo === null)
+ console.log(foo !== undefined)
+ console.log(foo === undefined)
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/exceptionFromInner.qml b/tests/auto/qml/qmlcppcodegen/data/exceptionFromInner.qml
new file mode 100644
index 0000000000..13855356f2
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/exceptionFromInner.qml
@@ -0,0 +1,10 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property QtObject theNull: null
+
+ function doFail() : string { return theNull.objectName }
+ function delegateFail() : string { doFail() }
+ function disbelieveFail() : string { delegateFail() }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/extra/extra.qml b/tests/auto/qml/qmlcppcodegen/data/extra/extra.qml
new file mode 100644
index 0000000000..e8f51984b8
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/extra/extra.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import QtQml
+
+B {
+ r: ({x: 4, y: 6, width: 8, height: 10})
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/extra2/extra.qml b/tests/auto/qml/qmlcppcodegen/data/extra2/extra.qml
new file mode 100644
index 0000000000..e8f51984b8
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/extra2/extra.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import QtQml
+
+B {
+ r: ({x: 4, y: 6, width: 8, height: 10})
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/failures.qml b/tests/auto/qml/qmlcppcodegen/data/failures.qml
index f90fb44fe1..3b0e4908ab 100644
--- a/tests/auto/qml/qmlcppcodegen/data/failures.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/failures.qml
@@ -9,6 +9,7 @@ QtObject {
property string attachedForNasty: Nasty.objectName
property Nasty nasty: Nasty {
+ id: theNasty
objectName: Component.objectName
}
@@ -30,18 +31,10 @@ QtObject {
Component.onCompleted: doesNotExist()
- property string aString: self + "a"
-
property BirthdayParty party: BirthdayParty {
onPartyStarted: (foozle) => { objectName = foozle }
}
- signal foo()
- signal bar()
-
- // Cannot assign potential undefined
- onFoo: objectName = self.bar()
-
property int enumFromGadget1: GadgetWithEnum.CONNECTED + 1
property int enumFromGadget2: TT2.GadgetWithEnum.CONNECTED + 1
@@ -62,4 +55,55 @@ QtObject {
let a;
return a;
}
+
+ function getText(myArr: list<string>): string {
+ myArr.shiftss()
+ }
+
+ function readTracks(metadataList : list<badType>): int {
+ return metadataList.length
+ }
+
+ function dtzFail() : int {
+ for (var a = 10; a < 20; ++a) {
+ switch (a) {
+ case 11:
+ let b = 5;
+ break;
+ case 10:
+ console.log(b);
+ break;
+ }
+ }
+ return a;
+ }
+
+ // TODO: Drop these once we can manipulate QVariant-wrapped lists.
+ property list<withLength> withLengths
+ property int l: withLengths.length
+ property withLength w: withLengths[10]
+
+ property unconstructibleWithLength uwl: 12 + 1
+
+ // Cannot generate code for getters
+ property rect r3: ({ get x() { return 42; }, y: 4 })
+
+ property int nonIterable: {
+ var result = 1;
+ for (var a in Component)
+ ++result;
+ return result;
+ }
+
+ property alias selfself: self
+ property alias nastyBad: theNasty.bad
+ function writeToUnknown() : int {
+ self.selfself.nastyBad = undefined;
+ return 5;
+ }
+
+ readonly property int someNumber: 10
+ function writeToReadonly() { someNumber = 20 }
+
+ property var silly: [,0]
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/fallbackresettable.qml b/tests/auto/qml/qmlcppcodegen/data/fallbackresettable.qml
new file mode 100644
index 0000000000..44b55e245a
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/fallbackresettable.qml
@@ -0,0 +1,23 @@
+pragma Strict
+import QtQml
+import TestTypes
+
+DynamicMeta {
+ id: self
+ value: 999
+
+ property double notResettable: 10
+ property double notResettable2: { return undefined }
+
+ property DynamicMeta shadowing: DynamicMeta {
+ property var shadowable: undefined
+ }
+
+ function doReset() { self.value = undefined }
+ function doReset2() { self.value = shadowing.shadowable }
+ function doNotReset() { self.notResettable = undefined }
+
+ signal aaa()
+ signal bbb()
+ onAaa: objectName = self.bbb()
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/fileDialog.qml b/tests/auto/qml/qmlcppcodegen/data/fileDialog.qml
index b8bd466717..6634982de2 100644
--- a/tests/auto/qml/qmlcppcodegen/data/fileDialog.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/fileDialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/qml/qmlcppcodegen/data/flagEnum.qml b/tests/auto/qml/qmlcppcodegen/data/flagEnum.qml
new file mode 100644
index 0000000000..3ea5cf98db
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/flagEnum.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import TestTypes
+
+CommunicationPermission {
+ communicationModes: CommunicationPermission.Access
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/gadgetwithenum.h b/tests/auto/qml/qmlcppcodegen/data/gadgetwithenum.h
index 839e026b77..3c81cd2e7f 100644
--- a/tests/auto/qml/qmlcppcodegen/data/gadgetwithenum.h
+++ b/tests/auto/qml/qmlcppcodegen/data/gadgetwithenum.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef GADGETWITHENUM_H
#define GADGETWITHENUM_H
@@ -26,4 +26,40 @@ namespace GadgetWithEnumWrapper {
QML_NAMED_ELEMENT(NamespaceWithEnum)
};
+struct Gadget
+{
+ Q_GADGET
+ QML_VALUE_TYPE(gadget)
+
+public:
+ enum class Prop1 { High, low, VeryHigh, VeryLow };
+ Q_ENUM(Prop1)
+
+ enum class Prop2 { VeryHigh, High, low, VeryLow };
+ Q_ENUM(Prop2)
+};
+
+class Backend : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+ Q_PROPERTY(prop priority READ priority FINAL CONSTANT)
+ Q_PROPERTY(Gadget gadget READ gadget FINAL CONSTANT)
+ Q_CLASSINFO("RegisterEnumsFromRelatedTypes", "false")
+
+public:
+ enum prop { High, low, VeryHigh, VeryLow };
+ Q_ENUM(prop)
+
+ explicit Backend(QObject *parent = nullptr) : QObject(parent) {}
+
+ prop priority() const { return m_priority; }
+ Gadget gadget() const { return m_gadget; }
+
+private:
+ prop m_priority = low;
+ Gadget m_gadget;
+};
+
#endif // GADGETWITHENUM_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.h b/tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.h
new file mode 100644
index 0000000000..e8a24cd707
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.h
@@ -0,0 +1,42 @@
+#ifndef GETOPTIONALLOOKUP_H
+#define GETOPTIONALLOOKUP_H
+
+#include <QObject>
+#include <QQmlEngine>
+
+class GOL_Object : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(int i READ i CONSTANT FINAL)
+ Q_PROPERTY(QString s READ s CONSTANT FINAL)
+ Q_PROPERTY(GOL_Object *childA READ childA WRITE setChildA NOTIFY childAChanged FINAL)
+ Q_PROPERTY(Enum e READ e CONSTANT FINAL)
+
+public:
+ GOL_Object(QObject *parent = nullptr) : QObject(parent) { }
+
+ int i() const { return m_i; }
+ void setI(int i) { m_i = i; }
+
+ QString s() const { return m_s; }
+ void setS(QString s) { m_s = s; }
+
+ GOL_Object *childA() const { return m_childA; }
+ void setChildA(GOL_Object *a) { m_childA = a; }
+
+ enum Enum { V1, V2 };
+ Q_ENUM(Enum)
+ Enum e() const { return Enum::V2; }
+
+signals:
+ void childAChanged();
+
+private:
+ int m_i = 5;
+ QString m_s = "6";
+ GOL_Object *m_childA = nullptr;
+};
+
+#endif // GETOPTIONALLOOKUP_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.qml b/tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.qml
new file mode 100644
index 0000000000..ee360d7142
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.qml
@@ -0,0 +1,34 @@
+pragma Strict
+pragma ValueTypeBehavior: Addressable
+
+import QtQuick
+
+GOL_Object {
+ id: root
+
+ property rect r: Qt.rect(0, 0, 20, 50)
+ property point p: Qt.point(0, -10)
+ property var v: Qt.point(5, 5)
+ property var u: undefined
+
+ property int to1: root?.i
+ property string to2: root?.s
+ property GOL_Object to3: root?.childA
+ property var to4: root.childA?.i
+ property var to5: (undefined as GOL_Object)?.childA
+ property int to6: (root as GOL_Object)?.s.length
+
+ property int tv1: root.r?.bottom
+ property int tv2: root.p?.y
+
+ property int te1: root?.e
+ property int te2: GOL_Object?.V2
+ property bool te3: root?.e === GOL_Object?.V1
+ property bool te4: root?.e === GOL_Object?.V2
+
+ property int tc1: root?.p.y
+ property int tc2: root.r?.x
+
+ property var tc4: root?.childA?.s
+ property var tc5: root.childA?.s
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/idAccess.qml b/tests/auto/qml/qmlcppcodegen/data/idAccess.qml
index 2090926872..6ca1f7f66b 100644
--- a/tests/auto/qml/qmlcppcodegen/data/idAccess.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/idAccess.qml
@@ -1,3 +1,4 @@
+pragma Strict
import QtQuick
Item {
@@ -11,5 +12,9 @@ Item {
Text {
id: ttt
+ onTextChanged: {
+ root.objectName = "dead"
+ ttt.objectName = "context"
+ }
}
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/ignoredFunctionReturn.qml b/tests/auto/qml/qmlcppcodegen/data/ignoredFunctionReturn.qml
new file mode 100644
index 0000000000..640e2bc22a
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/ignoredFunctionReturn.qml
@@ -0,0 +1,14 @@
+import QtQuick
+
+Item {
+ id: root
+
+ Component {
+ id: comp
+ Rectangle {
+ color: "blue"
+ }
+ }
+
+ Component.onCompleted: comp.createObject(root, {"width": 200, "height": 200})
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/indirectlyShadowable.qml b/tests/auto/qml/qmlcppcodegen/data/indirectlyShadowable.qml
new file mode 100644
index 0000000000..de31527e5b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/indirectlyShadowable.qml
@@ -0,0 +1,39 @@
+import QtQml
+
+QtObject {
+ id: self
+ objectName: "self"
+
+ component Inner : QtObject {
+ property QtObject shadowable: QtObject {
+ objectName: "shadowable"
+ }
+ }
+
+ component Outer : QtObject {
+ property Inner inner: Inner {}
+ }
+
+ component Evil : Outer {
+ property string inner: "evil"
+ }
+
+ property Outer outer: Outer {}
+ property Outer evil: Evil {}
+
+ property QtObject notShadowable: QtObject {
+ objectName: "notShadowable"
+ }
+
+ function getInnerShadowable() {
+ notShadowable = outer.inner.shadowable;
+ }
+
+ function setInnerShadowable() {
+ outer.inner.shadowable = self;
+ }
+
+ function turnEvil() {
+ outer = evil;
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/intToEnum.qml b/tests/auto/qml/qmlcppcodegen/data/intToEnum.qml
new file mode 100644
index 0000000000..e255f4e8f4
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/intToEnum.qml
@@ -0,0 +1,7 @@
+pragma Strict
+import TestTypes
+
+MyType {
+ a: myEnumType.type === 4 ? 2 : 1
+ property int b: method("12", "hh")
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/interactive.qml b/tests/auto/qml/qmlcppcodegen/data/interactive.qml
index e857df96e7..be5e5f0d40 100644
--- a/tests/auto/qml/qmlcppcodegen/data/interactive.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/interactive.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
pragma Strict
import QtQuick 2.9
diff --git a/tests/auto/qml/qmlcppcodegen/data/internalConversion.qml b/tests/auto/qml/qmlcppcodegen/data/internalConversion.qml
new file mode 100644
index 0000000000..7304b7a6b9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/internalConversion.qml
@@ -0,0 +1,16 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property QtObject offset: QtObject {
+ id: a
+ property string mark
+ }
+
+ function markInputs(mark: string) {
+ offset.objectName = mark;
+ a.mark = mark;
+ }
+
+ Component.onCompleted: markInputs("hello")
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/invisible.h b/tests/auto/qml/qmlcppcodegen/data/invisible.h
index a385ee975f..4f4ebb87ad 100644
--- a/tests/auto/qml/qmlcppcodegen/data/invisible.h
+++ b/tests/auto/qml/qmlcppcodegen/data/invisible.h
@@ -1,11 +1,12 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef INVISIBLE_H
#define INVISIBLE_H
#include <QtCore/qobject.h>
#include <QtQmlIntegration/qqmlintegration.h>
+#include <QtQml/qqmllist.h>
class Invisible : public QObject
{
@@ -45,6 +46,39 @@ class DerivedFromInvisible : public Invisible
{
Q_OBJECT
QML_ELEMENT
+ Q_PROPERTY(double implicitWidth MEMBER m_implicitWidth NOTIFY implicitWidthChanged FINAL)
+public:
+ DerivedFromInvisible(QObject *parent = nullptr) : Invisible(parent) {}
+
+signals:
+ void implicitWidthChanged();
+
+private:
+ double m_implicitWidth = 27;
+};
+
+class WithListPropertyOfDerivedFromInvisible : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(QQmlListProperty<DerivedFromInvisible> children READ children NOTIFY childrenChanged FINAL)
+
+public:
+ WithListPropertyOfDerivedFromInvisible(QObject *parent = nullptr) : QObject(parent)
+ {
+ m_children.append(new DerivedFromInvisible(this));
+ }
+
+ QQmlListProperty<DerivedFromInvisible> children()
+ {
+ return QQmlListProperty<DerivedFromInvisible>(this, &m_children);
+ }
+
+signals:
+ void childrenChanged();
+
+private:
+ QList<DerivedFromInvisible *> m_children;
};
#endif // INVISIBLE_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/iteration.qml b/tests/auto/qml/qmlcppcodegen/data/iteration.qml
new file mode 100644
index 0000000000..8632eefa1b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/iteration.qml
@@ -0,0 +1,20 @@
+pragma Strict
+
+import QtQml
+
+QtObject {
+ property list<int> ints: [3, 4, 5]
+ property list<QtObject> objects: [
+ QtObject { objectName: "a" },
+ QtObject { objectName: "b" },
+ QtObject { objectName: "c" }
+ ]
+
+ Component.onCompleted: {
+ for (var a in objects) {
+ objectName += objects[a].objectName;
+ for (var b in ints)
+ objectName += ints[b];
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/jsArrayMethods.qml b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethods.qml
new file mode 100644
index 0000000000..ff372bca45
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethods.qml
@@ -0,0 +1,28 @@
+pragma Strict
+import QML
+
+QtObject {
+ id: self
+
+ property QtObject l1: QtObject { objectName: "klaus" }
+ property QtObject l2: QtObject { function toString(): string { return "teil" } }
+ property QtObject l3: QtObject { }
+
+ function jsArray() : list<var> { return [l1, l2, l3, l1, l2, l3] }
+ property list<QtObject> listProperty: [l1, l2, l3, l1, l2, l3]
+
+ property string jsArrayToString: jsArray().toString()
+ property string listPropertyToString: listProperty.toString()
+
+ property bool listPropertyIncludes: listProperty.includes(l3)
+ property bool jsArrayIncludes: jsArray().includes(l3)
+
+ property string listPropertyJoin: listProperty.join()
+ property string jsArrayJoin: jsArray().join()
+
+ property int listPropertyIndexOf: listProperty.indexOf(l2)
+ property int jsArrayIndexOf: jsArray().indexOf(l2)
+
+ property int listPropertyLastIndexOf: listProperty.lastIndexOf(l3)
+ property int jsArrayLastIndexOf: jsArray().lastIndexOf(l3)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsUntyped.qml b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsUntyped.qml
new file mode 100644
index 0000000000..7426c692fe
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsUntyped.qml
@@ -0,0 +1,17 @@
+import QML
+
+QtObject {
+ id: self
+
+ property QtObject l1
+ property QtObject l2
+ property QtObject l3
+
+ function jsArray() { return [l1, l2, l3, l1, l2, l3] }
+
+ property string jsArrayToString: jsArray().toString()
+ property bool jsArrayIncludes: jsArray().includes(l3)
+ property string jsArrayJoin: jsArray().join()
+ property int jsArrayIndexOf: jsArray().indexOf(l2)
+ property int jsArrayLastIndexOf: jsArray().lastIndexOf(l3)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParams.qml b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParams.qml
new file mode 100644
index 0000000000..293e7cbda5
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParams.qml
@@ -0,0 +1,26 @@
+pragma Strict
+import QML
+
+QtObject {
+ id: self
+
+ required property int i
+ required property int j
+ required property int k
+
+ property QtObject l1: QtObject { objectName: "klaus" }
+ property QtObject l2: QtObject { function toString(): string { return "teil" } }
+ property QtObject l3: QtObject { }
+
+ function jsArray() : list<var> { return [l1, l2, l3, l1, l2, l3] }
+ property list<QtObject> listProperty: [l1, l2, l3, l1, l2, l3]
+
+ property list<QtObject> listPropertySlice: listProperty.slice(i, j)
+ property list<var> jsArraySlice: jsArray().slice(i, j)
+
+ property int listPropertyIndexOf: listProperty.indexOf(l2, i)
+ property int jsArrayIndexOf: jsArray().indexOf(l2, i)
+
+ property int listPropertyLastIndexOf: listProperty.lastIndexOf(l3, i)
+ property int jsArrayLastIndexOf: jsArray().lastIndexOf(l3, i)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParamsUntyped.qml b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParamsUntyped.qml
new file mode 100644
index 0000000000..9e928bd6f6
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParamsUntyped.qml
@@ -0,0 +1,18 @@
+import QML
+
+QtObject {
+ id: self
+
+ required property int i
+ required property int j
+ required property int k
+
+ property QtObject l1
+ property QtObject l2
+ property QtObject l3
+
+ function jsArray() { return [l1, l2, l3, l1, l2, l3] }
+ property var jsArraySlice: jsArray().slice(i, j)
+ property int jsArrayIndexOf: jsArray().indexOf(l2, i)
+ property int jsArrayLastIndexOf: jsArray().lastIndexOf(l3, i)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/listConversion.qml b/tests/auto/qml/qmlcppcodegen/data/listConversion.qml
new file mode 100644
index 0000000000..ca86d9a1d6
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/listConversion.qml
@@ -0,0 +1,17 @@
+pragma Strict
+import QtQml
+import TestTypes
+
+BirthdayParty {
+ id: self
+
+ guests: [
+ Person { name: "Horst 1" },
+ Person { name: "Horst 2" },
+ Person { name: "Horst 3" }
+ ]
+
+ property list<QtObject> o: self.guests
+ property list<string> s: self.guestNames
+ property list<var> v: self.stuffs
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/listOfInvisible.qml b/tests/auto/qml/qmlcppcodegen/data/listOfInvisible.qml
new file mode 100644
index 0000000000..f3698d78ab
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/listOfInvisible.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import TestTypes
+
+WithListPropertyOfDerivedFromInvisible {
+ property real width: children[0].implicitWidth
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/listToString.qml b/tests/auto/qml/qmlcppcodegen/data/listToString.qml
new file mode 100644
index 0000000000..e9e4b85956
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/listToString.qml
@@ -0,0 +1,25 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property list<string> stringList: ["one", "two"]
+ property list<int> intList: [1, 2]
+ property list<QtObject> objectList: [this, this]
+
+ Component.onCompleted: {
+ console.log(stringList)
+ console.log(stringList + "")
+
+ console.log(intList)
+ console.log(intList + "")
+
+ console.log(objectList)
+ console.log(objectList + "")
+
+ console.log(["a", "b"]);
+
+ // TODO: Cannot do this, yet, because we cannot coerce a list to string on the fly.
+ // We need to store it as list first.
+ // console.log(["a", "b"] + "");
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/listprovider.h b/tests/auto/qml/qmlcppcodegen/data/listprovider.h
new file mode 100644
index 0000000000..076944b586
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/listprovider.h
@@ -0,0 +1,24 @@
+#ifndef QLISTPROVIDER_H
+#define QLISTPROVIDER_H
+
+#include <QObject>
+#include <QQmlEngine>
+
+class QListProvider : public QObject
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(ListProvider)
+
+public:
+ explicit QListProvider(QObject *parent = nullptr) : QObject(parent) { }
+
+ Q_INVOKABLE QList<int> intList() const
+ {
+ QList<int> list;
+ for (int i = 0; i < 3; ++i)
+ list.append(i);
+ return list;
+ }
+};
+
+#endif // QLISTPROVIDER_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/math.qml b/tests/auto/qml/qmlcppcodegen/data/math.qml
index cc6cd3741a..ad6303e682 100644
--- a/tests/auto/qml/qmlcppcodegen/data/math.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/math.qml
@@ -3,4 +3,5 @@ import QML
QtObject {
property int a: Math.max(5, 7, 9, -111)
property var b: 50 / 22
+ property real c: Math.PI * 2
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/mathMinMax.qml b/tests/auto/qml/qmlcppcodegen/data/mathMinMax.qml
new file mode 100644
index 0000000000..654b699918
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/mathMinMax.qml
@@ -0,0 +1,59 @@
+pragma Strict
+import QtQml
+import QtQuick
+
+Rectangle {
+ Component.onCompleted: {
+ // Math.max()
+ console.log(Math.max(1, 1));
+ console.log(Math.max(1, 2));
+ console.log(Math.max(2, 1));
+ console.log(Math.max(0, 0));
+ console.log(Math.max(-1, 0));
+ console.log(Math.max(0, -1));
+ console.log(Math.max(-1, -1));
+
+ console.log(Math.max(0, 0, 0));
+ console.log(Math.max(0, 0, 1, 0, 0, 0));
+ console.log(Math.max(-2, -1, 0, 1, 2));
+ console.log(Math.max(2, 1, 0, -1, -2));
+ console.log(Math.max(9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ console.log(Math.max(0.0, 0.0, 0.0))
+ console.log(Math.max(-0.001, 0.001, 0.002))
+ console.log(Math.max(5.4, 1, 0.002))
+ console.log(Math.max(null, 0, -1, 8E-2, NaN, undefined, true, false, Infinity))
+ console.log(Math.max(0, -1, 8E-2, true, false, Infinity))
+ console.log(Math.max(0, -1, 8E-2, true, false))
+ console.log(Math.max(0, -1, 8E-2, false))
+ console.log(Math.max(0, -1, 8E-2, true, false, Infinity))
+ console.log(Math.max(-1, -8, null))
+ console.log(Math.max(undefined, 20, 70))
+
+ // Math.min()
+ console.log(Math.min(1, 1));
+ console.log(Math.min(1, +2));
+ console.log(Math.min(2, 1));
+ console.log(Math.min(0, 0));
+ console.log(Math.min(-1, 0));
+ console.log(Math.min(0, -1));
+ console.log(Math.min(-1, -1));
+
+ console.log(Math.min(0, 0, 0));
+ console.log(Math.min(0, 0, 1, 0, 0, 0));
+ console.log(Math.min(-2, -1, 0, 1, 2));
+ console.log(Math.min(2, 1, 0, -1, -2));
+ console.log(Math.min(9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ console.log(Math.min(0.0, 0.0, 0.0))
+ console.log(Math.min(-0.001, 0.001, 0.002))
+ console.log(Math.min(5.4, 1, 0.002))
+ console.log(Math.min(null, 0, -1, 8E-2, NaN, undefined, true, false, Infinity))
+ console.log(Math.min(0, -1, 8E-2, true, false, Infinity))
+ console.log(Math.min(0, -1, 8E-2, true, false))
+ console.log(Math.min(0, -1, 8E-2, false))
+ console.log(Math.min(0, -1, 8E-2, true, false, Infinity))
+ console.log(Math.min(-1, -8, null))
+ console.log(Math.min(undefined, 20, 70))
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/mathStaticProperties.qml b/tests/auto/qml/qmlcppcodegen/data/mathStaticProperties.qml
new file mode 100644
index 0000000000..fad74a28bd
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/mathStaticProperties.qml
@@ -0,0 +1,17 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+pragma Strict
+
+import QML
+
+QtObject {
+ property double e: Math.E
+ property double ln10: Math.LN10
+ property double ln2: Math.LN2
+ property double log10e: Math.LOG10E
+ property double log2e: Math.LOG2E
+ property double pi: Math.PI
+ property double sqrt1_2: Math.SQRT1_2
+ property double sqrt2: Math.SQRT2
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/mergedObjectRead.qml b/tests/auto/qml/qmlcppcodegen/data/mergedObjectRead.qml
new file mode 100644
index 0000000000..161e21e643
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/mergedObjectRead.qml
@@ -0,0 +1,14 @@
+pragma Strict
+import QtQuick
+
+Item {
+ objectName: "a"
+
+ function f(arg: Item) : string {
+ // Read arg as QtObject and Item, merged into QtObject.
+ console.log(arg)
+ return arg.x
+ }
+
+ Component.onCompleted: objectName = f(null)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/mergedObjectWrite.qml b/tests/auto/qml/qmlcppcodegen/data/mergedObjectWrite.qml
new file mode 100644
index 0000000000..5f4bb4ff87
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/mergedObjectWrite.qml
@@ -0,0 +1,15 @@
+pragma Strict
+import QtQuick
+
+Item {
+ objectName: "a"
+
+ function f(arg: Item) : string {
+ // Write arg as Item, read it as QtObject.
+ arg.x = 5
+ console.log(arg)
+ return arg.objectName
+ }
+
+ Component.onCompleted: objectName = f(null)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/methodOnListLookup.qml b/tests/auto/qml/qmlcppcodegen/data/methodOnListLookup.qml
new file mode 100644
index 0000000000..b6b7179438
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/methodOnListLookup.qml
@@ -0,0 +1,16 @@
+pragma Strict
+import QtQml
+import TestTypes
+
+QtObject {
+ objectName: people[0].getName()
+ property list<Person> people: [
+ Person {
+ name: "no one"
+ }
+ ]
+
+ function boom() : string {
+ return people[1].getName()
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/methods.qml b/tests/auto/qml/qmlcppcodegen/data/methods.qml
index 3abd14c9c1..c045c2249b 100644
--- a/tests/auto/qml/qmlcppcodegen/data/methods.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/methods.qml
@@ -35,6 +35,8 @@ BirthdayParty {
}
function stuff(sn) {
+ // Warning: to not test for signal handlers like this in actual code.
+ // Use the helper methods in QQmlSignalNames instead.
if (sn.substr(0, 2) === "on" && sn[2] === sn[2].toUpperCase())
return sn
return "on" + sn.substr(0, 1).toUpperCase() + sn.substr(1)
diff --git a/tests/auto/qml/qmlcppcodegen/data/multiforeign.h b/tests/auto/qml/qmlcppcodegen/data/multiforeign.h
index 290b6370f5..6c46d5ad86 100644
--- a/tests/auto/qml/qmlcppcodegen/data/multiforeign.h
+++ b/tests/auto/qml/qmlcppcodegen/data/multiforeign.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef MULTIFOREIGN_H
#define MULTIFOREIGN_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/multipleCtors.qml b/tests/auto/qml/qmlcppcodegen/data/multipleCtors.qml
new file mode 100644
index 0000000000..61dfdb7ca5
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/multipleCtors.qml
@@ -0,0 +1,13 @@
+pragma Strict
+
+import TestTypes
+import QtQml
+
+QtObject {
+ property rect r: Qt.rect(1, 2, 3, 4)
+ property point p: Qt.point(5, 6);
+
+ property withLength wr: r
+ property withLength wp: p
+ property withLength wi: 17
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/nullAccessInsideSignalHandler.qml b/tests/auto/qml/qmlcppcodegen/data/nullAccessInsideSignalHandler.qml
new file mode 100644
index 0000000000..8fe47b7296
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/nullAccessInsideSignalHandler.qml
@@ -0,0 +1,33 @@
+import QtQuick
+
+Item {
+ id: root
+ visible: true
+
+ property var speaker
+ signal say_hello()
+
+ Component{
+ id: speakerComp
+ Text {
+ text: "HELLO"
+ function say_hello() {
+ console.log(text)
+ }
+ }
+ }
+
+ Timer {
+ interval: 1; running: true; repeat: false
+ onTriggered: root.say_hello();
+ }
+
+ Component.onCompleted:
+ {
+ root.speaker = speakerComp.createObject(root);
+
+ root.say_hello.connect(root.speaker.say_hello);
+
+ root.speaker.destroy();
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/nullComparison.qml b/tests/auto/qml/qmlcppcodegen/data/nullComparison.qml
index 1f9af7169b..53b3697c9b 100644
--- a/tests/auto/qml/qmlcppcodegen/data/nullComparison.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/nullComparison.qml
@@ -6,6 +6,7 @@ QtObject {
property int w: 1
property int x: 1
property int y: 1
+ property int z: 1
Component.onCompleted: {
var g = null;
if (g !== null) {
@@ -22,5 +23,15 @@ QtObject {
if (h === undefined) {
y = 5;
}
+
+ var o = this;
+ if (o != null)
+ z += 7;
+ if (o == null)
+ z += 6;
+ if (g == null)
+ z += 10;
+ if (g != null)
+ z += 20;
}
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/nullishCoalescing.qml b/tests/auto/qml/qmlcppcodegen/data/nullishCoalescing.qml
new file mode 100644
index 0000000000..f84f93c5d2
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/nullishCoalescing.qml
@@ -0,0 +1,37 @@
+pragma Strict
+pragma ValueTypeBehavior: Addressable
+
+import QtQuick
+
+GOL_Object {
+ id: root
+
+ property int p1: 5 ?? -1
+ property string p2: "6" ?? "-1"
+
+ property var p3: undefined ?? undefined
+ property var p4: undefined ?? null
+ property var p5: undefined ?? -1
+ property var p6: undefined ?? "-1"
+
+ property var p7: null ?? undefined
+ property var p8: null ?? null
+ property var p9: null ?? -1
+ property var p10: null ?? "-1"
+
+ property int p11: GOL_Object.V2 ?? "-1"
+
+ property int p12: 1 ?? 2 ?? 3
+ property int p13: "1" ?? "2" ?? "3"
+ property var p14: undefined ?? "2" ?? undefined
+ property var p15: undefined ?? undefined ?? 1
+
+ property var p16
+ property var p17
+
+ Component.onCompleted: {
+ p16 = (root.childA as GOL_Object)?.i ?? -1
+ root.childA = root
+ p17 = (root.childA as GOL_Object)?.i ?? -1
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml b/tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml
index f12d3f5ea2..ec848429e8 100644
--- a/tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml
@@ -4,23 +4,57 @@ import TestTypes
QtObject {
function writeValues() {
+ Druggeljug.myInt8 = 35
+ Druggeljug.myUint8 = 36
+ Druggeljug.myInt16 = 37
+ Druggeljug.myUint16 = 38
Druggeljug.myInt = 39
Druggeljug.myUint = 40
Druggeljug.myInt32 = 41
Druggeljug.myUint32 = 42
}
+ function negateValues() {
+ Druggeljug.myInt8 = -Druggeljug.myInt8;
+ Druggeljug.myUint8 = -Druggeljug.myUint8;
+ Druggeljug.myInt16 = -Druggeljug.myInt16;
+ Druggeljug.myUint16 = -Druggeljug.myUint16;
+ Druggeljug.myInt = -Druggeljug.myInt;
+ Druggeljug.myUint = -Druggeljug.myUint;
+ Druggeljug.myInt32 = -Druggeljug.myInt32;
+ Druggeljug.myUint32 = -Druggeljug.myUint32;
+ }
+
+ function shuffleValues() {
+ Druggeljug.myInt8 = Druggeljug.myUint8;
+ Druggeljug.myUint8 = Druggeljug.myInt16;
+ Druggeljug.myInt16 = Druggeljug.myUint16;
+ Druggeljug.myUint16 = Druggeljug.myInt;
+ Druggeljug.myInt = Druggeljug.myUint;
+ Druggeljug.myUint = Druggeljug.myInt32;
+ Druggeljug.myInt32 = Druggeljug.myUint32;
+ Druggeljug.myUint32 = Druggeljug.myInt8;
+ }
+
function readValueAsString(i: int) : string {
switch (i) {
- case 0: return Druggeljug.myInt;
- case 1: return Druggeljug.myUint;
- case 2: return Druggeljug.myInt32;
- case 3: return Druggeljug.myUint32;
+ case 0: return Druggeljug.myInt8;
+ case 1: return Druggeljug.myUint8;
+ case 2: return Druggeljug.myInt16;
+ case 3: return Druggeljug.myUint16;
+ case 4: return Druggeljug.myInt;
+ case 5: return Druggeljug.myUint;
+ case 6: return Druggeljug.myInt32;
+ case 7: return Druggeljug.myUint32;
default: return "";
}
}
function storeValues() {
+ Druggeljug.storeMyInt8(1330)
+ Druggeljug.storeMyUint8(1331)
+ Druggeljug.storeMyInt16(1332)
+ Druggeljug.storeMyUint16(1333)
Druggeljug.storeMyInt(1334)
Druggeljug.storeMyUint(1335)
Druggeljug.storeMyInt32(1336)
diff --git a/tests/auto/qml/qmlcppcodegen/data/objectLookupOnListElement.qml b/tests/auto/qml/qmlcppcodegen/data/objectLookupOnListElement.qml
new file mode 100644
index 0000000000..4804921b02
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/objectLookupOnListElement.qml
@@ -0,0 +1,34 @@
+pragma Strict
+import QtQuick
+
+Item {
+ id: stack
+
+ property int current: 0
+
+ onCurrentChanged: setZOrders()
+ Component.onCompleted: setZOrders()
+
+ function setZOrders() {
+ for (var i = 0; i < Math.max(stack.children.length, 3); ++i) {
+ stack.children[i].z = (i == current ? 1 : 0)
+ stack.children[i].enabled = (i == current)
+ }
+ }
+
+ function zOrders() : list<int> {
+ return [
+ stack.children[0].z,
+ stack.children[1].z,
+ stack.children[2].z
+ ]
+ }
+
+ function clearChildren() {
+ children.length = 0;
+ }
+
+ Item {}
+ Item {}
+ Item {}
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/objectWithStringListMethod.qml b/tests/auto/qml/qmlcppcodegen/data/objectWithStringListMethod.qml
new file mode 100644
index 0000000000..14f84c57d0
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/objectWithStringListMethod.qml
@@ -0,0 +1,7 @@
+import QtQml
+import TestTypes
+
+QtObject {
+ readonly property ObjectWithStringListMethod foo: ObjectFactory.getFoo()
+ Component.onCompleted: console.log(foo ? foo.names().length : "-")
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h b/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h
index 348862985f..f43a0d5531 100644
--- a/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h
+++ b/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef OBJECTWITHMETOD_H
#define OBJECTWITHMETOD_H
@@ -7,6 +7,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qproperty.h>
#include <QtQml/qqml.h>
+#include <QtQml/private/qv4engine_p.h>
// Make objectName available. It doesn't exist on the builtin QtObject type
struct QObjectForeignForObjectName {
@@ -27,6 +28,20 @@ public:
Q_INVOKABLE int doThing() const { return theThing; }
QProperty<int> theThing;
QBindable<int> theThingBindable() { return QBindable<int>(&theThing); }
+
+ // The meta methods are populated back to front.
+ // The V4Function flag should not bleed into the others in either case.
+
+ Q_INVOKABLE void overloaded(QQmlV4FunctionPtr) { setObjectName(QStringLiteral("javaScript")); }
+ Q_INVOKABLE void overloaded(double) { setObjectName(QStringLiteral("double")); }
+ Q_INVOKABLE void overloaded(const QString &) { setObjectName(QStringLiteral("string")); }
+
+ Q_INVOKABLE void foo(const QString &bla) { setObjectName(bla); }
+ Q_INVOKABLE void foo(ObjectWithMethod *) { setObjectName(QStringLiteral("ObjectWithMethod")); }
+
+ Q_INVOKABLE void overloaded2(double) { setObjectName(QStringLiteral("double")); }
+ Q_INVOKABLE void overloaded2(const QString &) { setObjectName(QStringLiteral("string")); }
+ Q_INVOKABLE void overloaded2(QQmlV4FunctionPtr) { setObjectName(QStringLiteral("javaScript")); }
};
class OverriddenObjectName : public ObjectWithMethod
@@ -56,4 +71,40 @@ private:
QProperty<QString> m_objectName;
};
+class ObjectWithStringListMethod : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+public:
+ explicit ObjectWithStringListMethod(QObject *parent = nullptr) : QObject(parent)
+ {
+ m_names.append("One");
+ m_names.append("Two");
+ }
+
+ Q_INVOKABLE QStringList names() const { return m_names; }
+
+private:
+ QStringList m_names;
+};
+
+class ObjectFactory : public QObject {
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+
+public:
+ explicit ObjectFactory(QObject *parent = nullptr) : QObject(parent) {}
+ Q_INVOKABLE ObjectWithStringListMethod *getFoo()
+ {
+ if (!m_foo)
+ m_foo = new ObjectWithStringListMethod(this);
+ return m_foo;
+ }
+
+private:
+ ObjectWithStringListMethod *m_foo = nullptr;
+};
+
#endif // OBJECTWITHMETHOD_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/optionalComparison.qml b/tests/auto/qml/qmlcppcodegen/data/optionalComparison.qml
new file mode 100644
index 0000000000..4dbc541721
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/optionalComparison.qml
@@ -0,0 +1,77 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property list<QtObject> elms: [this, null, null]
+
+ property int found: find(this)
+ property int foundNot: findNot(this)
+ property int foundStrict: findStrict(this)
+ property int foundStrictNot: findStrictNot(this)
+
+ function find(elm : QtObject) : int {
+ let found = 0;
+ for (var i = 0; i < elms.length; i++) {
+ var value = elms[i];
+ if (value == elm)
+ ++found;
+ }
+ return found;
+ }
+
+ function findNot(elm : QtObject) : int {
+ let found = 0;
+ for (var i = 0; i < elms.length; i++) {
+ var value = elms[i];
+ if (value != elm)
+ ++found;
+ }
+ return found;
+ }
+
+ function findStrict(elm : QtObject) : int {
+ let found = 0;
+ for (var i = 0; i < elms.length; i++) {
+ var value = elms[i];
+ if (value === elm)
+ ++found;
+ }
+ return found;
+ }
+
+ function findStrictNot(elm : QtObject) : int {
+ let found = 0;
+ for (var i = 0; i < elms.length; i++) {
+ var value = elms[i];
+ if (value !== elm)
+ ++found;
+ }
+ return found;
+ }
+
+ property bool optionalNull: {
+ let a // Produces a QJsPrimitiveValue we can compare to null below
+ if (objectName.length === 0)
+ a = null
+ else
+ a = undefined
+
+ return a === null
+ }
+
+ property int undefinedEqualsUndefined: {
+ var matches = 0;
+
+ // Overrun the array so that we get some undefined !== undefined.
+ for (var i = 0; i < 4; i++) {
+ var val1 = elms[i]
+ for (var j = 0; j < 4; j++) {
+ var val2 = elms[j]
+ if (!(val1 !== val2))
+ ++matches
+ }
+ }
+
+ return matches;
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/person.cpp b/tests/auto/qml/qmlcppcodegen/data/person.cpp
index 4dcd6fd56f..946dfbcdaa 100644
--- a/tests/auto/qml/qmlcppcodegen/data/person.cpp
+++ b/tests/auto/qml/qmlcppcodegen/data/person.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "person.h"
@@ -98,3 +98,21 @@ void Person::setCousins(const QList<Person *> &newCousins)
m_cousins = newCousins;
emit cousinsChanged();
}
+
+QRectF Person::area() const
+{
+ return m_area;
+}
+
+void Person::setArea(const QRectF &newArea)
+{
+ if (m_area.valueBypassingBindings() == newArea)
+ return;
+ m_area = newArea;
+ emit areaChanged();
+}
+
+QBindable<QRectF> Person::areaBindable()
+{
+ return QBindable<QRectF>(&m_area);
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/person.h b/tests/auto/qml/qmlcppcodegen/data/person.h
index fba4a9e9a5..c46aa757a7 100644
--- a/tests/auto/qml/qmlcppcodegen/data/person.h
+++ b/tests/auto/qml/qmlcppcodegen/data/person.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef PERSON_H
#define PERSON_H
@@ -8,6 +8,35 @@
#include <QtQml/qqml.h>
#include <QtQml/qqmlengine.h>
#include <QtCore/qproperty.h>
+#include <QtCore/qrect.h>
+
+struct Inner
+{
+ Q_GADGET
+ QML_VALUE_TYPE(inner)
+ QML_STRUCTURED_VALUE
+ Q_PROPERTY(int i MEMBER i)
+
+private:
+ friend bool operator==(const Inner &lhs, const Inner &rhs) { return lhs.i == rhs.i; }
+ friend bool operator!=(const Inner &lhs, const Inner &rhs) { return !(lhs == rhs); }
+
+ int i = 11;
+};
+
+struct Outer
+{
+ Q_GADGET
+ QML_VALUE_TYPE(outer)
+ QML_STRUCTURED_VALUE
+ Q_PROPERTY(Inner inner MEMBER inner)
+
+private:
+ friend bool operator==(const Outer &lhs, const Outer &rhs) { return lhs.inner == rhs.inner; }
+ friend bool operator!=(const Outer &lhs, const Outer &rhs) { return !(lhs == rhs); }
+
+ Inner inner;
+};
// Intentionally opaque type
class Barzle : public QObject {};
@@ -22,6 +51,8 @@ class Person : public QObject
Q_PROPERTY(QList<Barzle *> barzles READ barzles WRITE setBarzles NOTIFY barzlesChanged FINAL)
Q_PROPERTY(QList<Person *> cousins READ cousins WRITE setCousins NOTIFY cousinsChanged FINAL)
Q_PROPERTY(QByteArray data READ data WRITE setData NOTIFY dataChanged FINAL)
+ Q_PROPERTY(QRectF area READ area WRITE setArea NOTIFY areaChanged) // not FINAL
+ Q_PROPERTY(QRectF area2 READ area WRITE setArea NOTIFY areaChanged BINDABLE areaBindable FINAL)
QML_ELEMENT
public:
Person(QObject *parent = nullptr);
@@ -52,6 +83,12 @@ public:
QList<Person *> cousins() const;
void setCousins(const QList<Person *> &newCousins);
+ QRectF area() const;
+ void setArea(const QRectF &newArea);
+ QBindable<QRectF> areaBindable();
+
+ Q_INVOKABLE QString getName() const { return m_name; }
+
signals:
void nameChanged();
void shoeSizeChanged();
@@ -62,6 +99,10 @@ signals:
void ambiguous(int a = 9);
void cousinsChanged();
+ void objectListHappened(const QList<QObject *> &);
+ void variantListHappened(const QList<QVariant> &);
+
+ void areaChanged();
private:
QString m_name;
@@ -70,6 +111,7 @@ private:
QList<Barzle *> m_barzles;
QList<Person *> m_cousins;
QProperty<QByteArray> m_data;
+ QProperty<QRectF> m_area;
};
class BarzleListRegistration
diff --git a/tests/auto/qml/qmlcppcodegen/data/qtbug113150.qml b/tests/auto/qml/qmlcppcodegen/data/qtbug113150.qml
new file mode 100644
index 0000000000..c7103eaf05
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/qtbug113150.qml
@@ -0,0 +1,13 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+pragma Strict
+
+import QtQuick
+
+Window {
+ // If static properties of the Math global object are not directly
+ // supported, a warning should be issued in turn failing the build
+ // due to `pragma Strict`.
+ width: 200 * Math.PI
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/readEnumFromInstance.qml b/tests/auto/qml/qmlcppcodegen/data/readEnumFromInstance.qml
new file mode 100644
index 0000000000..d0176e6b15
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/readEnumFromInstance.qml
@@ -0,0 +1,16 @@
+import QtQml
+import TestTypes
+
+QtObject {
+ id: root
+
+ property int priority: Backend.gadget.VeryHigh
+ property int prop2: Backend.priority
+
+ property bool priorityIsVeryHigh: root.priority == Backend.VeryHigh
+
+ function cyclePriority() : int {
+ root.priority = Backend.gadget.High;
+ return root.priority;
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/readonlyListProperty.qml b/tests/auto/qml/qmlcppcodegen/data/readonlyListProperty.qml
new file mode 100644
index 0000000000..149638283b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/readonlyListProperty.qml
@@ -0,0 +1,17 @@
+import QtQml
+
+QtObject {
+ id: testObj
+
+ // "readonly" means the identity of the list cannot be changed.
+ // Its contents can be changed.
+ readonly default property list<QtObject> theList
+
+ Component.onCompleted: {
+ for (var i = 0; i < 4; i++)
+ testObj.theList.push(testObj)
+ }
+
+ property int l: theList.length
+}
+
diff --git a/tests/auto/qml/qmlcppcodegen/data/reduceWithNullThis.qml b/tests/auto/qml/qmlcppcodegen/data/reduceWithNullThis.qml
new file mode 100644
index 0000000000..c6fda8c739
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/reduceWithNullThis.qml
@@ -0,0 +1,18 @@
+import QtQml
+
+QtObject {
+ id: mainItem
+ property int topPadding: 12
+ property int bottomPadding: 12
+
+ property int preferredHeight: mainItem.children.reduce(maximumImplicitHeightReducer, 0) + topPadding + bottomPadding
+ function maximumImplicitHeightReducer(accumulator: real, item: Binding): real {
+ return Math.max(accumulator, (item.objectName + "b").length);
+ }
+
+ property int preferredHeight2: mainItem.children.reduce((accumulator, item) => {
+ return Math.max(accumulator, (item.objectName + "b").length);
+ }, 0) + topPadding + bottomPadding
+
+ property list<Binding> children: [ Binding { objectName: "aaa" } ]
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/renameAdjust.qml b/tests/auto/qml/qmlcppcodegen/data/renameAdjust.qml
new file mode 100644
index 0000000000..9352163ba7
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/renameAdjust.qml
@@ -0,0 +1,19 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: last
+ property int value: 10
+
+ function verify(i: int) {
+ if (last.value !== i)
+ console.error("failed", last.value, i);
+ else
+ console.log("success")
+ }
+
+ Component.onCompleted: {
+ verify(10)
+ verify(11)
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/resettable.h b/tests/auto/qml/qmlcppcodegen/data/resettable.h
new file mode 100644
index 0000000000..755c8de237
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/resettable.h
@@ -0,0 +1,39 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef RESETTABLE_H
+#define RESETTABLE_H
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+class ResettableProperty : public QObject
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(Resettable)
+ Q_PROPERTY(qreal value READ value WRITE setValue RESET resetValue NOTIFY valueChanged FINAL)
+ Q_PROPERTY(qreal shadowable READ shadowable CONSTANT)
+
+public:
+ explicit ResettableProperty(QObject *parent = nullptr) : QObject(parent) {}
+ qreal value() const { return m_value; }
+ qreal shadowable() const { return 25; }
+
+public slots:
+ void resetValue() { setValue(0); }
+ void setValue(qreal value)
+ {
+ if (m_value == value)
+ return;
+ m_value = value;
+ emit valueChanged();
+ }
+
+signals:
+ void valueChanged();
+
+private:
+ qreal m_value = 0;
+};
+
+#endif // RESETTABLE_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/resettable.qml b/tests/auto/qml/qmlcppcodegen/data/resettable.qml
new file mode 100644
index 0000000000..561655032d
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/resettable.qml
@@ -0,0 +1,23 @@
+pragma Strict
+import QtQml
+import TestTypes
+
+Resettable {
+ id: self
+ value: 999
+
+ property double notResettable: 10
+ property double notResettable2: { return undefined }
+
+ property Resettable shadowing: Resettable {
+ property var shadowable: undefined
+ }
+
+ function doReset() { self.value = undefined }
+ function doReset2() { self.value = shadowing.shadowable }
+ function doNotReset() { self.notResettable = undefined }
+
+ signal aaa()
+ signal bbb()
+ onAaa: objectName = self.bbb()
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/returnAfterReject.qml b/tests/auto/qml/qmlcppcodegen/data/returnAfterReject.qml
new file mode 100644
index 0000000000..e0b85eb270
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/returnAfterReject.qml
@@ -0,0 +1,15 @@
+import QtQml
+
+QtObject {
+ id: remaining
+
+ property int bar: 0
+
+ Component.onCompleted: {
+ let remainingTime = 123
+ if (remainingTime < 0) {
+ remainingTime += 24 * 60 * 60
+ }
+ remaining.bar = isNaN(remainingTime) ? 0 : remainingTime
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/scopeIdLookup.qml b/tests/auto/qml/qmlcppcodegen/data/scopeIdLookup.qml
new file mode 100644
index 0000000000..e23f180598
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/scopeIdLookup.qml
@@ -0,0 +1,20 @@
+pragma ComponentBehavior: Bound
+
+import QtQml
+
+QtObject {
+ id: root
+
+ property QtObject b: QtObject {
+ id: bar
+ objectName: "outer"
+ }
+
+ property Instantiator i: Instantiator {
+ model: 1
+ delegate: QtObject {
+ property QtObject bar: QtObject { objectName: "inner" }
+ Component.onCompleted: root.objectName = bar.objectName
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml b/tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml
new file mode 100644
index 0000000000..8b9f161b06
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml
@@ -0,0 +1,19 @@
+import QtQml
+import TestTypes
+
+QtObject {
+ property int good: Data.DType.A
+ property int bad: Data.A
+
+ property int wrong: Data.EType.C
+ property int right: Data.C
+
+ property int notgood: Data2.DType.A
+ property int notbad: Data2.A
+
+ property int notwrong: Data2.EType.C
+ property int notright: Data2.C
+
+ property int passable: Enums.AppState.Blue
+ property int wild: Enums.Green
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.h b/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.h
new file mode 100644
index 0000000000..76c72fff36
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.h
@@ -0,0 +1,56 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef SEQUENCETOITERABLE_H
+#define SEQUENCETOITERABLE_H
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+class Entry : public QObject {
+ Q_OBJECT
+
+public:
+ explicit Entry(const QString &name, QObject *parent = nullptr)
+ : QObject(parent), m_name(name)
+ {
+ setObjectName(name);
+ }
+
+private:
+ QString m_name;
+};
+
+class EntryWrapper {
+ Q_GADGET
+ QML_FOREIGN(Entry)
+ QML_NAMED_ELEMENT(Entry)
+ QML_UNCREATABLE("These are my Entry objects")
+};
+
+class EntryListRegistration
+{
+ Q_GADGET
+ QML_FOREIGN(QList<Entry*>)
+ QML_ANONYMOUS
+ QML_SEQUENTIAL_CONTAINER(Entry*)
+};
+
+class EntrySource : public QObject {
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+
+public:
+ explicit EntrySource(QObject* parent = nullptr) : QObject(parent) {
+ for (int i = 0; i < 10; i++) {
+ m_entries.push_back(new Entry(QString("Item %1").arg(i), this));
+ }
+ }
+ Q_INVOKABLE QList<Entry*> getEntries() const { return m_entries; }
+
+private:
+ QList<Entry*> m_entries;
+};
+
+#endif // SEQUENCETOITERABLE_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.qml b/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.qml
new file mode 100644
index 0000000000..23e2645128
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.qml
@@ -0,0 +1,20 @@
+pragma Strict
+import QtQuick
+import TestTypes
+
+Item {
+ Component.onCompleted: () => {
+ repeater.model = EntrySource.getEntries()
+ }
+
+ Repeater {
+ id: repeater
+ Item {
+ required property int index
+ required property QtObject modelData
+ objectName: modelData + ": " + index
+ }
+ }
+
+ property int c: children.length
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/setLookupConversion.qml b/tests/auto/qml/qmlcppcodegen/data/setLookupConversion.qml
new file mode 100644
index 0000000000..404ee8653b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/setLookupConversion.qml
@@ -0,0 +1,17 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: first
+ property int value
+
+ objectName: a.objectName
+ property QtObject a: QtObject {}
+ function t() { a.objectName = "a" }
+
+ Component.onCompleted: {
+ for (let i = 0; i < 10; ++i) {
+ first.value = i;
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/setLookupOriginalScope.qml b/tests/auto/qml/qmlcppcodegen/data/setLookupOriginalScope.qml
new file mode 100644
index 0000000000..9975bfdfa4
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/setLookupOriginalScope.qml
@@ -0,0 +1,17 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property Component newEditConstraint: EditConstraint {}
+ property Variable variable: Variable {}
+ property EditConstraint edit
+
+ function trigger() {
+ change(variable, 55);
+ }
+
+ function change(v: Variable, newValue: int) {
+ edit = newEditConstraint.createObject(null, {myOutput: v}) as EditConstraint;
+ v.value = newValue;
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/shadowedAsCasts.qml b/tests/auto/qml/qmlcppcodegen/data/shadowedAsCasts.qml
new file mode 100644
index 0000000000..ccb50f4934
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/shadowedAsCasts.qml
@@ -0,0 +1,31 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property ShadowedObjectName shadowed1: ShadowedObjectName {}
+ property ShadowedObjectName shadowed2: ShadowedObjectName {}
+ property QtObject shadowed3: ShadowedObjectNameDerived {}
+
+ function returnShadowed2() : QtObject { return shadowed2 }
+
+ function a(mark: int) {
+ // as-cast can be optimized out if we're clever.
+ (shadowed1 as QtObject).objectName = mark;
+ }
+
+ function b(mark: int) {
+ // method return values can contain shadowed properties!
+ returnShadowed2().objectName = mark;
+ }
+
+ function c(mark: int) {
+ // Has to do an actual as-cast, but results in ShadowedObjectNameDerived!
+ (shadowed3 as ShadowedObjectName).objectName = mark;
+ }
+
+ Component.onCompleted: {
+ a(43);
+ b(42);
+ c(41);
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/shadowedMethod.qml b/tests/auto/qml/qmlcppcodegen/data/shadowedMethod.qml
new file mode 100644
index 0000000000..590fb40b17
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/shadowedMethod.qml
@@ -0,0 +1,35 @@
+pragma Strict
+import QtQuick
+
+Item {
+ component B: Item {
+ function contains(point: point) : string {
+ return "b"
+ }
+ }
+
+
+ component C: Item {
+ function contains(point: point) : string {
+ return "c"
+ }
+ }
+
+ property Item a: Item {}
+ property B b: B {}
+ property C c: C {}
+
+ function doThing() : var { return a.contains(Qt.point(0, 0)) }
+
+ property var athing;
+ property var bthing;
+ property var cthing;
+
+ Component.onCompleted: {
+ athing = doThing();
+ a = b;
+ bthing = doThing();
+ a = c;
+ cthing = doThing();
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/shadowedPrimitiveCmpEqNull.qml b/tests/auto/qml/qmlcppcodegen/data/shadowedPrimitiveCmpEqNull.qml
new file mode 100644
index 0000000000..0e130b9afc
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/shadowedPrimitiveCmpEqNull.qml
@@ -0,0 +1,16 @@
+import QtQuick
+
+QtObject {
+ id: win
+
+ component Foo: QtObject {
+ property int progress: 0
+ }
+
+ property int progress: 0
+ readonly property Foo configuring: Foo {}
+
+ Component.onCompleted: {
+ win.configuring.progress = win?.progress ?? 0
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/shared/Slider.qml b/tests/auto/qml/qmlcppcodegen/data/shared/Slider.qml
index 58a567f4db..3a0349966d 100644
--- a/tests/auto/qml/qmlcppcodegen/data/shared/Slider.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/shared/Slider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/qml/qmlcppcodegen/data/signalsWithLists.qml b/tests/auto/qml/qmlcppcodegen/data/signalsWithLists.qml
new file mode 100644
index 0000000000..9a07b206d4
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/signalsWithLists.qml
@@ -0,0 +1,18 @@
+pragma Strict
+import QtQml
+import TestTypes
+
+Person {
+ property list<var> varlist: [1, "foo", this, undefined, true]
+ property list<QtObject> objlist: [this, null, this]
+
+ function sendSignals() {
+ variantListHappened(varlist);
+ objectListHappened(objlist);
+ }
+
+ property int happening: 0
+
+ onObjectListHappened: (objects) => { happening += objects.length }
+ onVariantListHappened: (variants) => { happening += variants.length }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/state.h b/tests/auto/qml/qmlcppcodegen/data/state.h
index 1afcebc4ea..708e681781 100644
--- a/tests/auto/qml/qmlcppcodegen/data/state.h
+++ b/tests/auto/qml/qmlcppcodegen/data/state.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef STATE_H
#define STATE_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/structuredValueType.qml b/tests/auto/qml/qmlcppcodegen/data/structuredValueType.qml
new file mode 100644
index 0000000000..158dff2d0b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/structuredValueType.qml
@@ -0,0 +1,8 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property rect r: ({x: 1, y: 2, width: 3, height: 4})
+ property rect r2: { var x = 42; return {x}; }
+ property weatherModelUrl w: ({ strings: ["one", "two", "three"] })
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/theme.cpp b/tests/auto/qml/qmlcppcodegen/data/theme.cpp
index c8a2612753..10302645c0 100644
--- a/tests/auto/qml/qmlcppcodegen/data/theme.cpp
+++ b/tests/auto/qml/qmlcppcodegen/data/theme.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "theme.h"
diff --git a/tests/auto/qml/qmlcppcodegen/data/theme.h b/tests/auto/qml/qmlcppcodegen/data/theme.h
index f70a3b440e..3e56ec1f9f 100644
--- a/tests/auto/qml/qmlcppcodegen/data/theme.h
+++ b/tests/auto/qml/qmlcppcodegen/data/theme.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef THEME_H
#define THEME_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/thisObject.qml b/tests/auto/qml/qmlcppcodegen/data/thisObject.qml
new file mode 100644
index 0000000000..50664eced2
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/thisObject.qml
@@ -0,0 +1,11 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property QtObject warned
+
+ function f(arg: QtObject) { warned = arg }
+ function warn() { f(this) }
+
+ Component.onCompleted: warn()
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/timelinetheme.cpp b/tests/auto/qml/qmlcppcodegen/data/timelinetheme.cpp
index 1853d2dc12..04e1797c7c 100644
--- a/tests/auto/qml/qmlcppcodegen/data/timelinetheme.cpp
+++ b/tests/auto/qml/qmlcppcodegen/data/timelinetheme.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "timelinetheme.h"
diff --git a/tests/auto/qml/qmlcppcodegen/data/timelinetheme.h b/tests/auto/qml/qmlcppcodegen/data/timelinetheme.h
index 335e43b570..3e7da77cc9 100644
--- a/tests/auto/qml/qmlcppcodegen/data/timelinetheme.h
+++ b/tests/auto/qml/qmlcppcodegen/data/timelinetheme.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TIMELINETHEME_H
#define TIMELINETHEME_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/topLevelComponent.qml b/tests/auto/qml/qmlcppcodegen/data/topLevelComponent.qml
new file mode 100644
index 0000000000..a73e28f642
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/topLevelComponent.qml
@@ -0,0 +1,14 @@
+pragma Strict
+import QtQml
+
+Component {
+ QtObject {
+ id: root
+
+ function myOpen() {
+ root.objectName = "foo"
+ }
+
+ Component.onCompleted: myOpen()
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/trigraphs.qml b/tests/auto/qml/qmlcppcodegen/data/trigraphs.qml
new file mode 100644
index 0000000000..e7bf5ccec9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/trigraphs.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ objectName: "??= ??/ ??' ??( ??) ??! ??< ??> ??-"
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/tst_qmlcppcodegen_verify.cpp b/tests/auto/qml/qmlcppcodegen/data/tst_qmlcppcodegen_verify.cpp
new file mode 100644
index 0000000000..02629ad7f6
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/tst_qmlcppcodegen_verify.cpp
@@ -0,0 +1,47 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+
+#include <QtTest>
+#include <QtCore/qobject.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qbytearray.h>
+
+class tst_QmlCppCodegenVerify : public QObject
+{
+ Q_OBJECT
+private slots:
+ void verifyGeneratedSources_data();
+ void verifyGeneratedSources();
+};
+
+void tst_QmlCppCodegenVerify::verifyGeneratedSources_data()
+{
+ QTest::addColumn<QString>("file");
+
+ QDir a(":/a");
+ const QStringList entries = a.entryList(QDir::Files);
+ for (const QString &entry : entries)
+ QTest::addRow("%s", entry.toUtf8().constData()) << entry;
+}
+
+void tst_QmlCppCodegenVerify::verifyGeneratedSources()
+{
+ QFETCH(QString, file);
+ QFile a(":/a/" + file);
+ QFile b(":/b/" + file.replace("codegen_test_module", "codegen_test_module_verify"));
+
+ QVERIFY(a.open(QIODevice::ReadOnly));
+ QVERIFY(b.open(QIODevice::ReadOnly));
+
+ const QByteArray aData = a.readAll();
+ const QByteArray bData = b.readAll()
+ .replace("verify/TestTypes", "TestTypes")
+ .replace("verify_TestTypes", "TestTypes");
+
+ QCOMPARE(aData, bData);
+}
+
+QTEST_MAIN(tst_QmlCppCodegenVerify)
+
+#include "tst_qmlcppcodegen_verify.moc"
diff --git a/tests/auto/qml/qmlcppcodegen/data/undefinedToDouble.qml b/tests/auto/qml/qmlcppcodegen/data/undefinedToDouble.qml
new file mode 100644
index 0000000000..e76443a2e0
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/undefinedToDouble.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property double d: Math.max(undefined, 40)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/urlString.qml b/tests/auto/qml/qmlcppcodegen/data/urlString.qml
index 511c54532c..a83855ebdb 100644
--- a/tests/auto/qml/qmlcppcodegen/data/urlString.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/urlString.qml
@@ -9,5 +9,12 @@ QtObject {
Component.onCompleted: {
c = "http://dddddd.com";
self.d = "http://aaaaaa.com";
+ myUrlChanged(c)
+ }
+
+ signal myUrlChanged(urlParam: url)
+
+ onMyUrlChanged: (urlParam) => {
+ objectName = urlParam;
}
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/valueTypeCast.qml b/tests/auto/qml/qmlcppcodegen/data/valueTypeCast.qml
new file mode 100644
index 0000000000..a775773dda
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/valueTypeCast.qml
@@ -0,0 +1,43 @@
+pragma ValueTypeBehavior: Addressable
+import QtQml
+
+QtObject {
+ id: root
+ property rect r: Qt.rect(10, 20, 3, 4)
+ property var v: r
+ property real x: (v as rect).x
+
+ function f(input: bool) : var {
+ if (input)
+ return 0
+ return Qt.point(2, 2)
+ }
+
+ property var vv: Qt.point(5, 5)
+ property var uu: undefined
+
+ property int tv3: (root.vv as point)?.x
+ property var tv4: (root.uu as rect)?.x
+ property int tc3: (root?.vv as point)?.y
+ property var tc6: (root?.uu as rect)?.height
+ property var tc7: (f(true) as point)?.x
+ property var tc8: (f(false) as point)?.x
+
+ property string greeting1
+ property string greeting2
+
+ readonly property string defaultGreeting: "Default Greeting"
+ property QtObject o: QtObject {
+ id: o
+ property var customGreeting
+ function greet() : string {
+ return (o.customGreeting as string) ?? root.defaultGreeting
+ }
+ }
+
+ Component.onCompleted: {
+ root.greeting1 = o.greet()
+ o.customGreeting = "Custom Greeting"
+ root.greeting2 = o.greet()
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/valueTypeCopy.qml b/tests/auto/qml/qmlcppcodegen/data/valueTypeCopy.qml
index cca634753d..d33133bb6b 100644
--- a/tests/auto/qml/qmlcppcodegen/data/valueTypeCopy.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/valueTypeCopy.qml
@@ -1,4 +1,4 @@
-pragma ValueTypeBehavior: Copy
+pragma ValueTypeBehavior: Copy, Addressable
import QtQml
QtObject {
diff --git a/tests/auto/qml/qmlcppcodegen/data/valueTypeDefault.qml b/tests/auto/qml/qmlcppcodegen/data/valueTypeDefault.qml
new file mode 100644
index 0000000000..42a55e832d
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/valueTypeDefault.qml
@@ -0,0 +1,34 @@
+import QtQml
+
+
+QtObject {
+ id: root
+
+ property list<double> numbers: {
+ var result = [];
+ for (var i = 0; i < 10; ++i)
+ result[i] = i;
+ return result;
+ }
+
+ property rect r: ({x: 1, y: 2, width: 3, height: 4})
+
+ function evil() : double {
+ var numbers = root.numbers;
+ root.numbers = [];
+ var a = 0;
+ for (var j = 0; j < 10; ++j) {
+ a += numbers[j];
+ }
+ return a;
+ }
+
+ function fvil() : double {
+ var r = root.r;
+ root.r = {x: 5, y: 6, width: 7, height: 8};
+ return r.x;
+ }
+
+ property double e: evil()
+ property double f: fvil()
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/valueTypeReference.qml b/tests/auto/qml/qmlcppcodegen/data/valueTypeReference.qml
index 568f39820c..a87f88ecf9 100644
--- a/tests/auto/qml/qmlcppcodegen/data/valueTypeReference.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/valueTypeReference.qml
@@ -1,4 +1,4 @@
-pragma ValueTypeBehavior: Reference
+pragma ValueTypeBehavior: Reference, Inaddressable
import QtQml
QtObject {
diff --git a/tests/auto/qml/qmlcppcodegen/data/variantMap.qml b/tests/auto/qml/qmlcppcodegen/data/variantMap.qml
new file mode 100644
index 0000000000..d7147ec5fc
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/variantMap.qml
@@ -0,0 +1,27 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property Component shadowable: QtObject {}
+ property B b: B { id: theB }
+ property rect r: theB.r
+ property var v: { "1": null, "25": undefined, "19": "19" }
+
+ property Component c: Component {
+ id: unshadowable
+ QtObject {}
+ }
+
+ // We need this extra function in order to coerce the result of the shadowable
+ // method call back to QtObject
+ function createShadowable() : QtObject {
+ return shadowable.createObject(this, {objectName: "a"})
+ }
+
+ objectName: {
+ return createShadowable().objectName
+ + " " + unshadowable.createObject(this, {objectName: "b"}).objectName
+ }
+
+ Component.onCompleted: b.r = { x: 12, y: 13, width: 14, height: 15 }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.h b/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.h
new file mode 100644
index 0000000000..61d38228b0
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.h
@@ -0,0 +1,17 @@
+#pragma once
+#include <QObject>
+#include <QVariantMap>
+#include <QtQml/qqmlregistration.h>
+
+class VariantMapLookupFoo : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(QVariantMap data READ data CONSTANT)
+
+public:
+ VariantMapLookupFoo(QObject *parent = nullptr) : QObject(parent) { }
+
+private:
+ QVariantMap data() const { return { { "value", 42 } }; }
+};
diff --git a/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.qml b/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.qml
new file mode 100644
index 0000000000..4e56cb9448
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.qml
@@ -0,0 +1,11 @@
+pragma Strict
+import TestTypes
+import QtQuick
+
+Item {
+ property int i: moo.data.value
+
+ VariantMapLookupFoo {
+ id: moo
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/variantReturn.qml b/tests/auto/qml/qmlcppcodegen/data/variantReturn.qml
new file mode 100644
index 0000000000..cca26265c9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/variantReturn.qml
@@ -0,0 +1,15 @@
+pragma Strict
+import QtQml
+import TestTypes
+
+QtObject {
+ property DirectBindable a: DirectBindable {
+ id: aId
+ x: WeatherModelUrlUtils.url(1)
+ }
+
+ property IndirectBindable b: IndirectBindable {
+ id: bId
+ y: aId.x
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/variantreturn.h b/tests/auto/qml/qmlcppcodegen/data/variantreturn.h
new file mode 100644
index 0000000000..87718aaef3
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/variantreturn.h
@@ -0,0 +1,63 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef VARIANTERETURN_H
+#define VARIANTERETURN_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qproperty.h>
+#include <QtQml/qqmlregistration.h>
+
+#include "weathermoduleurl.h"
+
+class DirectBindable : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(WeatherModelUrl x READ x WRITE setX NOTIFY xChanged BINDABLE bindableX)
+
+public:
+ explicit DirectBindable(QObject *parent = nullptr) : QObject(parent) {}
+
+ WeatherModelUrl x() const { return m_x.value(); }
+ void setX(const WeatherModelUrl& newX) { m_x.setValue(newX);}
+ QBindable<WeatherModelUrl> bindableX() { return QBindable<WeatherModelUrl>(&m_x); }
+
+Q_SIGNALS:
+ void xChanged();
+
+private:
+ Q_OBJECT_BINDABLE_PROPERTY(DirectBindable, WeatherModelUrl, m_x, &DirectBindable::xChanged)
+};
+
+class IndirectBindable : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(WeatherModelUrl y READ y WRITE setY NOTIFY yChanged BINDABLE bindableY)
+ Q_PROPERTY(int z READ z NOTIFY zChanged)
+
+public:
+ explicit IndirectBindable(QObject *parent = nullptr) : QObject(parent) {
+ m_z.setBinding([this]()->int {
+ return m_y.value().timeIndex() * 2;
+ });
+ }
+
+ WeatherModelUrl y() const { return m_y.value(); }
+ void setY(const WeatherModelUrl& newY) { m_y.setValue(newY); }
+ QBindable<WeatherModelUrl> bindableY() { return QBindable<WeatherModelUrl>(&m_y); }
+
+ int z() const { return m_z.value(); }
+ QBindable<int> bindableZ() const { return QBindable<int>(&m_z); }
+
+Q_SIGNALS:
+ void yChanged();
+ void zChanged();
+
+private:
+ Q_OBJECT_BINDABLE_PROPERTY(IndirectBindable, WeatherModelUrl, m_y, &IndirectBindable::yChanged)
+ Q_OBJECT_BINDABLE_PROPERTY(IndirectBindable, int, m_z, &IndirectBindable::zChanged)
+};
+
+#endif // VARIANTRETURN_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/voidConversion.qml b/tests/auto/qml/qmlcppcodegen/data/voidConversion.qml
new file mode 100644
index 0000000000..f5826d9e48
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/voidConversion.qml
@@ -0,0 +1,10 @@
+import QtQml
+
+QtObject {
+ id: item
+ property point p: Qt.point(20, 10)
+
+ Component.onCompleted: {
+ item.p = undefined
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/weathermoduleurl.h b/tests/auto/qml/qmlcppcodegen/data/weathermoduleurl.h
new file mode 100644
index 0000000000..998118dc5b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/weathermoduleurl.h
@@ -0,0 +1,61 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef WEATHERMODELURL_H
+#define WEATHERMODELURL_H
+
+#include <QtQml/qqmlregistration.h>
+#include <QtCore/qobject.h>
+
+class WeatherModelUrl
+{
+ Q_GADGET
+ QML_STRUCTURED_VALUE
+ QML_VALUE_TYPE(weatherModelUrl)
+ Q_PROPERTY(qsizetype timeIndex READ timeIndex CONSTANT)
+ Q_PROPERTY(QStringList strings READ strings WRITE setStrings)
+
+public:
+ WeatherModelUrl() : m_timeIndex(-1) {}
+ WeatherModelUrl(qsizetype timeIdx) : m_timeIndex(timeIdx) {}
+
+ qsizetype timeIndex() const { return m_timeIndex; }
+
+ QStringList strings() const { return m_strings; }
+ void setStrings(const QStringList &newStrings)
+ {
+ if (m_strings != newStrings)
+ m_strings = newStrings;
+ }
+
+private:
+ friend bool operator==(const WeatherModelUrl &a, const WeatherModelUrl &b)
+ {
+ return a.m_timeIndex == b.m_timeIndex;
+ }
+
+ friend bool operator!=(const WeatherModelUrl &a, const WeatherModelUrl &b)
+ {
+ return !(a == b);
+ }
+
+ qsizetype m_timeIndex;
+ QStringList m_strings;
+};
+
+class WeatherModelUrlUtils : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+
+public:
+ WeatherModelUrlUtils(QObject *parent = nullptr) : QObject(parent) {}
+
+ Q_INVOKABLE static WeatherModelUrl url(int timeIdx)
+ {
+ return WeatherModelUrl(timeIdx);
+ }
+};
+
+#endif // WEATHERMODELURL_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/withlength.h b/tests/auto/qml/qmlcppcodegen/data/withlength.h
index ba95522c53..26c6307f2b 100644
--- a/tests/auto/qml/qmlcppcodegen/data/withlength.h
+++ b/tests/auto/qml/qmlcppcodegen/data/withlength.h
@@ -1,11 +1,13 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef WITHLENGTH_H
#define WITHLENGTH_H
#include <QtCore/qobject.h>
-#include <QtQmlIntegration/qqmlintegration.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+#include <QtQml/qqml.h>
struct ValueTypeWithLength
{
@@ -18,6 +20,8 @@ struct ValueTypeWithLength
public:
ValueTypeWithLength() = default;
Q_INVOKABLE ValueTypeWithLength(int length) : m_length(length) {}
+ Q_INVOKABLE ValueTypeWithLength(QPointF point) : m_length(point.manhattanLength()) {}
+ Q_INVOKABLE ValueTypeWithLength(QRectF rect) : m_length(rect.width()) {}
Q_INVOKABLE QString toString() const { return QStringLiteral("no"); }
int length() const { return m_length; }
@@ -26,4 +30,24 @@ private:
int m_length = 19;
};
+struct InnerWithLength {
+ int m_length;
+};
+
+struct UnconstructibleWithLength
+{
+ Q_GADGET
+ QML_VALUE_TYPE(unconstructibleWithLength)
+
+ QML_FOREIGN(InnerWithLength)
+ QML_EXTENDED(UnconstructibleWithLength)
+
+public:
+ UnconstructibleWithLength() = default;
+ Q_INVOKABLE UnconstructibleWithLength(int length) : v{length} {}
+
+private:
+ InnerWithLength v;
+};
+
#endif // WITHLENGTH_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/wrapwithvariant.h b/tests/auto/qml/qmlcppcodegen/data/wrapwithvariant.h
index dce78fa9c9..7de49f095a 100644
--- a/tests/auto/qml/qmlcppcodegen/data/wrapwithvariant.h
+++ b/tests/auto/qml/qmlcppcodegen/data/wrapwithvariant.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef WRAPWITHVARIANT_H
#define WRAPWITHVARIANT_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/writableVariantMap.h b/tests/auto/qml/qmlcppcodegen/data/writableVariantMap.h
new file mode 100644
index 0000000000..3c0fedd28b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/writableVariantMap.h
@@ -0,0 +1,31 @@
+#pragma once
+#include <QObject>
+#include <QVariantMap>
+#include <QtQml/qqmlregistration.h>
+
+class WritableVariantMap : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(QVariantMap data READ data WRITE setData NOTIFY dataChanged)
+
+public:
+ WritableVariantMap(QObject *parent = nullptr) : QObject(parent) { }
+
+ QVariantMap data() const { return m_data; }
+ void setData(const QVariantMap &data)
+ {
+ if (m_data != data) {
+ m_data = data;
+ emit dataChanged();
+ }
+ }
+
+signals:
+ void dataChanged();
+
+private:
+ QVariantMap m_data;
+};
+
+
diff --git a/tests/auto/qml/qmlcppcodegen/data/writeVariantMap.qml b/tests/auto/qml/qmlcppcodegen/data/writeVariantMap.qml
new file mode 100644
index 0000000000..536e53b408
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/writeVariantMap.qml
@@ -0,0 +1,10 @@
+pragma Strict
+import StringBuilderTestTypes
+
+WritableVariantMap {
+ id: dragSource
+ property string modelData: "Drag Me"
+ data: ({
+ "text/plain": "%" + dragSource.modelData + "%"
+ })
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/writeback.qml b/tests/auto/qml/qmlcppcodegen/data/writeback.qml
new file mode 100644
index 0000000000..359f00efb7
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/writeback.qml
@@ -0,0 +1,43 @@
+pragma Strict
+
+import TestTypes
+import QtQml
+
+Person {
+ id: self
+
+ area {
+ width: 19
+ height: 199
+ }
+
+ property list<int> ints: [4, 3, 2, 1]
+
+ property outer recursive
+ property Person shadowable: Person {
+ id: notShadowable
+ area.width: self.area.width
+ area2.height: self.area2.height
+ }
+
+ Component.onCompleted: {
+ area.width = 16
+ area2.height = 17
+
+ self.area.x = 4
+ self.area2.y = 5
+
+ // You cannot do this on the shadowable Person because
+ // shadowable.area may not actually be a QRectF anymore.
+ notShadowable.area.x = 40
+ notShadowable.area2.y = 50
+
+ self.recursive.inner.i = 99;
+
+ self.ints[0] = 12;
+ ints[1] = 22;
+ ints[6] = 33;
+ }
+
+ property int inner: recursive.inner.i
+}
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index 400075c08d..53cc068e8c 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -1,10 +1,16 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-#include "data/druggeljug.h"
#include <data/birthdayparty.h>
#include <data/cppbaseclass.h>
+#include <data/druggeljug.h>
+#include <data/enumProperty.h>
#include <data/enumproblems.h>
+#include <data/getOptionalLookup.h>
#include <data/objectwithmethod.h>
+#include <data/resettable.h>
+#include <data/weathermoduleurl.h>
+#include <data/withlength.h>
#include <QtQml/private/qqmlengine_p.h>
#include <QtQml/private/qqmlpropertycachecreator_p.h>
@@ -12,6 +18,7 @@
#include <QtTest>
#include <QtQml>
#include <QtGui/qcolor.h>
+#include <QtGui/qpa/qplatformdialoghelper.h>
#if QT_CONFIG(process)
#include <QtCore/qprocess.h>
@@ -26,146 +33,460 @@ class tst_QmlCppCodegen : public QObject
Q_OBJECT
private slots:
void initTestCase();
+ void cleanupTestCase();
- void simpleBinding();
- void cppValueTypeList();
+ void accessModelMethodFromOutSide();
+ void aliasLookup();
+ void ambiguousAs();
+ void ambiguousSignals();
void anchorsFill();
- void signalHandler();
- void idAccess();
- void globals();
- void multiLookup();
- void enums();
- void funcWithParams();
- void intOverflow();
- void stringLength();
- void scopeVsObject();
- void compositeTypeMethod();
- void excessiveParameters();
- void jsImport();
- void jsmoduleImport();
- void methods();
- void math();
- void unknownParameter();
+ void argumentConversion();
void array();
- void equalsUndefined();
- void conversions();
- void interestingFiles_data();
- void interestingFiles();
- void extendedTypes();
- void construct();
- void contextParam();
- void attachedType();
- void componentReturnType();
- void onAssignment();
- void failures();
- void enumScope();
- void unusedAttached();
+ void arrayCtor();
+ void asCast();
void attachedBaseEnum();
- void nullAccess();
- void interceptor();
- void nonNotifyable();
- void importsFromImportPath();
- void aliasLookup();
- void outOfBoundsArray();
- void compositeSingleton();
- void lotsOfRegisters();
- void inPlaceDecrement();
- void shifts();
- void valueTypeProperty();
- void propertyOfParent();
- void accessModelMethodFromOutSide();
- void functionArguments();
+ void attachedSelf();
+ void attachedType();
+ void badSequence();
+ void basicBlocksWithBackJump();
+ void basicBlocksWithBackJump_infinite();
+ void basicDTZ();
+ void bindToValueType();
void bindingExpression();
- void voidFunction();
- void overriddenProperty();
- void listLength();
- void parentProperty();
- void registerElimination();
- void asCast();
- void noQQmlData();
- void scopeObjectDestruction();
+ void blockComments();
+ void boolCoercions();
+ void boolPointerMerge();
+ void boundComponents();
+ void callContextPropertyLookupResult();
+ void callWithSpread();
void colorAsVariant();
- void bindToValueType();
- void undefinedResets();
- void innerObjectNonShadowable();
- void ownPropertiesNonShadowable();
- void modulePrefix();
void colorString();
- void urlString();
- void callContextPropertyLookupResult();
+ void compareOriginals();
+ void comparisonTypes();
+ void componentReturnType();
+ void compositeSingleton();
+ void compositeTypeMethod();
+ void consoleObject();
+ void consoleTrace();
+ void construct();
+ void contextParam();
+ void conversionDecrement();
+ void conversionInDeadCode();
+ void conversions();
+ void convertPrimitiveToVar();
+ void convertQJSPrimitiveValueToIntegral();
+ void convertToOriginalReadAcumulatorForUnaryOperators();
+ void cppMethodListReturnType();
+ void cppValueTypeList();
+ void dateConstruction();
+ void dateConversions();
void deadShoeSize();
- void listIndices();
- void jsMathObject();
- void intEnumCompare();
- void attachedSelf();
- void functionReturningVoid();
- void functionCallOnNamespaced();
+ void dialogButtonBox();
+ void enumConversion();
+ void enumFromBadSingleton();
+ void enumLookup();
+ void enumMarkedAsFlag();
+ void enumProblems();
+ void enumScope();
+ void enums();
+ void enforceSignature();
+ void enumsInOtherObject();
+ void equalityQObjects();
+ void equalityQUrl();
+ void equalityTestsWithNullOrUndefined();
+ void equalityVarAndNonStorable();
+ void equalityVarAndStorable();
+ void equalsUndefined();
+ void evadingAmbiguity();
+ void exceptionFromInner();
+ void excessiveParameters();
+ void extendedTypes();
+ void failures();
+ void fallbackLookups();
+ void fileImportsContainCxxTypes();
+ void flagEnum();
void flushBeforeCapture();
- void unknownAttached();
- void variantlist();
- void popContextAfterRet();
- void revisions();
- void invisibleBase();
- void notEqualsInt();
- void infinities();
- void blockComments();
+ void fromBoolValue();
+ void funcWithParams();
+ void functionArguments();
+ void functionCallOnNamespaced();
void functionLookup();
- void objectInVar();
+ void functionReturningVoid();
void functionTakingVar();
- void testIsnan();
- void fallbackLookups();
- void typedArray();
- void prefixedType();
- void evadingAmbiguity();
- void fromBoolValue();
- void invisibleTypes();
+ void getLookupOfScript();
+ void getOptionalLookup();
+ void getOptionalLookup_data();
+ void getOptionalLookupOnQJSValueNonStrict();
+ void getOptionalLookupShadowed();
+ void globals();
+ void idAccess();
+ void ignoredFunctionReturn();
+ void importsFromImportPath();
+ void inPlaceDecrement();
+ void inaccessibleProperty();
+ void indirectlyShadowable();
+ void infinities();
+ void infinitiesToInt();
+ void innerObjectNonShadowable();
+ void intEnumCompare();
+ void intOverflow();
+ void intToEnum();
+ void interceptor();
+ void interestingFiles();
+ void interestingFiles_data();
+ void internalConversion();
void invalidPropertyType();
- void valueTypeLists();
- void boundComponents();
+ void invisibleBase();
void invisibleListElementType();
- void typePropertyClash();
- void objectToString();
- void throwObjectName();
+ void invisibleSingleton();
+ void invisibleTypes();
+ void iteration();
void javaScriptArgument();
- void translation();
- void stringArg();
- void conversionDecrement();
- void unstoredUndefined();
- void registerPropagation();
- void argumentConversion();
- void badSequence();
- void enumLookup();
- void trivialSignalHandler();
- void stringToByteArray();
+ void jsArrayMethods();
+ void jsArrayMethodsWithParams();
+ void jsArrayMethodsWithParams_data();
+ void jsImport();
+ void jsMathObject();
+ void jsmoduleImport();
+ void lengthAccessArraySequenceCompat();
+ void letAndConst();
+ void listAsArgument();
+ void listConversion();
+ void listIndices();
+ void listLength();
+ void listOfInvisible();
void listPropertyAsModel();
- void notNotString();
+ void listToString();
+ void lotsOfRegisters();
+ void math();
+ void mathMinMax();
void mathOperations();
- void inaccessibleProperty();
- void typePropagationLoop();
- void signatureIgnored();
- void listAsArgument();
- void letAndConst();
- void signalIndexMismatch();
- void callWithSpread();
- void nullComparison();
- void consoleObject();
+ void mathStaticProperties();
+ void mergedObjectReadWrite();
+ void methodOnListLookup();
+ void methods();
+ void modulePrefix();
+ void multiDirectory_data();
+ void multiDirectory();
void multiForeign();
+ void multiLookup();
+ void multipleCtors();
void namespaceWithEnum();
- void enumProblems();
- void enumConversion();
- void ambiguousSignals();
- void fileImportsContainCxxTypes();
- void lengthAccessArraySequenceCompat();
- void storeElementSideEffects();
+ void noQQmlData();
+ void nonNotifyable();
+ void notEqualsInt();
+ void notNotString();
+ void nullAccess();
+ void nullAccessInsideSignalHandler();
+ void nullComparison();
+ void nullishCoalescing();
+ void nullishCoalescing_data();
void numbersInJsPrimitive();
- void infinitiesToInt();
- void equalityVarAndNonStorable();
- void equalityQObjects();
- void dateConversions();
+ void objectInVar();
+ void objectLookupOnListElement();
+ void objectToString();
+ void objectWithStringListMethod();
+ void onAssignment();
+ void optionalComparison();
+ void outOfBoundsArray();
+ void overriddenProperty();
+ void ownPropertiesNonShadowable();
+ void parentProperty();
+ void popContextAfterRet();
+ void prefixedType();
+ void propertyOfParent();
+ void reduceWithNullThis();
+ void readEnumFromInstance();
+ void readonlyListProperty();
+ void registerElimination();
+ void registerPropagation();
+ void renameAdjust();
+
+ void resettableProperty();
+ void resettableProperty_data();
+
+ void returnAfterReject();
+ void revisions();
+ void scopeIdLookup();
+ void scopeObjectDestruction();
+ void scopeVsObject();
+ void scopedEnum();
+ void sequenceToIterable();
+ void setLookupConversion();
+ void setLookupOriginalScope();
+ void shadowedAsCasts();
+ void shadowedMethod();
+ void shadowedPrimitiveCmpEqNull();
+ void shifts();
+ void signalHandler();
+ void signalIndexMismatch();
+ void signalsWithLists();
+ void signatureIgnored();
+ void simpleBinding();
+ void storeElementSideEffects();
+ void storeMetaEnum();
+ void stringArg();
+ void stringLength();
+ void stringToByteArray();
+ void structuredValueType();
+ void testIsnan();
+ void thisObject();
+ void throwObjectName();
+ void topLevelComponent();
+ void translation();
+ void trigraphs();
+ void trivialSignalHandler();
+ void typePropagationLoop();
+ void typePropertyClash();
+ void typedArray();
+ void undefinedResets();
+ void undefinedToDouble();
+ void unknownAttached();
+ void unknownParameter();
+ void unstoredUndefined();
+ void unusedAttached();
+ void urlString();
void valueTypeBehavior();
- void invisibleSingleton();
+ void valueTypeLists();
+ void valueTypeProperty();
+ void variantMapLookup();
+ void variantReturn();
+ void variantlist();
+ void variantMap();
+ void voidConversion();
+ void voidFunction();
+ void writeBack();
+ void writeVariantMap();
};
+static QByteArray arg1()
+{
+ const QStringList args = QCoreApplication::instance()->arguments();
+ return args.size() > 1 ? args[1].toUtf8() : QByteArray("undefined");
+}
+
+namespace QmlCacheGeneratedCode {
+namespace _qt_qml_TestTypes_failures_qml {
+extern const QQmlPrivate::AOTCompiledFunction aotBuiltFunctions[];
+}
+}
+
+static void checkColorProperties(QQmlComponent *component)
+{
+ QVERIFY2(component->isReady(), qPrintable(component->errorString()));
+ QScopedPointer<QObject> rootObject(component->create());
+ QVERIFY(rootObject);
+
+ const QMetaObject *mo = QMetaType::fromName("QQuickIcon").metaObject();
+ QVERIFY(mo != nullptr);
+
+ const QMetaProperty prop = mo->property(mo->indexOfProperty("color"));
+ QVERIFY(prop.isValid());
+
+ const QVariant a = rootObject->property("a");
+ QVERIFY(a.isValid());
+
+ const QVariant iconColor = prop.readOnGadget(rootObject->property("icon").data());
+ QVERIFY(iconColor.isValid());
+
+ const QMetaType colorType = QMetaType::fromName("QColor");
+ QVERIFY(colorType.isValid());
+
+ QCOMPARE(a.metaType(), colorType);
+ QCOMPARE(iconColor.metaType(), colorType);
+
+ QCOMPARE(iconColor, a);
+}
+
+static const double numbers[] = {
+ qQNaN(), -qInf(),
+ std::numeric_limits<double>::min(),
+ std::numeric_limits<float>::min(),
+ std::numeric_limits<qint32>::min(),
+ -1000.2, -100, -2, -1.333, -1, -0.84, -0.5,
+
+ // -0 and 0 are not different on the QML side. Therefore, don't keep them adjacent.
+ // Otherwise the bindings won't get re-evaluated.
+ std::copysign(0.0, -1), 1, 0.0,
+
+ 0.5, 0.77, 1.4545, 2, 199, 2002.13,
+ std::numeric_limits<qint32>::max(),
+ std::numeric_limits<quint32>::max(),
+ std::numeric_limits<float>::max(),
+ std::numeric_limits<double>::max(),
+ qInf()
+};
+
+class MyCppType : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool useListDelegate
+ READ useListDelegate
+ WRITE setUseListDelegate
+ NOTIFY useListDelegateChanged)
+public:
+ explicit MyCppType(QObject * parent = nullptr) : QObject(parent) {}
+
+ bool useListDelegate() const { return m_useListDelegate; }
+ void setUseListDelegate(bool useListDelegate)
+ {
+ if (useListDelegate != m_useListDelegate) {
+ m_useListDelegate = useListDelegate;
+ emit useListDelegateChanged();
+ }
+ }
+
+signals:
+ void useListDelegateChanged();
+
+private:
+ bool m_useListDelegate = false;
+};
+
+class InvisibleListElementType : public QObject
+{
+ Q_OBJECT
+public:
+ InvisibleListElementType(QObject *parent = nullptr) : QObject(parent) {}
+};
+
+template<typename T>
+QString toOperand(double arg);
+
+template<>
+QString toOperand<double>(double arg)
+{
+ if (qIsNull(arg))
+ return std::signbit(arg) ? QStringLiteral("(-0)") : QStringLiteral("(0)");
+
+ return u'(' + QJSPrimitiveValue(arg).toString() + u')';
+}
+
+template<>
+QString toOperand<int>(double arg)
+{
+ const int iArg = QJSPrimitiveValue(arg).toInteger();
+ return u'(' + QJSPrimitiveValue(iArg).toString() + u')';
+}
+
+template<>
+QString toOperand<bool>(double arg)
+{
+ const bool bArg = QJSPrimitiveValue(arg).toBoolean();
+ return u'(' + QJSPrimitiveValue(bArg).toString() + u')';
+}
+
+template<typename T1, typename T2>
+double jsEval(double arg1, double arg2, const QString &op, QJSEngine *engine)
+{
+ auto evalBinary = [&](const QString &jsOp) {
+ return engine->evaluate(toOperand<T1>(arg1) + jsOp + toOperand<T2>(arg2)).toNumber();
+ };
+
+ auto evalBinaryConst = [&](const QString &jsOp) {
+ return engine->evaluate(toOperand<T1>(arg1) + jsOp + u'9').toNumber();
+ };
+
+ auto evalUnary = [&](const QString &jsOp) {
+ return engine->evaluate(jsOp + toOperand<T1>(arg1)).toNumber();
+ };
+
+ auto evalInPlace = [&](const QString &jsOp) {
+ return engine->evaluate(
+ u"(function() {var a = "_s + toOperand<T1>(arg1)+ u"; return "_s
+ + jsOp + u"a;})()"_s).toNumber();
+ };
+
+ if (op == u"unot")
+ return evalUnary(u"!"_s);
+ if (op == u"uplus")
+ return evalUnary(u"+"_s);
+ if (op == u"uminus")
+ return evalUnary(u"-"_s);
+ if (op == u"ucompl")
+ return evalUnary(u"~"_s);
+
+ if (op == u"increment")
+ return evalInPlace(u"++"_s);
+ if (op == u"decrement")
+ return evalInPlace(u"--"_s);
+
+ if (op == u"add")
+ return evalBinary(u"+"_s);
+ if (op == u"sub")
+ return evalBinary(u"-"_s);
+ if (op == u"mul")
+ return evalBinary(u"*"_s);
+ if (op == u"div")
+ return evalBinary(u"/"_s);
+ if (op == u"exp")
+ return evalBinary(u"**"_s);
+ if (op == u"mod")
+ return evalBinary(u"%"_s);
+
+ if (op == u"bitAnd")
+ return evalBinary(u"&"_s);
+ if (op == u"bitOr")
+ return evalBinary(u"|"_s);
+ if (op == u"bitXor")
+ return evalBinary(u"^"_s);
+
+ if (op == u"bitAndConst")
+ return evalBinaryConst(u"&"_s);
+ if (op == u"bitOrConst")
+ return evalBinaryConst(u"|"_s);
+ if (op == u"bitXorConst")
+ return evalBinaryConst(u"^"_s);
+
+ if (op == u"ushr")
+ return evalBinary(u">>>"_s);
+ if (op == u"shr")
+ return evalBinary(u">>"_s);
+ if (op == u"shl")
+ return evalBinary(u"<<"_s);
+
+ if (op == u"ushrConst")
+ return evalBinaryConst(u">>>"_s);
+ if (op == u"shrConst")
+ return evalBinaryConst(u">>"_s);
+ if (op == u"shlConst")
+ return evalBinaryConst(u"<<"_s);
+
+ qDebug() << op;
+ Q_UNREACHABLE_RETURN(0);
+}
+
+static QList<QString> convertToStrings(const QList<qint64> &ints)
+{
+ QList<QString> strings;
+ for (qint64 i : ints)
+ strings.append(QString::number(i));
+ return strings;
+}
+
+static QRegularExpression bindingLoopMessage(const QUrl &url, char var)
+{
+ // The actual string depends on how many times QObject* was registered with what parameters.
+ return QRegularExpression(
+ "%1:4:1: QML [^:]+: Binding loop detected for property \"%2\""_L1
+ .arg(url.toString()).arg(QLatin1Char(var)));
+}
+
+static void listsEqual(QObject *listProp, QObject *array, const char *method)
+{
+ const QByteArray listPropertyPropertyName = QByteArray("listProperty") + method;
+ const QByteArray jsArrayPropertyName = QByteArray("jsArray") + method;
+
+ const QQmlListReference listPropertyProperty(listProp, listPropertyPropertyName.constData());
+ const QVariantList jsArrayProperty = array->property(jsArrayPropertyName.constData()).toList();
+
+ const qsizetype listPropertyCount = listPropertyProperty.count();
+ QCOMPARE(listPropertyCount, jsArrayProperty.count());
+
+ for (qsizetype i = 0; i < listPropertyCount; ++i)
+ QCOMPARE(listPropertyProperty.at(i), jsArrayProperty.at(i).value<QObject *>());
+}
+
void tst_QmlCppCodegen::initTestCase()
{
#ifdef QT_TEST_FORCE_INTERPRETER
@@ -173,40 +494,91 @@ void tst_QmlCppCodegen::initTestCase()
#endif
}
-void tst_QmlCppCodegen::simpleBinding()
+void tst_QmlCppCodegen::cleanupTestCase()
+{
+ // This code checks for basic blocks validation failures in the tests
+ QStringList expectedFailures = {
+ "codegen_test_module_basicBlocksWithBackJump_infinite_qml.cpp",
+ "codegen_test_module_verify_basicBlocksWithBackJump_infinite_qml.cpp",
+ };
+
+ QString generatedCppFolder = GENERATED_CPP_FOLDER;
+ QDirIterator dirIterator(generatedCppFolder, { "*.cpp" }, QDir::Files);
+ while (dirIterator.hasNext()) {
+ QFile file(dirIterator.next());
+ if (!file.open(QIODeviceBase::ReadOnly | QIODeviceBase::Text)) {
+ qDebug() << "Couldn't open generated file";
+ continue;
+ }
+
+ const auto content = file.readAll();
+ if (bool validationFailed = content.contains("// QV4_BASIC_BLOCK_VALIDATION_FAILED:"_L1)) {
+ if (expectedFailures.contains(dirIterator.fileInfo().fileName())) {
+ QEXPECT_FAIL("", "Expected failure", Continue);
+ }
+ const auto message = file.fileName() + ": Basic blocks validation failed.";
+ QVERIFY2(!validationFailed, message.toStdString().c_str());
+ }
+ }
+}
+
+void tst_QmlCppCodegen::accessModelMethodFromOutSide()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Test.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/AccessModelMethodsFromOutside.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+
+ QTest::ignoreMessage(QtDebugMsg, "3");
+ QTest::ignoreMessage(QtDebugMsg, "Apple");
QScopedPointer<QObject> object(component.create());
- QVERIFY2(!object.isNull(), component.errorString().toUtf8().constData());
- QCOMPARE(object->property("foo").toInt(), int(3));
- {
- CppBaseClass *base = qobject_cast<CppBaseClass *>(object.data());
- Q_ASSERT(base);
- QVERIFY(!base->cppProp.hasBinding());
- QCOMPARE(base->cppProp.value(), 7);
- QVERIFY(base->cppProp2.hasBinding());
- QCOMPARE(base->cppProp2.value(), 14);
- base->cppProp.setValue(9);
- QCOMPARE(base->cppProp.value(), 9);
- QCOMPARE(base->cppProp2.value(), 18);
- }
+ QCOMPARE(object->property("cost1").toDouble(), 3);
+ QCOMPARE(object->property("name1").toString(), u"Orange"_s);
+ QCOMPARE(object->property("cost2").toDouble(), 1.95);
+ QCOMPARE(object->property("name2").toString(), u"Banana"_s);
}
-void tst_QmlCppCodegen::cppValueTypeList()
+void tst_QmlCppCodegen::aliasLookup()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Test.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/aliasLookup.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
- QVERIFY2(!object.isNull(), component.errorString().toUtf8().constData());
- QCOMPARE(object->property("a").toInt(), 16);
- QMetaObject::invokeMethod(object.data(), "incA");
- QCOMPARE(object->property("a").toInt(), 17);
+ QVERIFY(!object.isNull());
- QCOMPARE(object->property("b").toDouble(), 0.25);
- QMetaObject::invokeMethod(object.data(), "incB");
- QCOMPARE(object->property("b").toDouble(), 13.5);
+ const QVariant t = object->property("t");
+ QCOMPARE(t.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(t.toString(), u"12"_s);
+}
+
+void tst_QmlCppCodegen::ambiguousAs()
+{
+ QQmlEngine e;
+ const QUrl url(u"qrc:/qt/qml/TestTypes/ambiguousAs.qml"_s);
+ QQmlComponent c(&e, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("other").value<QObject *>(), o.data());
+ o->setProperty("useSelf", QVariant::fromValue(false));
+ QCOMPARE(o->property("other").value<QObject *>(), nullptr);
+}
+
+void tst_QmlCppCodegen::ambiguousSignals()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ambiguousSignals.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), u"tomorrow"_s);
+ Person *p = qobject_cast<Person *>(o.data());
+ QVERIFY(p);
+ emit p->ambiguous(12);
+ QCOMPARE(o->objectName(), u"12foo"_s);
+ emit p->ambiguous();
+ QCOMPARE(o->objectName(), u"9foo"_s);
}
void tst_QmlCppCodegen::anchorsFill()
@@ -231,342 +603,629 @@ void tst_QmlCppCodegen::anchorsFill()
QCOMPARE(child->property("width").toInt(), 47);
}
-void tst_QmlCppCodegen::signalHandler()
+void tst_QmlCppCodegen::argumentConversion()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/signal.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/argumentConversion.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ auto checkNaN = [&](const char *propName) {
+ const QVariant prop = o->property(propName);
+ QCOMPARE(prop.metaType(), QMetaType::fromType<double>());
+ QVERIFY(qIsNaN(prop.toDouble()));
+ };
+
+ checkNaN("a");
+ checkNaN("b");
+ checkNaN("e");
+
+ QCOMPARE(o->property("c").toDouble(), 3.0);
+ QCOMPARE(o->property("d").toDouble(), -1.0);
+ QCOMPARE(o->property("f").toDouble(), 10.0);
+}
+
+void tst_QmlCppCodegen::array()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/array.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QCOMPARE(object->objectName(), QString());
- QCOMPARE(object->property("ff").toInt(), 4);
+ const QJSValue value1 = object->property("values1").value<QJSValue>();
+ QVERIFY(value1.isArray());
+ QCOMPARE(value1.property(u"length"_s).toInt(), 3);
+ QCOMPARE(value1.property(0).toInt(), 1);
+ QCOMPARE(value1.property(1).toInt(), 2);
+ QCOMPARE(value1.property(2).toInt(), 3);
- object->setObjectName(u"foo"_s);
- QCOMPARE(object->property("ff").toInt(), 12);
+ const QJSValue value2 = object->property("values2").value<QJSValue>();
+ QVERIFY(value2.isArray());
+ QCOMPARE(value2.property(u"length"_s).toInt(), 0);
}
-void tst_QmlCppCodegen::idAccess()
+void tst_QmlCppCodegen::arrayCtor()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/idAccess.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/arrayCtor.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QVERIFY(object->property("y").toInt() != 48);
- QCOMPARE(object->property("y").toInt(), 12);
- object->setProperty("z", 13);
- QCOMPARE(object->property("y").toInt(), 13);
- object->setProperty("x", QVariant::fromValue(333));
- QCOMPARE(object->property("y").toInt(), 48);
+ QCOMPARE(object->property("defaultCtor"), QVariant::fromValue(QList<int>()));
+ QCOMPARE(object->property("oneArgCtor"), QVariant::fromValue(QList<int>(5)));
+ QCOMPARE(object->property("multiArgCtor"), QVariant::fromValue(QList<int>({2, 3, 3, 4})));
+ QCOMPARE(object->property("arrayTrue"), QVariant::fromValue(QList<bool>({true})));
+ QCOMPARE(object->property("arrayFalse"), QVariant::fromValue(QList<bool>({false})));
+ QCOMPARE(object->property("arrayNegative"), QVariant::fromValue(QList<double>()));
+}
- // The binding was broken by setting the property
- object->setProperty("z", 14);
- QCOMPARE(object->property("y").toInt(), 48);
+void tst_QmlCppCodegen::asCast()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/asCast.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
- QObject *ttt = qmlContext(object.data())->objectForName(u"ttt"_s);
- QFont f = qvariant_cast<QFont>(ttt->property("font"));
- QCOMPARE(f.pointSize(), 22);
+ QQmlContext *context = qmlContext(root.data());
+ const QObject *object = context->objectForName(u"object"_s);
+ const QObject *item = context->objectForName(u"item"_s);
+ const QObject *rectangle = context->objectForName(u"rectangle"_s);
+ const QObject *dummy = context->objectForName(u"dummy"_s);
+
+ QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsObject")), object);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsItem")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsRectangle")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsDummy")), nullptr);
+
+ QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsObject")), item);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsItem")), item);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsRectangle")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsDummy")), nullptr);
+
+ QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsObject")), rectangle);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsItem")), rectangle);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsRectangle")), rectangle);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsDummy")), nullptr);
+
+ QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsObject")), dummy);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsItem")), dummy);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsRectangle")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsDummy")), dummy);
+
+ QCOMPARE(qvariant_cast<QObject *>(root->property("nullAsObject")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("nullAsItem")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("nullAsRectangle")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("nullAsDummy")), nullptr);
+
+ QCOMPARE(qvariant_cast<QObject *>(root->property("undefinedAsObject")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("undefinedAsItem")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("undefinedAsRectangle")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("undefinedAsDummy")), nullptr);
}
-static QByteArray arg1()
+void tst_QmlCppCodegen::attachedBaseEnum()
{
- const QStringList args = QCoreApplication::instance()->arguments();
- return args.size() > 1 ? args[1].toUtf8() : QByteArray("undefined");
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/attachedBaseEnum.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+
+ QObject *drag = qvariant_cast<QObject *>(object->property("drag"));
+ QVERIFY(drag);
+
+ // Drag.YAxis is 2, but we cannot #include it here.
+ bool ok = false;
+ QCOMPARE(drag->property("axis").toInt(&ok), 2);
+ QVERIFY(ok);
}
-void tst_QmlCppCodegen::globals()
+void tst_QmlCppCodegen::attachedSelf()
{
QQmlEngine engine;
- int exitCode = -1;
- QObject::connect(&engine, &QQmlEngine::exit, [&](int code) { exitCode = code; });
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/globals.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/SelectionRectangle.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- const QByteArray message = QByteArray("Start 2 ") + arg1();
- QTest::ignoreMessage(QtDebugMsg, message.constData());
+ QObject *handle = qvariant_cast<QObject *>(o->property("aa"));
+ QVERIFY(handle);
+ QVERIFY(qvariant_cast<QObject *>(handle->property("rect")) != nullptr);
+}
+void tst_QmlCppCodegen::attachedType()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/text.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QTRY_COMPARE(exitCode, 0);
+ QCOMPARE(object->property("dayz").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
+ QCOMPARE(object->property("oParty").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
- QObject *application = qvariant_cast<QObject *>(object->property("application"));
- QVERIFY(application);
- QCOMPARE(QString::fromUtf8(application->metaObject()->className()),
- u"QQuickApplication"_s);
+ QObject *party = qvariant_cast<QObject *>(object->property("party"));
+ QVERIFY(party);
+ QCOMPARE(party->property("eee").toInt(), 21);
+ QCOMPARE(party->property("fff").toInt(), 33);
+ QCOMPARE(object->property("ggg").toInt(), 37);
+}
- QTest::ignoreMessage(QtDebugMsg, "End");
- QMetaObject::invokeMethod(application, "aboutToQuit");
+void tst_QmlCppCodegen::badSequence()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/badSequence.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
- const QVariant somewhere = object->property("somewhere");
- QCOMPARE(somewhere.userType(), QMetaType::QUrl);
- QCOMPARE(qvariant_cast<QUrl>(somewhere).toString(), u"qrc:/somewhere/else.qml"_s);
+ Person *self = qobject_cast<Person *>(o.data());
+ QVERIFY(self);
+ QVERIFY(self->barzles().isEmpty());
+ QVERIFY(self->cousins().isEmpty());
- const QVariant somewhereString = object->property("somewhereString");
- QCOMPARE(somewhereString.userType(), QMetaType::QString);
- QCOMPARE(somewhereString.toString(), u"qrc:/somewhere/else.qml"_s);
+ Person *other = o->property("other").value<Person *>();
+ QVERIFY(other);
- const QVariant plain = object->property("plain");
- QCOMPARE(plain.userType(), QMetaType::QUrl);
- QCOMPARE(qvariant_cast<QUrl>(plain).toString(), u"/not/here.qml"_s);
+ QVERIFY(other->barzles().isEmpty());
+ QVERIFY(other->cousins().isEmpty());
+
+ Barzle f1;
+ Barzle f2;
+ const QList<Barzle *> barzles { &f1, &f2 };
+ const QList<Person *> cousins { self, other };
+
+ other->setBarzles(barzles);
+ QCOMPARE(self->barzles(), barzles);
+ QCOMPARE(self->property("l").toInt(), 2);
+
+ other->setCousins(cousins);
+ QCOMPARE(self->cousins(), cousins);
+ QCOMPARE(self->property("m").toInt(), 2);
+
+ QQmlListProperty<Person> others
+ = self->property("others").value<QQmlListProperty<Person>>();
+ QCOMPARE(others.count(&others), 2);
+ QCOMPARE(others.at(&others, 0), cousins[0]);
+ QCOMPARE(others.at(&others, 1), cousins[1]);
+
+ QQmlListProperty<Person> momsCousins
+ = self->property("momsCousins").value<QQmlListProperty<Person>>();
+ QCOMPARE(momsCousins.count(&momsCousins), 2);
+ QCOMPARE(momsCousins.at(&momsCousins, 0), cousins[0]);
+ QCOMPARE(momsCousins.at(&momsCousins, 1), cousins[1]);
+
+ QQmlListProperty<Person> dadsCousins
+ = self->property("dadsCousins").value<QQmlListProperty<Person>>();
+ QCOMPARE(dadsCousins.count(&dadsCousins), 1);
+ QCOMPARE(dadsCousins.at(&dadsCousins, 0), other);
}
-void tst_QmlCppCodegen::multiLookup()
+static bool expectingMessage = false;
+static void handler(QtMsgType type, const QMessageLogContext &, const QString &message)
+{
+ QVERIFY(expectingMessage);
+ QCOMPARE(type, QtDebugMsg);
+ QCOMPARE(message, u"false");
+ expectingMessage = false;
+}
+
+void tst_QmlCppCodegen::basicBlocksWithBackJump()
{
- // Multiple lookups of singletons (Qt in this case) don't clash with one another.
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/immediateQuit.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/basicBlocksWithBackJump.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
- const QByteArray message = QByteArray("End: ") + arg1();
- QTest::ignoreMessage(QtDebugMsg, message.constData());
+ const auto oldHandler = qInstallMessageHandler(&handler);
+ const auto guard = qScopeGuard([oldHandler]() { qInstallMessageHandler(oldHandler); });
- QSignalSpy quitSpy(&engine, &QQmlEngine::quit);
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(quitSpy.size(), 1);
+ // t1 does not log anything
+ QMetaObject::invokeMethod(o.data(), "t1");
+
+ // t2 logs "false" exactly once
+ expectingMessage = true;
+ QMetaObject::invokeMethod(o.data(), "t2");
+ QVERIFY(!expectingMessage);
+
+ // t3 logs "false" exactly once
+ expectingMessage = true;
+ QMetaObject::invokeMethod(o.data(), "t3");
+ QVERIFY(!expectingMessage);
}
-void tst_QmlCppCodegen::enums()
+void tst_QmlCppCodegen::basicBlocksWithBackJump_infinite()
{
QQmlEngine engine;
- {
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Enums.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/basicBlocksWithBackJump_infinite.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+}
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/Enums.qml:4:1: "
- "QML Enums: Layout must be attached to Item elements");
- QScopedPointer<QObject> object(component.create());
+void tst_QmlCppCodegen::basicDTZ()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/basicDTZ.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
- QVERIFY(!object.isNull());
- bool ok = false;
- QCOMPARE(object->property("appState").toInt(&ok), 2);
- QVERIFY(ok);
- QCOMPARE(object->property("color").toString(), u"blue"_s);
+ QCOMPARE(o->property("title").toString(), u"none");
- QTRY_COMPARE(object->property("appState").toInt(&ok), 1);
- QVERIFY(ok);
- QCOMPARE(object->property("color").toString(), u"green"_s);
+ QMetaObject::invokeMethod(o.data(), "t1");
+ QMetaObject::invokeMethod(o.data(), "t2");
+ QMetaObject::invokeMethod(o.data(), "t3");
+
+ QCOMPARE(o->property("title").toString(), u"Baz 41");
+}
+
+void tst_QmlCppCodegen::bindToValueType()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/bindToValueType.qml"_s));
+ checkColorProperties(&component);
+}
+
+void tst_QmlCppCodegen::bindingExpression()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/BindingExpression.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+
+ QObject *child = qmlContext(object.data())->objectForName(u"child"_s);
+
+ double width = 200;
+ double y = 10;
+ for (int i = 0; i < 10; ++i) {
+ QCOMPARE(object->property("width").toDouble(), width);
+ QCOMPARE(object->property("height").toDouble(), width);
+ QCOMPARE(object->property("y").toDouble(), y);
- const auto func = qmlAttachedPropertiesFunction(
- object.data(), QMetaType::fromName("QQuickLayout*").metaObject());
+ const double childY = y + (width - 100) / 2;
+ QCOMPARE(child->property("y").toDouble(), childY);
+ QCOMPARE(object->property("mass"), childY > 100 ? u"heavy"_s : u"light"_s);
+ QCOMPARE(object->property("test_division").toDouble(), width / 1000 + 50);
+ QCOMPARE(object->property("test_ternary").toDouble(), 2.2);
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/enumsInOtherObject.qml:4:25: "
- "QML Enums: Layout must be attached to Item elements");
- QObject *attached = qmlAttachedPropertiesObject(object.data(), func);
+ const int test_switch = object->property("test_switch").toInt();
+ switch (int(width) % 3) {
+ case 0:
+ QCOMPARE(test_switch, 130);
+ break;
+ case 1:
+ QCOMPARE(test_switch, 380);
+ break;
+ case 2:
+ QCOMPARE(test_switch, 630);
+ break;
+ }
- const QVariant prop = attached->property("alignment");
- QVERIFY(prop.isValid());
- QCOMPARE(qvariant_cast<Qt::Alignment>(prop), Qt::AlignCenter);
+ width = 200 * i;
+ y = 10 + i;
+ object->setProperty("width", width);
+ object->setProperty("y", y);
}
- {
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumsInOtherObject.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("color").toString(), u"blue"_s);
- QTRY_COMPARE(object->property("color").toString(), u"green"_s);
+}
+
+void tst_QmlCppCodegen::blockComments()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/blockComments.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("implicitHeight").toDouble(), 8.0);
+}
+
+void tst_QmlCppCodegen::boolCoercions()
+{
+ QQmlEngine e;
+ const QUrl url(u"qrc:/qt/qml/TestTypes/boolCoercions.qml"_s);
+ QQmlComponent c(&e, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":41:5: Unable to assign [undefined] to bool"_L1));
+ QScopedPointer<QObject> o(c.create());
+
+ for (char p = '1'; p <= '8'; ++p) {
+ const QVariant t = o->property(qPrintable(QLatin1String("t%1").arg(p)));
+ QCOMPARE(t.metaType(), QMetaType::fromType<bool>());
+ QVERIFY(t.toBool());
+ }
+
+ for (char p = '1'; p <= '5'; ++p) {
+ const QVariant f = o->property(qPrintable(QLatin1String("f%1").arg(p)));
+ QCOMPARE(f.metaType(), QMetaType::fromType<bool>());
+ QVERIFY(!f.toBool());
}
}
-void tst_QmlCppCodegen::funcWithParams()
+void tst_QmlCppCodegen::boolPointerMerge()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/boolPointerMerge.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QObject *item = o->property("item").value<QObject *>();
+ QVERIFY(item);
+ QCOMPARE(item->property("ppp").toInt(), -99);
+}
+
+void tst_QmlCppCodegen::boundComponents()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/funcWithParams.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("bar").toInt(), 30);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/boundComponents.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QObject *c1o = o->property("o").value<QObject *>();
+ QVERIFY(c1o != nullptr);
+ QCOMPARE(c1o->objectName(), u"bar"_s);
+
+ QObject *c2o = c1o->property("o").value<QObject *>();
+ QVERIFY(c2o != nullptr);
+ QCOMPARE(c2o->objectName(), u"bar12"_s);
}
-void tst_QmlCppCodegen::intOverflow()
+void tst_QmlCppCodegen::callContextPropertyLookupResult()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/intOverflow.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("a").toDouble(), 1.09951162778e+12);
- QCOMPARE(object->property("b").toInt(), 5);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/callContextPropertyLookupResult.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+
+ QVERIFY(qvariant_cast<QQmlComponent *>(o->property("c")) != nullptr);
}
-void tst_QmlCppCodegen::stringLength()
+void tst_QmlCppCodegen::callWithSpread()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/stringLength.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("stringLength").toInt(), 8);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/callWithSpread.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtCriticalMsg, "That is great!");
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
}
-void tst_QmlCppCodegen::scopeVsObject()
+void tst_QmlCppCodegen::colorAsVariant()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/scopeVsObject.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/colorAsVariant.qml"_s));
+ checkColorProperties(&component);
+}
+
+void tst_QmlCppCodegen::colorString()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/colorString.qml"_s));
+
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
+
+ QCOMPARE(qvariant_cast<QColor>(rootObject->property("c")), QColor::fromRgb(0xdd, 0xdd, 0xdd));
+ QCOMPARE(qvariant_cast<QColor>(rootObject->property("d")), QColor::fromRgb(0xaa, 0xaa, 0xaa));
+ QCOMPARE(qvariant_cast<QColor>(rootObject->property("e")), QColor::fromRgb(0x11, 0x22, 0x33));
+}
+
+void tst_QmlCppCodegen::compareOriginals()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/compareOriginals.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QCOMPARE(object->property("objectName").toString(), u"foobar"_s);
+
+ QCOMPARE(object->property("compareOriginals").toInt(), 5);
+ QVERIFY(object->property("optionalThis").toBool());
}
-void tst_QmlCppCodegen::compositeTypeMethod()
+void tst_QmlCppCodegen::comparisonTypes()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/compositeTypeMethod.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/comparisonTypes.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QSignalSpy spy(object.data(), SIGNAL(foo()));
- QTRY_VERIFY(spy.size() > 0);
+
+ QCOMPARE(object->property("found").toInt(), 1);
+ QCOMPARE(object->property("foundStrict").toInt(), 0);
+
+ QCOMPARE(object->property("foundNot").toInt(), 2);
+ QCOMPARE(object->property("foundNotStrict").toInt(), 10);
}
-void tst_QmlCppCodegen::excessiveParameters()
+void tst_QmlCppCodegen::componentReturnType()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/excessiveParameters.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/componentReturnType.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QSignalSpy spy(object.data(), SIGNAL(foo()));
- QTRY_VERIFY(spy.size() > 0);
+
+ QCOMPARE(object->property("count").toInt(), 10);
+ QCOMPARE(QQmlListReference(object.data(), "children").count(), 11);
}
-void tst_QmlCppCodegen::jsImport()
+void tst_QmlCppCodegen::compositeSingleton()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/jsimport.qml"_s));
+ engine.addImportPath(u":/qt/qml/TestTypes/imports/"_s);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/compositesingleton.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("value").toInt(), 42);
+ QScopedPointer<QObject> o(component.create());
+ QCOMPARE(o->property("x").toDouble(), 4.5);
+ QCOMPARE(o->property("y").toDouble(), 10.0);
+ QCOMPARE(o->property("smooth").toBool(), true);
}
-void tst_QmlCppCodegen::jsmoduleImport()
+void tst_QmlCppCodegen::compositeTypeMethod()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/jsmoduleimport.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/compositeTypeMethod.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QCOMPARE(object->property("ok").toBool(), true);
- QVariant okFunc = object->property("okFunc");
- QCOMPARE(okFunc.metaType(), QMetaType::fromType<QJSValue>());
- QJSValue val = engine.toScriptValue(okFunc);
- QJSValue result = val.call();
- QVERIFY(result.isBool());
- QVERIFY(result.toBool());
+ QSignalSpy spy(object.data(), SIGNAL(foo()));
+ QTRY_VERIFY(spy.size() > 0);
}
-void tst_QmlCppCodegen::methods()
+void tst_QmlCppCodegen::consoleObject()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/methods.qml"_s));
- QVERIFY(component.isReady());
-
- QTest::ignoreMessage(QtDebugMsg, "The Bar");
- QTest::ignoreMessage(QtWarningMsg, QRegularExpression(u"TypeError: .* is not a function"_s));
- QScopedPointer<QObject> obj(component.create());
- QVERIFY(obj);
- BirthdayParty *party(qobject_cast<BirthdayParty *>(obj.data()));
-
- QVERIFY(party && party->host());
- QCOMPARE(party->guestCount(), 5);
+ static const QString urlString = u"qrc:/qt/qml/TestTypes/consoleObject.qml"_s;
+ QQmlComponent c(&engine, QUrl(urlString));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- bool foundGreen = false;
- bool foundFoo = false;
- for (int ii = 0; ii < party->guestCount(); ++ii) {
- if (party->guest(ii)->name() == u"William Green"_s)
- foundGreen = true;
- if (party->guest(ii)->name() == u"The Foo"_s)
- foundFoo = true;
- }
+ QTest::ignoreMessage(QtDebugMsg, "b 4.55");
+ QTest::ignoreMessage(QtDebugMsg, "b 4.55");
+ QTest::ignoreMessage(QtInfoMsg, "b 4.55");
+ QTest::ignoreMessage(QtWarningMsg, "b 4.55");
+ QTest::ignoreMessage(QtCriticalMsg, "b 4.55");
- QVERIFY(foundGreen);
- QVERIFY(foundFoo);
+ // Unfortunately we cannot check the logging category with QTest::ignoreMessage
+ QTest::ignoreMessage(QtDebugMsg, "b 4.55");
+ QTest::ignoreMessage(QtDebugMsg, "b 4.55");
+ QTest::ignoreMessage(QtInfoMsg, "b 4.55");
+ QTest::ignoreMessage(QtWarningMsg, "b 4.55");
+ QTest::ignoreMessage(QtCriticalMsg, "b 4.55");
- QCOMPARE(obj->property("n1").toString(), u"onGurk"_s);
- QCOMPARE(obj->property("n2").toString(), u"onSemmeln"_s);
- QCOMPARE(obj->property("n3"), QVariant());
+ const QRegularExpression re(u"QQmlComponentAttached\\(0x[0-9a-f]+\\) b 4\\.55"_s);
+ QTest::ignoreMessage(QtDebugMsg, re);
+ QTest::ignoreMessage(QtDebugMsg, re);
+ QTest::ignoreMessage(QtInfoMsg, re);
+ QTest::ignoreMessage(QtWarningMsg, re);
+ QTest::ignoreMessage(QtCriticalMsg, re);
- {
- QVariant ret;
- obj->metaObject()->invokeMethod(obj.data(), "retrieveVar", Q_RETURN_ARG(QVariant, ret));
- QCOMPARE(ret.typeId(), QMetaType::QString);
- QCOMPARE(ret.toString(), u"Jack Smith"_s);
- }
+ QTest::ignoreMessage(QtDebugMsg, "a undefined b false null 7");
+ QTest::ignoreMessage(QtDebugMsg, "");
+ QTest::ignoreMessage(QtDebugMsg, "4");
+ QTest::ignoreMessage(QtDebugMsg, "");
- {
- QString ret;
- obj->metaObject()->invokeMethod(obj.data(), "retrieveString", Q_RETURN_ARG(QString, ret));
- QCOMPARE(ret, u"Jack Smith"_s);
- }
+ const QRegularExpression re2(u"QQmlComponentAttached\\(0x[0-9a-f]+\\)"_s);
+ QTest::ignoreMessage(QtDebugMsg, re2);
- QCOMPARE(party->host()->shoeSize(), 12);
- obj->metaObject()->invokeMethod(obj.data(), "storeElement");
- QCOMPARE(party->host()->shoeSize(), 13);
- QJSManagedValue v = engine.toManagedValue(obj->property("dresses"));
- QVERIFY(v.isArray());
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- QJSManagedValue inner(v.property(2), &engine);
- QVERIFY(inner.isArray());
- QCOMPARE(inner.property(0).toInt(), 1);
- QCOMPARE(inner.property(1).toInt(), 2);
- QCOMPARE(inner.property(2).toInt(), 3);
+ auto oldHandler = qInstallMessageHandler(
+ [](QtMsgType, const QMessageLogContext &ctxt, const QString &) {
+ QCOMPARE(ctxt.file, urlString.toUtf8());
+ QCOMPARE(ctxt.function, QByteArray("expression for onCompleted"));
+ QVERIFY(ctxt.line > 0);
+ });
+ const auto guard = qScopeGuard([oldHandler]() { qInstallMessageHandler(oldHandler); });
- QCOMPARE(obj->property("enumValue").toInt(), 2);
+ QScopedPointer<QObject> p(c.create());
+ QVERIFY(!p.isNull());
}
-void tst_QmlCppCodegen::math()
+void tst_QmlCppCodegen::consoleTrace()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/math.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/consoleTrace.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
+
+#if !defined(QT_NO_DEBUG) || defined(QT_TEST_FORCE_INTERPRETER)
+ // All line numbers in debug mode or when interpreting
+
+ QTest::ignoreMessage(QtDebugMsg, R"(c (qrc:/qt/qml/TestTypes/consoleTrace.qml:6)
+b (qrc:/qt/qml/TestTypes/consoleTrace.qml:5)
+a (qrc:/qt/qml/TestTypes/consoleTrace.qml:4)
+expression for onCompleted (qrc:/qt/qml/TestTypes/consoleTrace.qml:7))");
+#else
+ // Only top-most line number otherwise
+
+ QTest::ignoreMessage(QtDebugMsg, R"(c (qrc:/qt/qml/TestTypes/consoleTrace.qml:6)
+b (qrc:/qt/qml/TestTypes/consoleTrace.qml)
+a (qrc:/qt/qml/TestTypes/consoleTrace.qml)
+expression for onCompleted (qrc:/qt/qml/TestTypes/consoleTrace.qml))");
+#endif
+
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QCOMPARE(object->property("a").toInt(), 9);
- QCOMPARE(object->property("b").toDouble(), 50.0 / 22.0);
}
-void tst_QmlCppCodegen::unknownParameter()
+void tst_QmlCppCodegen::construct()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unknownParameter.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/construct.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QCOMPARE(object->property("cppProp").toInt(), 18);
+
+ const QJSManagedValue v = engine.toManagedValue(object->property("foo"));
+ QVERIFY(v.isError());
+ QCOMPARE(v.toString(), u"Error: bar"_s);
+
+ QCOMPARE(object->property("aaa").toInt(), 12);
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/construct.qml:9: Error: ouch");
+ object->metaObject()->invokeMethod(object.data(), "ouch");
+ QCOMPARE(object->property("aaa").toInt(), 13);
}
-void tst_QmlCppCodegen::array()
+void tst_QmlCppCodegen::contextParam()
{
+ // The compiler cannot resolve context parameters.
+ // Make sure the binding is interpreted.
+
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/array.qml"_s));
+
+ QVariantMap m;
+ m.insert(u"foo"_s, 10);
+ engine.rootContext()->setContextProperty(u"contextParam"_s, m);
+
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/contextParam.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- const QJSValue value1 = object->property("values1").value<QJSValue>();
- QVERIFY(value1.isArray());
- QCOMPARE(value1.property(u"length"_s).toInt(), 3);
- QCOMPARE(value1.property(0).toInt(), 1);
- QCOMPARE(value1.property(1).toInt(), 2);
- QCOMPARE(value1.property(2).toInt(), 3);
- const QJSValue value2 = object->property("values2").value<QJSValue>();
- QVERIFY(value2.isArray());
- QCOMPARE(value2.property(u"length"_s).toInt(), 0);
+ QCOMPARE(object->property("foo").toInt(), 10);
}
-void tst_QmlCppCodegen::equalsUndefined()
+void tst_QmlCppCodegen::conversionDecrement()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalsUndefined.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/conversionDecrement.qml"_s));
- QCOMPARE(object->property("a").toInt(), 50);
- QCOMPARE(object->property("b").toInt(), 5000);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("currentPageIndex").toInt(), 0);
+ o->setProperty("pages", 5);
+ QCOMPARE(o->property("currentPageIndex").toInt(), 3);
+ o->setProperty("pages", 4);
+ QCOMPARE(o->property("currentPageIndex").toInt(), 0);
+ o->setProperty("pages", 6);
+ QCOMPARE(o->property("currentPageIndex").toInt(), 4);
+ o->setProperty("pages", 60);
+ QCOMPARE(o->property("currentPageIndex").toInt(), 3);
+}
+
+void tst_QmlCppCodegen::conversionInDeadCode()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/conversionInDeadCode.qml"_s));
+
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("a").toInt(), -4);
+ QCOMPARE(o->property("b").toInt(), 12);
+ QCOMPARE(o->property("c").toInt(), 10);
+ QCOMPARE(o->property("d").toInt(), 10);
+ QCOMPARE(o->property("e").toInt(), 10);
+ QCOMPARE(o->property("f").toInt(), 20);
+ QCOMPARE(o->property("g").toInt(), 33);
}
void tst_QmlCppCodegen::conversions()
@@ -699,157 +1358,260 @@ void tst_QmlCppCodegen::conversions()
QVERIFY(!undef.isValid());
}
-void tst_QmlCppCodegen::interestingFiles_data()
+void tst_QmlCppCodegen::convertPrimitiveToVar()
{
- QTest::addColumn<QString>("file");
- QTest::addColumn<bool>("isValid");
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/convertPrimitiveToVar.qml"_s));
- QTest::addRow("conversions2") << u"conversions2.qml"_s << true;
- QTest::addRow("TestCase") << u"TestCase.qml"_s << true;
- QTest::addRow("layouts") << u"layouts.qml"_s << true;
- QTest::addRow("interactive") << u"interactive.qml"_s << true;
- QTest::addRow("Panel") << u"Panel.qml"_s << true;
- QTest::addRow("ProgressBar") << u"ProgressBar/ProgressBar.ui.qml"_s << true;
- QTest::addRow("Root") << u"ProgressBar/Root.qml"_s << true;
- QTest::addRow("noscope") << u"noscope.qml"_s << true;
- QTest::addRow("dynamicscene") << u"dynamicscene.qml"_s << true;
- QTest::addRow("curlygrouped") << u"curlygrouped.qml"_s << true;
- QTest::addRow("cycleHead") << u"cycleHead.qml"_s << false;
- QTest::addRow("deadStoreLoop") << u"deadStoreLoop.qml"_s << true;
- QTest::addRow("moveRegVoid") << u"moveRegVoid.qml"_s << true;
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("offsetValue").toInt(), 41);
}
-void tst_QmlCppCodegen::interestingFiles()
+void tst_QmlCppCodegen::convertQJSPrimitiveValueToIntegral()
{
- QFETCH(QString, file);
- QFETCH(bool, isValid);
-
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/%1"_s.arg(file)));
- if (isValid) {
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- } else {
- QVERIFY(component.isError());
- }
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/convertQJSPrimitiveValueToIntegral.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
}
-void tst_QmlCppCodegen::extendedTypes()
+void tst_QmlCppCodegen::convertToOriginalReadAcumulatorForUnaryOperators()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/extendedTypes.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
-
- QTest::ignoreMessage(QtDebugMsg, "6 QSizeF(10, 20) 30");
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/convertToOriginalReadAcumulatorForUnaryOperators.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
- QCOMPARE(object->property("a").toInt(), 6);
- QCOMPARE(qvariant_cast<QSizeF>(object->property("b")), QSizeF(10, 20));
- QCOMPARE(object->property("c").toInt(), 30);
- QCOMPARE(object->property("d").toString(), u"QSizeF(10, 20)"_s);
+void tst_QmlCppCodegen::cppMethodListReturnType()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/CppMethodListReturnType.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- QCOMPARE(object->property("e").toInt(), 2);
+ QCOMPARE(o->property("list").toList()[2].toInt(), 2);
}
-void tst_QmlCppCodegen::construct()
+void tst_QmlCppCodegen::cppValueTypeList()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/construct.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Test.qml"_s));
QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
-
- const QJSManagedValue v = engine.toManagedValue(object->property("foo"));
- QVERIFY(v.isError());
- QCOMPARE(v.toString(), u"Error: bar"_s);
+ QVERIFY2(!object.isNull(), component.errorString().toUtf8().constData());
+ QCOMPARE(object->property("a").toInt(), 16);
+ QMetaObject::invokeMethod(object.data(), "incA");
+ QCOMPARE(object->property("a").toInt(), 17);
- QCOMPARE(object->property("aaa").toInt(), 12);
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/construct.qml:9: Error: ouch");
- object->metaObject()->invokeMethod(object.data(), "ouch");
- QCOMPARE(object->property("aaa").toInt(), 13);
+ QCOMPARE(object->property("b").toDouble(), 0.25);
+ QMetaObject::invokeMethod(object.data(), "incB");
+ QCOMPARE(object->property("b").toDouble(), 13.5);
}
-void tst_QmlCppCodegen::contextParam()
+void tst_QmlCppCodegen::dateConstruction()
{
- // The compiler cannot resolve context parameters.
- // Make sure the binding is interpreted.
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/dateConstruction.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QDateTime now = QDateTime::currentDateTime();
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QVERIFY(o->property("now").value<QDateTime>().toMSecsSinceEpoch() >= now.toMSecsSinceEpoch());
+ QCOMPARE(o->property("now2"), o->property("now"));
+ QCOMPARE(o->property("fromString").value<QDateTime>(),
+ QDateTime(QDate(1995, 12, 17), QTime(3, 24), QTimeZone::LocalTime));
+ QCOMPARE(o->property("fromNumber").value<QDateTime>().toMSecsSinceEpoch(), 777);
+ QCOMPARE(o->property("fromPrimitive").value<QDateTime>().toMSecsSinceEpoch(), 57);
+ o->setObjectName("foo"_L1);
+ QCOMPARE(o->property("fromPrimitive").value<QDateTime>(),
+ QDateTime(QDate(1997, 2, 13), QTime(13, 4, 12), QTimeZone::LocalTime));
+
+ QCOMPARE(o->property("from2").value<QDateTime>(),
+ QDateTime(QDate(1996, 2, 1), QTime(), QTimeZone::LocalTime));
+ QCOMPARE(o->property("from3").value<QDateTime>(),
+ QDateTime(QDate(1996, 3, 3), QTime(), QTimeZone::LocalTime));
+ QCOMPARE(o->property("from4").value<QDateTime>(),
+ QDateTime(QDate(1996, 4, 4), QTime(5, 0), QTimeZone::LocalTime));
+ QCOMPARE(o->property("from5").value<QDateTime>(),
+ QDateTime(QDate(1996, 5, 5), QTime(6, 7), QTimeZone::LocalTime));
+ QCOMPARE(o->property("from6").value<QDateTime>(),
+ QDateTime(QDate(1996, 6, 6), QTime(7, 8, 9), QTimeZone::LocalTime));
+ QCOMPARE(o->property("from7").value<QDateTime>(),
+ QDateTime(QDate(1996, 7, 7), QTime(8, 9, 10, 11), QTimeZone::LocalTime));
+ QCOMPARE(o->property("from8").value<QDateTime>(),
+ QDateTime(QDate(1996, 8, 8), QTime(9, 10, 11, 12), QTimeZone::LocalTime));
+
+ QCOMPARE(o->property("withUnderflow").value<QDateTime>(),
+ QDateTime(QDate(-6, 7, 24), QTime(16, 51, 50, 990), QTimeZone::LocalTime));
+ QCOMPARE(o->property("invalid").value<QDateTime>(), QDateTime());
+}
+void tst_QmlCppCodegen::dateConversions()
+{
QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/dateConversions.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
- QVariantMap m;
- m.insert(u"foo"_s, 10);
- engine.rootContext()->setContextProperty(u"contextParam"_s, m);
+ Druggeljug *ref = engine.singletonInstance<Druggeljug *>("TestTypes", "Druggeljug");
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/contextParam.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
+ const QDateTime refDate = engine.coerceValue<QDate, QDateTime>(ref->myDate());
+ const QDateTime refTime = engine.coerceValue<QTime, QDateTime>(ref->myTime());
+
+ QCOMPARE(o->property("date").value<QDateTime>(), refDate);
+ QCOMPARE(o->property("time").value<QDateTime>(), refTime);
+
+ QCOMPARE(o->property("dateString").toString(),
+ (engine.coerceValue<QDateTime, QString>(refDate)));
+ QCOMPARE(o->property("dateNumber").toDouble(),
+ (engine.coerceValue<QDateTime, double>(refDate)));
+ QCOMPARE(o->property("timeString").toString(),
+ (engine.coerceValue<QDateTime, QString>(refTime)));
+ QCOMPARE(o->property("timeNumber").toDouble(),
+ (engine.coerceValue<QDateTime, double>(refTime)));
+
+ QMetaObject::invokeMethod(o.data(), "shuffle");
+
+ QCOMPARE(ref->myDate(), (engine.coerceValue<QDateTime, QDate>(refDate)));
+ QCOMPARE(ref->myTime(), (engine.coerceValue<QDateTime, QTime>(refTime)));
+
+ const QDate date = ref->myDate();
+ const QTime time = ref->myTime();
+
+ QCOMPARE(o->property("dateString").toString(), (engine.coerceValue<QDate, QString>(date)));
+ QCOMPARE(o->property("dateNumber").toDouble(), (engine.coerceValue<QDate, double>(date)));
+ QCOMPARE(o->property("timeString").toString(), (engine.coerceValue<QTime, QString>(time)));
+ QCOMPARE(o->property("timeNumber").toDouble(), (engine.coerceValue<QTime, double>(time)));
+
+ QMetaObject::invokeMethod(o.data(), "fool");
+
+ QCOMPARE(ref->myDate(), (engine.coerceValue<QTime, QDate>(time)));
+ QCOMPARE(ref->myTime(), (engine.coerceValue<QDate, QTime>(date)));
+
+ QMetaObject::invokeMethod(o.data(), "invalidate");
+ QMetaObject::invokeMethod(o.data(), "shuffle");
+
+ QCOMPARE(o->property("dateString").toString(), "Invalid Date"_L1);
+ QVERIFY(qIsNaN(o->property("dateNumber").toDouble()));
+ QCOMPARE(o->property("timeString").toString(), "Invalid Date"_L1);
+ QVERIFY(qIsNaN(o->property("timeNumber").toDouble()));
- QCOMPARE(object->property("foo").toInt(), 10);
}
-void tst_QmlCppCodegen::attachedType()
+void tst_QmlCppCodegen::deadShoeSize()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/text.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("dayz").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
- QCOMPARE(object->property("oParty").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
-
- QObject *party = qvariant_cast<QObject *>(object->property("party"));
- QVERIFY(party);
- QCOMPARE(party->property("eee").toInt(), 21);
- QCOMPARE(party->property("fff").toInt(), 33);
- QCOMPARE(object->property("ggg").toInt(), 37);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/deadShoeSize.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/deadShoeSize.qml:5: Error: ouch");
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("shoeSize").toInt(), 0);
}
-void tst_QmlCppCodegen::componentReturnType()
+void tst_QmlCppCodegen::dialogButtonBox()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/componentReturnType.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
+ const QUrl copy(u"qrc:/qt/qml/TestTypes/dialogButtonBox.qml"_s);
+ QQmlComponent c(&engine, copy);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QObject *footer = o->property("footer").value<QObject *>();
+ QVERIFY(footer);
- QCOMPARE(object->property("count").toInt(), 10);
- QCOMPARE(QQmlListReference(object.data(), "children").count(), 11);
+ QCOMPARE(footer->property("standardButtons").value<QPlatformDialogHelper::StandardButton>(),
+ QPlatformDialogHelper::Ok | QPlatformDialogHelper::Cancel);
}
-void tst_QmlCppCodegen::onAssignment()
+void tst_QmlCppCodegen::enumConversion()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/pressAndHoldButton.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QCOMPARE(object->property("pressed").toBool(), false);
- QCOMPARE(object->property("scale").toDouble(), 1.0);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumConversion.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- object->metaObject()->invokeMethod(object.data(), "press");
- QTRY_COMPARE(object->property("pressed").toBool(), true);
- QCOMPARE(object->property("scale").toDouble(), 0.9);
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("test").toInt(), 0x04);
+ QCOMPARE(o->property("test_1").toBool(), true);
+ QCOMPARE(o->objectName(), u"0m"_s);
+}
- object->metaObject()->invokeMethod(object.data(), "release");
- QCOMPARE(object->property("pressed").toBool(), false);
- QCOMPARE(object->property("scale").toDouble(), 1.0);
+void tst_QmlCppCodegen::enumFromBadSingleton()
+{
+ QQmlEngine e;
+ const QUrl url(u"qrc:/qt/qml/TestTypes/enumFromBadSingleton.qml"_s);
+ QQmlComponent c(&e, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+#if QT_DEPRECATED_SINCE(6,4)
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(
+ url.toString()
+ + u":5:5: TypeError: Cannot read property 'TestA' of undefined"_s));
+#else
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(
+ url.toString()
+ + u":5:5: ReferenceError: DummyObjekt is not defined"_s));
+#endif
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QVERIFY(o->objectName().isEmpty());
}
-namespace QmlCacheGeneratedCode {
-namespace _qt_qml_TestTypes_failures_qml {
-extern const QQmlPrivate::TypedFunction aotBuiltFunctions[];
+void tst_QmlCppCodegen::enumLookup()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumLookup.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QCOMPARE(o->property("ready").toBool(), true);
}
+
+void tst_QmlCppCodegen::enumMarkedAsFlag()
+{
+ QQmlEngine engine;
+
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumMarkedAsFlag.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QCOMPARE(o->property("flagValue").toInt(), 3);
}
-void tst_QmlCppCodegen::failures()
+void tst_QmlCppCodegen::enumProblems()
{
- const auto &aotFailure
- = QmlCacheGeneratedCode::_qt_qml_TestTypes_failures_qml::aotBuiltFunctions[0];
- QVERIFY(aotFailure.argumentTypes.isEmpty());
- QVERIFY(!aotFailure.functionPtr);
- QCOMPARE(aotFailure.extraData, 0);
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumProblems.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> outer(c.create());
+ QVERIFY(!outer.isNull());
+ QObject *inner = outer->property("o").value<QObject *>();
+ QVERIFY(inner);
+
+ Foo *bar = inner->property("bar").value<Foo *>();
+ QVERIFY(bar);
+ QCOMPARE(bar->type(), Foo::Component);
+
+ Foo *fighter = inner->property("fighter").value<Foo *>();
+ QVERIFY(fighter);
+ QCOMPARE(fighter->type(), Foo::Fighter);
+
+ QCOMPARE(outer->property("a").toInt(), FooFactory::B);
+ QCOMPARE(outer->property("b").toInt(), FooFactory::C);
+ QCOMPARE(outer->property("c").toInt(), FooFactory::D);
+ QCOMPARE(outer->property("d").toInt(), FooFactory::E);
}
void tst_QmlCppCodegen::enumScope()
@@ -861,283 +1623,370 @@ void tst_QmlCppCodegen::enumScope()
QCOMPARE(object->property("flow").toInt(), 1);
}
-void tst_QmlCppCodegen::unusedAttached()
+void tst_QmlCppCodegen::enums()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unusedAttached.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Enums.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
+
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/Enums.qml:4:1: "
+ "QML Enums: Layout must be attached to Item elements");
QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ bool ok = false;
+ QCOMPARE(object->property("appState").toInt(&ok), 2);
+ QVERIFY(ok);
+ QCOMPARE(object->property("color").toString(), u"blue"_s);
+
+ QTRY_COMPARE(object->property("appState").toInt(&ok), 1);
+ QVERIFY(ok);
+ QCOMPARE(object->property("color").toString(), u"green"_s);
+
const auto func = qmlAttachedPropertiesFunction(
- object.data(), QMetaType::fromName("QQuickKeyNavigationAttached*").metaObject());
+ object.data(), QMetaType::fromName("QQuickLayout*").metaObject());
+
QObject *attached = qmlAttachedPropertiesObject(object.data(), func);
- const QVariant prop = attached->property("priority");
+
+ const QVariant prop = attached->property("alignment");
QVERIFY(prop.isValid());
- QCOMPARE(QByteArray(prop.metaType().name()), "QQuickKeyNavigationAttached::Priority");
- bool ok = false;
- QCOMPARE(prop.toInt(&ok), 0);
- QVERIFY(ok);
+ QCOMPARE(qvariant_cast<Qt::Alignment>(prop), Qt::AlignCenter);
+
}
-void tst_QmlCppCodegen::attachedBaseEnum()
+void tst_QmlCppCodegen::enforceSignature()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/attachedBaseEnum.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enforceSignature.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- QObject *drag = qvariant_cast<QObject *>(object->property("drag"));
- QVERIFY(drag);
+ const QVariant a = object->property("a");
+ QCOMPARE(a.metaType(), QMetaType::fromType<QObject *>());
+ QCOMPARE(a.value<QObject *>(), nullptr);
- // Drag.YAxis is 2, but we cannot #include it here.
- bool ok = false;
- QCOMPARE(drag->property("axis").toInt(&ok), 2);
- QVERIFY(ok);
+ const QVariant b = object->property("b");
+ QCOMPARE(b.metaType(), QMetaType::fromType<QObject *>());
+ QCOMPARE(b.value<QObject *>(), nullptr);
}
-void tst_QmlCppCodegen::nullAccess()
+void tst_QmlCppCodegen::enumsInOtherObject()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nullAccess.qml"_s));
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/enumsInOtherObject.qml:4:25: "
+ "QML Enums: Layout must be attached to Item elements");
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumsInOtherObject.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
-
- QTest::ignoreMessage(QtWarningMsg,
- "qrc:/qt/qml/TestTypes/nullAccess.qml:4:5: TypeError: "
- "Cannot read property 'width' of null");
- QTest::ignoreMessage(QtWarningMsg,
- "qrc:/qt/qml/TestTypes/nullAccess.qml:5:5: TypeError: "
- "Cannot read property 'height' of null");
- QTest::ignoreMessage(QtWarningMsg,
- "qrc:/qt/qml/TestTypes/nullAccess.qml:6: TypeError: Value is null and "
- "could not be converted to an object");
QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("color").toString(), u"blue"_s);
+ QTRY_COMPARE(object->property("color").toString(), u"green"_s);
+}
- QCOMPARE(object->property("width").toDouble(), 0.0);
- QCOMPARE(object->property("height").toDouble(), 0.0);
+void tst_QmlCppCodegen::equalityQObjects()
+{
+ QQmlEngine engine;
+ QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalityQObjects.qml"_s));
+ QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
+ QScopedPointer<QObject> object(c1.create());
+ QVERIFY(!object.isNull() && !c1.isError());
+
+ QVERIFY(object->property("derivedIsNotNull").toBool());
+ QVERIFY(object->property("nullObjectIsNull").toBool());
+ QVERIFY(object->property("nonNullObjectIsNotNull").toBool());
+ QVERIFY(object->property("compareSameObjects").toBool());
+ QVERIFY(object->property("compareDifferentObjects").toBool());
+ QVERIFY(object->property("compareObjectWithNullObject").toBool());
+
+ QVERIFY(object->property("nonStrict_derivedIsNotNull").toBool());
+ QVERIFY(object->property("nonStrict_nullObjectIsNull").toBool());
+ QVERIFY(object->property("nonStrict_nonNullObjectIsNotNull").toBool());
+ QVERIFY(object->property("nonStrict_compareSameObjects").toBool());
+ QVERIFY(object->property("nonStrict_compareDifferentObjects").toBool());
+ QVERIFY(object->property("nonStrict_compareObjectWithNullObject").toBool());
}
-void tst_QmlCppCodegen::interceptor()
+void tst_QmlCppCodegen::equalityQUrl()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/interceptor.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("x").toInt(), 100);
- QCOMPARE(object->property("y").toInt(), 100);
+ QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalityQUrl.qml"_s));
+ QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
- QVERIFY(object->property("width").toInt() != 200);
- QVERIFY(object->property("height").toInt() != 200);
- QVERIFY(object->property("qProperty1").toInt() != 300);
- QVERIFY(object->property("qProperty2").toInt() != 300);
- QTRY_COMPARE(object->property("width").toInt(), 200);
- QTRY_COMPARE(object->property("height").toInt(), 200);
- QTRY_COMPARE(object->property("qProperty1").toInt(), 300);
- QTRY_COMPARE(object->property("qProperty2").toInt(), 300);
+ QScopedPointer<QObject> object(c1.create());
+ QVERIFY(!object.isNull() && !c1.isError());
+ QVERIFY(object->property("emptyUrlStrict").toBool());
+ QVERIFY(object->property("emptyUrlWeak").toBool());
+ QVERIFY(object->property("sourceUrlStrict").toBool());
+ QVERIFY(object->property("sourceUrlWeak").toBool());
+ QVERIFY(object->property("sourceIsNotEmptyStrict").toBool());
+ QVERIFY(object->property("sourceIsNotEmptyWeak").toBool());
}
-void tst_QmlCppCodegen::nonNotifyable()
+void tst_QmlCppCodegen::equalityTestsWithNullOrUndefined()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nonNotifyable.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalityTestsWithNullOrUndefined.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(o);
+}
- QCOMPARE(qvariant_cast<QDateTime>(object->property("dayz")),
- QDateTime(QDate(2121, 1, 12), QTime()));
- QCOMPARE(qvariant_cast<QDateTime>(object->property("oParty")),
- QDateTime(QDate(2111, 12, 11), QTime()));
+void tst_QmlCppCodegen::equalityVarAndNonStorable()
+{
+ QQmlEngine engine;
+
+ QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalityVarAndNonStorable.qml"_s));
+ QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
+
+ QScopedPointer<QObject> object(c1.create());
+ QVERIFY(!object.isNull() && !c1.isError());
+ QVERIFY(!object->property("aIsNull").toBool());
+ QVERIFY(object->property("aIsNotNull").toBool());
+ QVERIFY(object->property("aIsNotUndefined").toBool());
+ QVERIFY(object->property("objectIsNotNull").toBool());
+ QVERIFY(!object->property("typedArrayIsNull").toBool());
+ QVERIFY(object->property("isUndefined").toBool());
+ QVERIFY(!object->property("derivedIsNull").toBool());
+
+ QVERIFY(object->property("primitiveIsNull").toBool());
+ QVERIFY(object->property("primitiveIsDefined").toBool());
+ QVERIFY(object->property("primitiveIsUndefined").toBool());
+
+ QVERIFY(object->property("jsValueIsNull").toBool());
+ QVERIFY(object->property("jsValueIsDefined").toBool());
+ QVERIFY(object->property("jsValueIsUndefined").toBool());
+
+ QVERIFY(object->property("nullVarIsUndefined").toBool());
+ QVERIFY(object->property("nullIsUndefined").toBool());
+ QVERIFY(object->property("nullVarIsNull").toBool());
+ QVERIFY(object->property("nullIsNotUndefined").toBool());
}
-void tst_QmlCppCodegen::importsFromImportPath()
+void tst_QmlCppCodegen::equalityVarAndStorable()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/importsFromImportPath.qml"_s));
+ QQmlComponent planner(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Planner.qml"_s));
+ QVERIFY2(!planner.isError(), qPrintable(planner.errorString()));
+ QScopedPointer<QObject> p(planner.create());
+ QVERIFY(!p.isNull());
- // We might propagate the import path, eventually, but for now instantiating is not important.
- // If the compiler accepts the file, it's probably fine.
- QVERIFY(component.isError());
- QCOMPARE(component.errorString(),
- u"qrc:/qt/qml/TestTypes/importsFromImportPath.qml:1 module \"Module\" is not installed\n"_s);
+ QQmlComponent variable(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Variable.qml"_s));
+ QVERIFY2(!variable.isError(), qPrintable(variable.errorString()));
+ QScopedPointer<QObject> v(variable.create());
+ QVERIFY(!v.isNull());
+
+ QVERIFY(p->objectName().isEmpty());
+ QMetaObject::invokeMethod(p.data(), "typeErasedRemoveOne", v.data());
+ QCOMPARE(p->objectName(), u"n");
+
+ v->setProperty("value", 1);
+ QMetaObject::invokeMethod(p.data(), "typeErasedRemoveOne", v.data());
+ QCOMPARE(p->objectName(), u"nd");
+
+ QQmlComponent constraint(&engine, QUrl(u"qrc:/qt/qml/TestTypes/BaseConstraint.qml"_s));
+ QVERIFY2(!constraint.isError(), qPrintable(constraint.errorString()));
+ QScopedPointer<QObject> c(constraint.create());
+ QVERIFY(!c.isNull());
+
+ c->setProperty("output", QVariant::fromValue(v.data()));
+ QCOMPARE(v->property("mark").toInt(), 0);
+ QMetaObject::invokeMethod(p.data(), "typeErasedRun", c.data());
+ QCOMPARE(v->property("mark").toInt(), 5);
+
+ QTest::ignoreMessage(QtDebugMsg, "success");
+ QMetaObject::invokeMethod(p.data(), "verify", 10);
+
+ QTest::ignoreMessage(QtCriticalMsg, "failed 10 11");
+ QMetaObject::invokeMethod(p.data(), "verify", 11);
}
-void tst_QmlCppCodegen::aliasLookup()
+void tst_QmlCppCodegen::equalsUndefined()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/aliasLookup.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalsUndefined.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- const QVariant t = object->property("t");
- QCOMPARE(t.metaType(), QMetaType::fromType<QString>());
- QCOMPARE(t.toString(), u"12"_s);
+ QCOMPARE(object->property("a").toInt(), 50);
+ QCOMPARE(object->property("b").toInt(), 5000);
}
-void tst_QmlCppCodegen::outOfBoundsArray()
+void tst_QmlCppCodegen::evadingAmbiguity()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/outOfBounds.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QTest::ignoreMessage(QtDebugMsg, "oob undefined");
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QVERIFY(object->metaObject()->indexOfProperty("oob") > 0);
- QVERIFY(!object->property("oob").isValid());
- const QVariant oob2 = object->property("oob2");
- QCOMPARE(oob2.metaType(), QMetaType::fromType<QObject *>());
- QCOMPARE(oob2.value<QObject *>(), nullptr);
+ // We need to add an import path here because we cannot namespace the implicit import.
+ // The implicit import is what we use for all the other tests, even if we explicitly
+ // import TestTypes. That is because the TestTypes module is in a subdirectory "data".
+ engine.addImportPath(u":/"_s);
+
+ QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ambiguous1/Ambiguous.qml"_s));
+ QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
+ QScopedPointer<QObject> o1(c1.create());
+ QCOMPARE(o1->objectName(), QStringLiteral("Ambiguous"));
+ QCOMPARE(o1->property("i").toString(), QStringLiteral("Ambiguous1"));
+
+ QQmlComponent c2(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ambiguous2/Ambiguous.qml"_s));
+ QVERIFY2(c2.isReady(), qPrintable(c2.errorString()));
+ QScopedPointer<QObject> o2(c2.create());
+ QCOMPARE(o2->objectName(), QStringLiteral("Ambiguous"));
+ QCOMPARE(o2->property("i").toString(), QStringLiteral("Ambiguous2"));
}
-void tst_QmlCppCodegen::compositeSingleton()
+void tst_QmlCppCodegen::exceptionFromInner()
{
QQmlEngine engine;
- engine.addImportPath(u":/qt/qml/TestTypes/imports/"_s);
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/compositesingleton.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/exceptionFromInner.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> o(component.create());
- QCOMPARE(o->property("x").toDouble(), 4.5);
- QCOMPARE(o->property("y").toDouble(), 10.0);
- QCOMPARE(o->property("smooth").toBool(), true);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "qrc:/qt/qml/TestTypes/exceptionFromInner.qml:7: TypeError: "
+ "Cannot read property 'objectName' of null");
+ QMetaObject::invokeMethod(object.data(), "disbelieveFail");
}
-void tst_QmlCppCodegen::lotsOfRegisters()
+void tst_QmlCppCodegen::excessiveParameters()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/page.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/excessiveParameters.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
+ QSignalSpy spy(object.data(), SIGNAL(foo()));
+ QTRY_VERIFY(spy.size() > 0);
+}
- const auto compare = [&]() {
- const qreal implicitBackgroundWidth = object->property("implicitBackgroundWidth").toDouble();
- const qreal leftInset = object->property("leftInset").toDouble();
- const qreal rightInset = object->property("rightInset").toDouble();
- const qreal contentWidth = object->property("contentWidth").toDouble();
- const qreal leftPadding = object->property("leftPadding").toDouble();
- const qreal rightPadding = object->property("rightPadding").toDouble();
- const qreal implicitFooterWidth = object->property("implicitFooterWidth").toDouble();
- const qreal implicitHeaderWidth = object->property("implicitHeaderWidth").toDouble();
+void tst_QmlCppCodegen::extendedTypes()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/extendedTypes.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
- const qreal implicitWidth = object->property("implicitWidth").toDouble();
- QCOMPARE(implicitWidth, qMax(qMax(implicitBackgroundWidth + leftInset + rightInset,
- contentWidth + leftPadding + rightPadding),
- qMax(implicitHeaderWidth, implicitFooterWidth)));
- };
+ QTest::ignoreMessage(QtDebugMsg, "6 QSizeF(10, 20) 30");
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- compare();
+ QCOMPARE(object->property("a").toInt(), 6);
+ QCOMPARE(qvariant_cast<QSizeF>(object->property("b")), QSizeF(10, 20));
+ QCOMPARE(object->property("c").toInt(), 30);
+ QCOMPARE(object->property("d").toString(), u"QSizeF(10, 20)"_s);
- const QList<const char *> props = {
- "leftInset", "rightInset", "contentWidth", "leftPadding", "rightPadding"
- };
+ QCOMPARE(object->property("e").toInt(), 2);
+}
- for (int i = 0; i < 100; ++i) {
- QVERIFY(object->setProperty(props[i % props.size()], (i * 17) % 512));
- compare();
- }
+void tst_QmlCppCodegen::failures()
+{
+ const auto &aotFailure
+ = QmlCacheGeneratedCode::_qt_qml_TestTypes_failures_qml::aotBuiltFunctions[0];
+ QVERIFY(!aotFailure.functionPtr);
+ QCOMPARE(aotFailure.functionIndex, 0);
}
-void tst_QmlCppCodegen::inPlaceDecrement()
+void tst_QmlCppCodegen::fallbackLookups()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/dialog.qml"_s));
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QObject *header = qvariant_cast<QObject *>(object->property("header"));
- QVERIFY(header);
- QObject *background = qvariant_cast<QObject *>(header->property("background"));
- QObject *parent = qvariant_cast<QObject *>(background->property("parent"));
+ const QUrl document(u"qrc:/qt/qml/TestTypes/fallbacklookups.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QCOMPARE(background->property("width").toInt(), parent->property("width").toInt() + 1);
- QCOMPARE(background->property("height").toInt(), parent->property("height").toInt() - 1);
+ QCOMPARE(o->objectName(), QString());
+ int result = 0;
- QVERIFY(object->setProperty("width", QVariant::fromValue(17)));
- QVERIFY(parent->property("width").toInt() > 0);
- QVERIFY(object->setProperty("height", QVariant::fromValue(53)));
- QVERIFY(parent->property("height").toInt() > 0);
+ QMetaObject::invokeMethod(o.data(), "withContext", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 16);
+ QCOMPARE(o->objectName(), QStringLiteral("aa93"));
- QCOMPARE(background->property("width").toInt(), parent->property("width").toInt() + 1);
- QCOMPARE(background->property("height").toInt(), parent->property("height").toInt() - 1);
+ QMetaObject::invokeMethod(o.data(), "withId", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 17);
+ QCOMPARE(o->objectName(), QStringLiteral("bb94"));
- QCOMPARE(object->property("a").toInt(), 1024);
+ 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::shifts()
+void tst_QmlCppCodegen::fileImportsContainCxxTypes()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/shifts.qml"_s));
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
-
- QCOMPARE(object->property("a").toInt(), 9728);
- QCOMPARE(object->property("b").toInt(), 4864);
- QCOMPARE(object->property("c").toInt(), 19448);
- QCOMPARE(object->property("d").toInt(), 9731);
- QCOMPARE(object->property("e").toInt(), 0);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/usingCxxTypesFromFileImports.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), u"horst guenther"_s);
}
-void tst_QmlCppCodegen::valueTypeProperty()
+void tst_QmlCppCodegen::flagEnum()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/valueTypeProperty.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/flagEnum.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- QFont font = qvariant_cast<QFont>(object->property("font"));
- QCOMPARE(object->property("foo").toString(), font.family());
- font.setFamily(u"Bar"_s);
- object->setProperty("font", QVariant::fromValue(font));
- QCOMPARE(object->property("foo").toString(), u"Bar"_s);
+ QQmlCommunicationPermission *p = qobject_cast<QQmlCommunicationPermission *>(o.data());
+ QCOMPARE(p->communicationModes(), CommunicationPermission::Access);
}
-void tst_QmlCppCodegen::propertyOfParent()
+void tst_QmlCppCodegen::flushBeforeCapture()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/RootWithoutId.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
-
- QObject *child = qmlContext(object.data())->objectForName(u"item"_s);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/noBindingLoop.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- bool expected = false;
+ QCOMPARE(o->property("deviation").toDouble(), 9.0 / 3.3333);
+ QCOMPARE(o->property("samples").toInt(), 16);
+ QCOMPARE(o->property("radius").toDouble(), 8.0);
+}
- for (int i = 0; i < 3; ++i) {
- const QVariant foo = object->property("foo");
- QCOMPARE(foo.metaType(), QMetaType::fromType<bool>());
- QCOMPARE(foo.toBool(), expected);
+void tst_QmlCppCodegen::fromBoolValue()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/fromBoolValue.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QCOMPARE(o->property("a").toBool(), true);
+ o->setProperty("x", 100);
+ QCOMPARE(o->property("a").toBool(), false);
- const QVariant bar = object->property("bar");
- QCOMPARE(bar.metaType(), QMetaType::fromType<bool>());
- QCOMPARE(bar.toBool(), expected);
+ QCOMPARE(o->property("width").toInt(), 100);
+ QCOMPARE(o->property("b").toBool(), false);
- const QVariant visible = child->property("visible");
- QCOMPARE(visible.metaType(), QMetaType::fromType<bool>());
- QCOMPARE(visible.toBool(), expected);
+ QScopedPointer<QObject> parent(c.create());
+ o->setProperty("parent", QVariant::fromValue(parent.data()));
+ QCOMPARE(o->property("width").toInt(), 100);
+ QCOMPARE(o->property("b").toBool(), false);
- expected = !expected;
- object->setProperty("foo", expected);
- }
+ o->setProperty("state", QVariant::fromValue(u"foo"_s));
+ QCOMPARE(o->property("width").toInt(), 0);
+ QCOMPARE(o->property("b").toBool(), false);
}
-void tst_QmlCppCodegen::accessModelMethodFromOutSide()
+void tst_QmlCppCodegen::funcWithParams()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/AccessModelMethodsFromOutside.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
-
- QTest::ignoreMessage(QtDebugMsg, "3");
- QTest::ignoreMessage(QtDebugMsg, "Apple");
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/funcWithParams.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
-
- QCOMPARE(object->property("cost1").toDouble(), 3);
- QCOMPARE(object->property("name1").toString(), u"Orange"_s);
- QCOMPARE(object->property("cost2").toDouble(), 1.95);
- QCOMPARE(object->property("name2").toString(), u"Banana"_s);
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("bar").toInt(), 30);
}
// QML-generated types have no C++ names, but we want to call a method that
@@ -1150,42 +1999,55 @@ void tst_QmlCppCodegen::accessModelMethodFromOutSide()
// the metatype of the argument we pass does not match the metatype of the
// argument the method expects. In order to work around it, we specialize
// qMetaTypeInterfaceForType() and produce a "correct" metatype this way.
-class Dummy_QMLTYPE_0;
+class Dummy2_QMLTYPE_0;
// We set this to the actual value retrieved from an actual instance of the QML
// type before retrieving the metatype interface for the first time.
static const QtPrivate::QMetaTypeInterface *dummyMetaTypeInterface = nullptr;
template<>
-const QtPrivate::QMetaTypeInterface *QtPrivate::qMetaTypeInterfaceForType<Dummy_QMLTYPE_0 *>() {
+const QtPrivate::QMetaTypeInterface *QtPrivate::qMetaTypeInterfaceForType<Dummy2_QMLTYPE_0 *>() {
return dummyMetaTypeInterface;
}
void tst_QmlCppCodegen::functionArguments()
{
+ qmlClearTypeRegistrations();
+
QQmlEngine engine;
+ QQmlComponent preheat(&engine);
+ preheat.setData(R"(
+ import QtQml
+ import TestTypes
+ QtObject {
+ objectName: Style.objectName
+ }
+ )", QUrl(u"qrc:/qt/qml/TestTypes/preheat.qml"_s));
+ QVERIFY2(preheat.isReady(), qPrintable(preheat.errorString()));
+ QScopedPointer<QObject> hot(preheat.create());
+ QVERIFY(!hot.isNull());
- // Ensure that Dummy gets counter value 0. Don't do that at home
+ // Ensure that Dummy gets counter value 1. Don't do that at home
QScopedValueRollback<QAtomicInt> rb(QQmlPropertyCacheCreatorBase::classIndexCounter, 0);
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Dummy.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Dummy2.qml"_s));
QVERIFY2(component.isReady(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
const QMetaObject *metaObject = object->metaObject();
dummyMetaTypeInterface = metaObject->metaType().iface();
const QByteArray className = QByteArray(metaObject->className());
- QCOMPARE(className, "Dummy_QMLTYPE_0");
+ QCOMPARE(className, "Dummy2_QMLTYPE_0");
int result;
int a = 1;
bool b = false;
- Dummy_QMLTYPE_0 *c = nullptr;
+ Dummy2_QMLTYPE_0 *c = nullptr;
double d = -1.2;
int e = 3;
metaObject->invokeMethod(
object.data(), "someFunction", Q_RETURN_ARG(int, result),
- Q_ARG(int, a), Q_ARG(bool, b), Q_ARG(Dummy_QMLTYPE_0 *, c),
+ Q_ARG(int, a), Q_ARG(bool, b), Q_ARG(Dummy2_QMLTYPE_0 *, c),
Q_ARG(double, d), Q_ARG(int, e));
QCOMPARE(result, 42);
@@ -1198,473 +2060,780 @@ void tst_QmlCppCodegen::functionArguments()
QCOMPARE(concatenated, u"foobar"_s);
}
-void tst_QmlCppCodegen::bindingExpression()
+void tst_QmlCppCodegen::functionCallOnNamespaced()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/BindingExpression.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
-
- QObject *child = qmlContext(object.data())->objectForName(u"child"_s);
-
- double width = 200;
- double y = 10;
- for (int i = 0; i < 10; ++i) {
- QCOMPARE(object->property("width").toDouble(), width);
- QCOMPARE(object->property("height").toDouble(), width);
- QCOMPARE(object->property("y").toDouble(), y);
-
- const double childY = y + (width - 100) / 2;
- QCOMPARE(child->property("y").toDouble(), childY);
- QCOMPARE(object->property("mass"), childY > 100 ? u"heavy"_s : u"light"_s);
- QCOMPARE(object->property("test_division").toDouble(), width / 1000 + 50);
- QCOMPARE(object->property("test_ternary").toDouble(), 2.2);
-
- const int test_switch = object->property("test_switch").toInt();
- switch (int(width) % 3) {
- case 0:
- QCOMPARE(test_switch, 130);
- break;
- case 1:
- QCOMPARE(test_switch, 380);
- break;
- case 2:
- QCOMPARE(test_switch, 630);
- break;
- }
+ {
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/themergood.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("i").toInt(), 12);
+ }
- width = 200 * i;
- y = 10 + i;
- object->setProperty("width", width);
- object->setProperty("y", y);
+ {
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/themerbad.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("r"), QVariant::fromValue(QRectF(5.0, 10.0, 1.0, 1.0)));
}
}
-void tst_QmlCppCodegen::voidFunction()
+void tst_QmlCppCodegen::functionLookup()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/voidfunction.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QVERIFY(object->objectName().isEmpty());
- object->metaObject()->invokeMethod(object.data(), "doesNotReturnValue");
- QCOMPARE(object->objectName(), u"barbar"_s);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/functionLookup.qml"_s));
+ 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::overriddenProperty()
+void tst_QmlCppCodegen::functionReturningVoid()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/childobject.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->objectName(), u"kraut"_s);
- QCOMPARE(object->property("doneThing").toInt(), 5);
- QCOMPARE(object->property("usingFinal").toInt(), 5);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/functionReturningVoid.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- auto checkAssignment = [&]() {
- const QString newName = u"worscht"_s;
- QMetaObject::invokeMethod(object.data(), "setChildObjectName", Q_ARG(QString, newName));
- QCOMPARE(object->objectName(), newName);
- };
- checkAssignment();
+ // It should be able to call the methods and wrap the void values into invalid QVariants,
+ // without crashing.
+ QVERIFY(o->metaObject()->indexOfProperty("aa") >= 0);
+ QVERIFY(o->metaObject()->indexOfProperty("bb") >= 0);
+ QVERIFY(!o->property("aa").isValid());
+ QVERIFY(!o->property("bb").isValid());
+}
- ObjectWithMethod *benign = new ObjectWithMethod(object.data());
- benign->theThing = 10;
- benign->setObjectName(u"cabbage"_s);
- object->setProperty("child", QVariant::fromValue(benign));
- QCOMPARE(object->objectName(), u"cabbage"_s);
- checkAssignment();
- QCOMPARE(object->property("doneThing").toInt(), 10);
- QCOMPARE(object->property("usingFinal").toInt(), 10);
+void tst_QmlCppCodegen::functionTakingVar()
+{
+ QQmlEngine engine;
+ const QUrl document(u"qrc:/qt/qml/TestTypes/functionTakingVar.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- OverriddenObjectName *evil = new OverriddenObjectName(object.data());
- QTest::ignoreMessage(QtWarningMsg,
- "Final member fff is overridden in class OverriddenObjectName. "
- "The override won't be used.");
- object->setProperty("child", QVariant::fromValue(evil));
+ QVERIFY(!o->property("c").isValid());
- QCOMPARE(object->objectName(), u"borschtsch"_s);
+ 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);
- checkAssignment();
- QCOMPARE(object->property("doneThing").toInt(), 7);
- QCOMPARE(object->property("usingFinal").toInt(), 5);
+ QCOMPARE(o->property("c"), QVariant::fromValue<int>(11));
}
-void tst_QmlCppCodegen::listLength()
+void tst_QmlCppCodegen::getLookupOfScript()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listlength.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("l").toInt(), 2);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/NotificationItem.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), u"heading"_s);
}
-void tst_QmlCppCodegen::parentProperty()
+void tst_QmlCppCodegen::getOptionalLookup_data()
{
- QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/parentProp.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("c").toInt(), 11);
- QCOMPARE(object->property("i").toInt(), 22);
- object->setProperty("a", QVariant::fromValue(22));
- QCOMPARE(object->property("c").toInt(), 28);
- object->setProperty("implicitWidth", QVariant::fromValue(14));
- QCOMPARE(object->property("i").toInt(), 26);
+ QTest::addColumn<QString>("propertyName");
+ QTest::addColumn<QVariant>("expected");
- QObject *child = qmlContext(object.data())->objectForName(u"child"_s);
- QObject *sibling = qmlContext(object.data())->objectForName(u"sibling"_s);
- QObject *evil = qmlContext(object.data())->objectForName(u"evil"_s);
+ // Objects
+ QTest::addRow("int on object") << u"to1"_s << QVariant(5);
+ QTest::addRow("string on object") << u"to2"_s << QVariant("6");
+ QTest::addRow("object on object") << u"to3"_s << QVariant::fromValue<QObject *>(nullptr);
+ QTest::addRow("int on null") << u"to4"_s << QVariant(); // undefined
+ QTest::addRow("any on undefined as object") << u"to5"_s << QVariant(); // undefined
+ QTest::addRow("int on string on object") << u"to6"_s << QVariant(1);
- child->setProperty("parent", QVariant::fromValue(sibling));
+ // Value Types
+ QTest::addRow("int on rect") << u"tv1"_s << QVariant(50);
+ QTest::addRow("int on point") << u"tv2"_s << QVariant(-10);
+ QTest::addRow("int on undefined as point") << u"tv4"_s << QVariant(); // undefined
- QCOMPARE(child->property("b").toInt(), 0);
- QCOMPARE(child->property("i").toInt(), 28);
- QCOMPARE(object->property("i").toInt(), 56);
+ // Enums
+ QTest::addRow("enum on object") << u"te1"_s << QVariant(1);
+ QTest::addRow("enum on type") << u"te2"_s << QVariant(1);
+ QTest::addRow("enums comparison 1") << u"te3"_s << QVariant(false);
+ QTest::addRow("enums comparison 2") << u"te4"_s << QVariant(true);
- child->setProperty("parent", QVariant::fromValue(evil));
+ // Complex chains
+ QTest::addRow("mixed 1") << u"tc1"_s << QVariant(-10);
+ QTest::addRow("mixed 2") << u"tc2"_s << QVariant(0);
+ QTest::addRow("early out 1") << u"tc4"_s << QVariant(); // undefined
+ QTest::addRow("early out 2") << u"tc5"_s << QVariant(); // undefined
+}
- QCOMPARE(child->property("b").toInt(), 5994);
- QCOMPARE(object->property("c").toInt(), 5996);
+void tst_QmlCppCodegen::getOptionalLookup()
+{
+ QQmlEngine engine;
+ const QUrl document(u"qrc:/qt/qml/TestTypes/getOptionalLookup.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QCOMPARE(child->property("i").toInt(), 443);
- QCOMPARE(object->property("i").toInt(), 886);
+ QFETCH(QString, propertyName);
+ QFETCH(QVariant, expected);
- {
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/specificParent.qml"_s));
+ QVariant actual = o->property(propertyName.toLocal8Bit());
+ QCOMPARE(actual, expected);
+}
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> rootObject(component.create());
- QVERIFY(rootObject);
+void tst_QmlCppCodegen::getOptionalLookupOnQJSValueNonStrict()
+{
+ QQmlEngine engine;
+ const QUrl document(u"qrc:/qt/qml/TestTypes/GetOptionalLookupOnQJSValueNonStrict.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QCOMPARE(rootObject->property("a").toReal(), 77.0);
- }
+ QVERIFY(o->property("b").toBool());
}
-void tst_QmlCppCodegen::registerElimination()
+void tst_QmlCppCodegen::getOptionalLookupShadowed()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/registerelimination.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ const QUrl document(u"qrc:/qt/qml/TestTypes/GetOptionalLookupShadowed.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+
+ QCOMPARE(o->property("res").toString(), "a");
+}
+
+void tst_QmlCppCodegen::globals()
+{
+ QQmlEngine engine;
+ int exitCode = -1;
+ QObject::connect(&engine, &QQmlEngine::exit, [&](int code) { exitCode = code; });
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/globals.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+
+ const QByteArray message = QByteArray("Start 2 ") + arg1();
+ QTest::ignoreMessage(QtDebugMsg, message.constData());
+
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
+ QTRY_COMPARE(exitCode, 0);
- // Increment of 23 hits both 0 and 460
- for (int input = -23; input < 700; input += 23) {
- object->setProperty("input", input);
- if (input <= 0 || input >= 460)
- QCOMPARE(object->property("output").toInt(), 459);
- else
- QCOMPARE(object->property("output").toInt(), input);
- }
+ QObject *application = qvariant_cast<QObject *>(object->property("application"));
+ QVERIFY(application);
+ QCOMPARE(QString::fromUtf8(application->metaObject()->className()),
+ u"QQuickApplication"_s);
+
+ QTest::ignoreMessage(QtDebugMsg, "End");
+ QMetaObject::invokeMethod(application, "aboutToQuit");
+
+ const QVariant somewhere = object->property("somewhere");
+ QCOMPARE(somewhere.userType(), QMetaType::QUrl);
+ QCOMPARE(qvariant_cast<QUrl>(somewhere).toString(), u"qrc:/somewhere/else.qml"_s);
+
+ const QVariant somewhereString = object->property("somewhereString");
+ QCOMPARE(somewhereString.userType(), QMetaType::QString);
+ QCOMPARE(somewhereString.toString(), u"qrc:/somewhere/else.qml"_s);
+
+ const QVariant plain = object->property("plain");
+ QCOMPARE(plain.userType(), QMetaType::QUrl);
+ QCOMPARE(qvariant_cast<QUrl>(plain).toString(), u"/not/here.qml"_s);
}
-void tst_QmlCppCodegen::asCast()
+void tst_QmlCppCodegen::idAccess()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/asCast.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> root(component.create());
- QVERIFY(!root.isNull());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/idAccess.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- QQmlContext *context = qmlContext(root.data());
- const QObject *object = context->objectForName(u"object"_s);
- const QObject *item = context->objectForName(u"item"_s);
- const QObject *rectangle = context->objectForName(u"rectangle"_s);
- const QObject *dummy = context->objectForName(u"dummy"_s);
+ QVERIFY(object->property("y").toInt() != 48);
+ QCOMPARE(object->property("y").toInt(), 12);
+ object->setProperty("z", 13);
+ QCOMPARE(object->property("y").toInt(), 13);
+ object->setProperty("x", QVariant::fromValue(333));
+ QCOMPARE(object->property("y").toInt(), 48);
- QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsObject")), object);
- QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsItem")), nullptr);
- QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsRectangle")), nullptr);
- QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsDummy")), nullptr);
+ // The binding was broken by setting the property
+ object->setProperty("z", 14);
+ QCOMPARE(object->property("y").toInt(), 48);
- QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsObject")), item);
- QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsItem")), item);
- QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsRectangle")), nullptr);
- QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsDummy")), nullptr);
+ QObject *ttt = qmlContext(object.data())->objectForName(u"ttt"_s);
+ QFont f = qvariant_cast<QFont>(ttt->property("font"));
+ QCOMPARE(f.pointSize(), 22);
- QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsObject")), rectangle);
- QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsItem")), rectangle);
- QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsRectangle")), rectangle);
- QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsDummy")), nullptr);
+ QObject::connect(object.data(), &QObject::objectNameChanged, ttt, [&](){
+ ttt->setParent(nullptr);
+ QJSEngine::setObjectOwnership(ttt, QJSEngine::CppOwnership);
+ object.reset(ttt);
+ });
- QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsObject")), dummy);
- QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsItem")), dummy);
- QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsRectangle")), nullptr);
- QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsDummy")), dummy);
+ QVERIFY(object->objectName().isEmpty());
+ QVERIFY(ttt->objectName().isEmpty());
+ ttt->setProperty("text", u"kill"_s);
+ QCOMPARE(object.data(), ttt);
+ QCOMPARE(ttt->objectName(), u"context"_s);
}
-void tst_QmlCppCodegen::noQQmlData()
+void tst_QmlCppCodegen::ignoredFunctionReturn()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/noQQmlData.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ignoredFunctionReturn.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+}
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/noQQmlData.qml:7: TypeError: "
- "Cannot read property 'name' of null");
- QScopedPointer<QObject> root(component.create());
- QVERIFY(!root.isNull());
+void tst_QmlCppCodegen::importsFromImportPath()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/importsFromImportPath.qml"_s));
- BirthdayParty *party = qobject_cast<BirthdayParty *>(root.data());
- QVERIFY(party != nullptr);
+ // We might propagate the import path, eventually, but for now instantiating is not important.
+ // If the compiler accepts the file, it's probably fine.
+ QVERIFY(component.isError());
+ QCOMPARE(component.errorString(),
+ u"qrc:/qt/qml/TestTypes/importsFromImportPath.qml:1 module \"Module\" is not installed\n"_s);
+}
- QCOMPARE(party->host(), nullptr);
- QCOMPARE(party->property("n").toString(), QString());
+void tst_QmlCppCodegen::inPlaceDecrement()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/dialog.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QObject *header = qvariant_cast<QObject *>(object->property("header"));
+ QVERIFY(header);
+ QObject *background = qvariant_cast<QObject *>(header->property("background"));
+ QObject *parent = qvariant_cast<QObject *>(background->property("parent"));
- Person *host1 = new Person(party);
- party->setHost(host1);
- QCOMPARE(party->property("n").toString(), u"Bart in da house!"_s);
- host1->setName(u"Marge"_s);
- QCOMPARE(party->property("n").toString(), u"Marge in da house!"_s);
+ QCOMPARE(background->property("width").toInt(), parent->property("width").toInt() + 1);
+ QCOMPARE(background->property("height").toInt(), parent->property("height").toInt() - 1);
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/noQQmlData.qml:7: TypeError: "
- "Cannot read property 'name' of null");
+ QVERIFY(object->setProperty("width", QVariant::fromValue(17)));
+ QVERIFY(parent->property("width").toInt() > 0);
+ QVERIFY(object->setProperty("height", QVariant::fromValue(53)));
+ QVERIFY(parent->property("height").toInt() > 0);
- // Doesn't crash
- party->setHost(nullptr);
+ QCOMPARE(background->property("width").toInt(), parent->property("width").toInt() + 1);
+ QCOMPARE(background->property("height").toInt(), parent->property("height").toInt() - 1);
- // Lookups are initialized now, and we introduce an object without QQmlData
- Person *host2 = new Person(party);
- party->setHost(host2);
- QCOMPARE(party->property("n").toString(), u"Bart in da house!"_s);
- host2->setName(u"Homer"_s);
- QCOMPARE(party->property("n").toString(), u"Homer in da house!"_s);
+ QCOMPARE(object->property("a").toInt(), 1024);
+}
- QMetaObject::invokeMethod(party, "burn");
- engine.collectGarbage();
+void tst_QmlCppCodegen::inaccessibleProperty()
+{
+ QQmlEngine engine;
- // Does not crash
- party->setProperty("inDaHouse", u" burns!"_s);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/versionmismatch.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
- // Mr Burns may or may not burn, depending on whether we use lookups.
- // If using lookups, the binding is aborted when we find the isQueuedForDeletion flag.
- // If reading the property directly, we don't have to care about it.
- QVERIFY(party->property("n").toString().startsWith(u"Mr Burns"_s));
+ QCOMPARE(o->property("c").toInt(), 5);
}
-void tst_QmlCppCodegen::scopeObjectDestruction()
+void tst_QmlCppCodegen::indirectlyShadowable()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/fileDialog.qml"_s));
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> rootObject(component.create());
- QVERIFY(rootObject);
+ const QString url = u"qrc:/qt/qml/TestTypes/indirectlyShadowable.qml"_s;
+ QQmlComponent c(&engine, QUrl(url));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- QObject *dialog = rootObject->property("dialog").value<QObject *>();
- QVERIFY(dialog);
+ const auto verifyShadowable = [&](const QString &objectName) {
+ QObject *outer = o->property("outer").value<QObject *>();
+ QVERIFY(outer);
+ QObject *inner = outer->property("inner").value<QObject *>();
+ QVERIFY(inner);
+ QObject *shadowable = inner->property("shadowable").value<QObject *>();
+ QVERIFY(shadowable);
+ QCOMPARE(shadowable->objectName(), objectName);
+ };
- // We cannot check the warning messages. The AOT compiled code complains about reading the
- // "parent" property of an object scheduled for deletion. The runtime silently returns undefined
- // at that point and then complains about not being able to read a property on undefined.
+ const auto verifyNotShadowable = [&](const QString &objectName) {
+ QObject *notShadowable = o->property("notShadowable").value<QObject *>();
+ QCOMPARE(notShadowable->objectName(), objectName);
+ };
- // Doesn't crash, even though it triggers bindings on scope objects scheduled for deletion.
- QMetaObject::invokeMethod(dialog, "open");
-}
+ const auto verifyEvil = [&]() {
+ QObject *outer = o->property("outer").value<QObject *>();
+ QVERIFY(outer);
+ QCOMPARE(outer->property("inner").toString(), u"evil"_s);
+ };
-static void checkColorProperties(QQmlComponent *component)
-{
- QVERIFY2(component->isReady(), qPrintable(component->errorString()));
- QScopedPointer<QObject> rootObject(component->create());
- QVERIFY(rootObject);
+ verifyShadowable(u"shadowable"_s);
+ verifyNotShadowable(u"notShadowable"_s);
- const QMetaObject *mo = QMetaType::fromName("QQuickIcon").metaObject();
- QVERIFY(mo != nullptr);
+ QMetaObject::invokeMethod(o.data(), "setInnerShadowable");
- const QMetaProperty prop = mo->property(mo->indexOfProperty("color"));
- QVERIFY(prop.isValid());
+ verifyShadowable(u"self"_s);
+ verifyNotShadowable(u"notShadowable"_s);
- const QVariant a = rootObject->property("a");
- QVERIFY(a.isValid());
+ QMetaObject::invokeMethod(o.data(), "getInnerShadowable");
- const QVariant iconColor = prop.readOnGadget(rootObject->property("icon").data());
- QVERIFY(iconColor.isValid());
+ verifyShadowable(u"self"_s);
+ verifyNotShadowable(u"self"_s);
- const QMetaType colorType = QMetaType::fromName("QColor");
- QVERIFY(colorType.isValid());
+ QMetaObject::invokeMethod(o.data(), "turnEvil");
- QCOMPARE(a.metaType(), colorType);
- QCOMPARE(iconColor.metaType(), colorType);
+ verifyEvil();
+ verifyNotShadowable(u"self"_s);
- QCOMPARE(iconColor, a);
+ // Does not produce an error message because JavaScript.
+ QMetaObject::invokeMethod(o.data(), "setInnerShadowable");
+
+ verifyEvil();
+ verifyNotShadowable(u"self"_s);
+
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(url + u":29: Error: Cannot assign [undefined] to QObject*"_s));
+ QMetaObject::invokeMethod(o.data(), "getInnerShadowable");
+
+ verifyEvil();
+ verifyNotShadowable(u"self"_s);
}
-void tst_QmlCppCodegen::colorAsVariant()
+void tst_QmlCppCodegen::infinities()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/colorAsVariant.qml"_s));
- checkColorProperties(&component);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/infinities.qml"_s));
+ 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::bindToValueType()
+void tst_QmlCppCodegen::infinitiesToInt()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/bindToValueType.qml"_s));
- checkColorProperties(&component);
+
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/infinitiesToInt.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ const char *props[] = {"a", "b", "c"};
+ for (const char *prop : props) {
+ const QVariant i = o->property(prop);
+ QCOMPARE(i.metaType(), QMetaType::fromType<int>());
+ bool ok = false;
+ QCOMPARE(i.toInt(&ok), 0);
+ QVERIFY(ok);
+ }
}
-void tst_QmlCppCodegen::undefinedResets()
+void tst_QmlCppCodegen::innerObjectNonShadowable()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/undefinedResets.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ownProperty.qml"_s));
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
QScopedPointer<QObject> rootObject(component.create());
QVERIFY(rootObject);
- Person *person = qobject_cast<Person *>(rootObject.data());
- QVERIFY(person);
- QCOMPARE(person->shoeSize(), 0);
- QCOMPARE(person->name(), u"Marge"_s);
-
- person->setShoeSize(11);
+ QCOMPARE(rootObject->objectName(), u"foo"_s);
+}
- QCOMPARE(person->shoeSize(), 11);
- QCOMPARE(person->name(), u"Bart"_s);
+void tst_QmlCppCodegen::intEnumCompare()
+{
+ QQmlEngine engine;
+ {
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/intEnumCompare.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("a").toBool(), true);
+ QCOMPARE(o->property("b").toBool(), false);
+ QCOMPARE(o->property("c").toBool(), true);
+ QCOMPARE(o->property("d").toBool(), false);
+ }
- person->setShoeSize(10);
- QCOMPARE(person->shoeSize(), 10);
- QCOMPARE(person->name(), u"Marge"_s);
+ {
+ // We cannot use Qt.red in QML because it's lower case.
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumInvalid.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("c").toBool(), true);
+ QCOMPARE(o->property("d").toBool(), false);
+ }
+}
- person->setName(u"no one"_s);
- QCOMPARE(person->name(), u"no one"_s);
+void tst_QmlCppCodegen::intOverflow()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/intOverflow.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("a").toDouble(), 1.09951162778e+12);
+ QCOMPARE(object->property("b").toInt(), 5);
+}
- person->setObjectName(u"the one"_s);
- QCOMPARE(person->name(), u"Bart"_s);
+void tst_QmlCppCodegen::intToEnum()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/intToEnum.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ MyType *m = qobject_cast<MyType *>(o.data());
+ QCOMPARE(m->a(), MyType::D);
+ QCOMPARE(m->property("b").toInt(), 24);
}
-void tst_QmlCppCodegen::innerObjectNonShadowable()
+void tst_QmlCppCodegen::interceptor()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ownProperty.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/interceptor.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> rootObject(component.create());
- QVERIFY(rootObject);
+ QCOMPARE(object->property("x").toInt(), 100);
+ QCOMPARE(object->property("y").toInt(), 100);
- QCOMPARE(rootObject->objectName(), u"foo"_s);
+ QVERIFY(object->property("width").toInt() != 200);
+ QVERIFY(object->property("height").toInt() != 200);
+ QVERIFY(object->property("qProperty1").toInt() != 300);
+ QVERIFY(object->property("qProperty2").toInt() != 300);
+ QTRY_COMPARE(object->property("width").toInt(), 200);
+ QTRY_COMPARE(object->property("height").toInt(), 200);
+ QTRY_COMPARE(object->property("qProperty1").toInt(), 300);
+ QTRY_COMPARE(object->property("qProperty2").toInt(), 300);
}
-void tst_QmlCppCodegen::ownPropertiesNonShadowable()
+void tst_QmlCppCodegen::interestingFiles()
{
+ QFETCH(QString, file);
+ QFETCH(bool, isValid);
+
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/overriddenMember.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/%1"_s.arg(file)));
+ if (isValid) {
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ } else {
+ QVERIFY(component.isError());
+ }
+}
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> rootObject(component.create());
- QVERIFY(rootObject);
+void tst_QmlCppCodegen::interestingFiles_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<bool>("isValid");
- QCOMPARE(rootObject->property("ppp").toInt(), 16);
- QCOMPARE(rootObject->property("ppp2").toInt(), 9);
- QCOMPARE(rootObject->property("ppp3").toInt(), 12);
+ QTest::addRow("conversions2") << u"conversions2.qml"_s << true;
+ QTest::addRow("TestCase") << u"TestCase.qml"_s << true;
+ QTest::addRow("layouts") << u"layouts.qml"_s << true;
+ QTest::addRow("interactive") << u"interactive.qml"_s << true;
+ QTest::addRow("Panel") << u"Panel.qml"_s << true;
+ QTest::addRow("ProgressBar") << u"ProgressBar/ProgressBar.ui.qml"_s << true;
+ QTest::addRow("Root") << u"ProgressBar/Root.qml"_s << true;
+ QTest::addRow("noscope") << u"noscope.qml"_s << true;
+ QTest::addRow("dynamicscene") << u"dynamicscene.qml"_s << true;
+ QTest::addRow("curlygrouped") << u"curlygrouped.qml"_s << true;
+ QTest::addRow("cycleHead") << u"cycleHead.qml"_s << false;
+ QTest::addRow("deadStoreLoop") << u"deadStoreLoop.qml"_s << true;
+ QTest::addRow("moveRegVoid") << u"moveRegVoid.qml"_s << true;
}
-void tst_QmlCppCodegen::modulePrefix()
+void tst_QmlCppCodegen::internalConversion()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/modulePrefix.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/internalConversion.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> obj(c.create());
+ QVERIFY(!obj.isNull());
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> rootObject(component.create());
- QVERIFY(rootObject);
+ QObject *offset = obj->property("offset").value<QObject *>();
+ QVERIFY(offset);
- QCOMPARE(rootObject->property("foo").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
- QCOMPARE(rootObject->property("bar").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
- QCOMPARE(rootObject->property("baz").toString(), QStringLiteral("ItIsTheSingleton"));
+ QCOMPARE(offset->objectName(), "hello"_L1);
+ QCOMPARE(offset->property("mark").toString(), "hello"_L1);
}
-void tst_QmlCppCodegen::colorString()
+void tst_QmlCppCodegen::invalidPropertyType()
{
+ // Invisible on purpose
+ qmlRegisterType<MyCppType>("App", 1, 0, "MyCppType");
+
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/colorString.qml"_s));
+ QQmlComponent okComponent(&engine, QUrl(u"qrc:/qt/qml/TestTypes/OkType.qml"_s));
+ QVERIFY2(okComponent.isReady(), qPrintable(okComponent.errorString()));
+ QScopedPointer<QObject> picker(okComponent.create());
+ QVERIFY2(!picker.isNull(), qPrintable(okComponent.errorString()));
+ QObject *inner = qmlContext(picker.data())->objectForName(u"inner"_s);
+ QVERIFY(inner);
+ MyCppType *myCppType = qobject_cast<MyCppType *>(inner);
+ QVERIFY(myCppType);
+ QVERIFY(!myCppType->useListDelegate());
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> rootObject(component.create());
- QVERIFY(rootObject);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/BadType.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.createWithInitialProperties(
+ QVariantMap {{u"picker"_s, QVariant::fromValue(picker.data())}}));
+ QVERIFY2(!o.isNull(), qPrintable(c.errorString()));
+ QVERIFY(!myCppType->useListDelegate());
- QCOMPARE(qvariant_cast<QColor>(rootObject->property("c")), QColor::fromRgb(0xdd, 0xdd, 0xdd));
- QCOMPARE(qvariant_cast<QColor>(rootObject->property("d")), QColor::fromRgb(0xaa, 0xaa, 0xaa));
- QCOMPARE(qvariant_cast<QColor>(rootObject->property("e")), QColor::fromRgb(0x11, 0x22, 0x33));
+ o->setProperty("useListDelegate", QVariant::fromValue<bool>(true));
+ QVERIFY(myCppType->useListDelegate());
}
-void tst_QmlCppCodegen::urlString()
+void tst_QmlCppCodegen::invisibleBase()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/urlString.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/invisibleBase.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(qvariant_cast<QObject *>(o->property("n")), o.data());
+}
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> rootObject(component.create());
- QVERIFY(rootObject);
+void tst_QmlCppCodegen::invisibleListElementType()
+{
+ qmlRegisterType<InvisibleListElementType>("Invisible", 1, 0, "InvisibleListElement");
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/invisibleListElementType.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- QCOMPARE(qvariant_cast<QUrl>(rootObject->property("c")), QUrl(u"http://dddddd.com"_s));
- QCOMPARE(qvariant_cast<QUrl>(rootObject->property("d")), QUrl(u"http://aaaaaa.com"_s));
- QCOMPARE(qvariant_cast<QUrl>(rootObject->property("e")), QUrl(u"http://a112233.de"_s));
+ QObject *a = o->property("a").value<QObject *>();
+ QVERIFY(a);
+
+ const QVariant x = a->property("x");
+ QCOMPARE(x.metaType(), QMetaType::fromType<QQmlListReference>());
+ const QQmlListReference ref = x.value<QQmlListReference>();
+ QVERIFY(ref.isValid());
+ QCOMPARE(ref.size(), 0);
}
+void tst_QmlCppCodegen::invisibleSingleton()
+{
+ // We may have seen Style.qml as singleton before, which would make the assignment pass.
+ // So let's flush the type registry.
+ qmlClearTypeRegistrations();
-void tst_QmlCppCodegen::callContextPropertyLookupResult()
+ QQmlEngine engine;
+ const QUrl copy(u"qrc:/qt/qml/HiddenTestTypes/hidden/Main.qml"_s);
+ QQmlComponent c(&engine, copy);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "qrc:/qt/qml/HiddenTestTypes/hidden/Main.qml:4:5: "
+ "Unable to assign [undefined] to QColor");
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("c"), QVariant(QMetaType::fromName("QColor")));
+}
+
+void tst_QmlCppCodegen::invisibleTypes()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/callContextPropertyLookupResult.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/invisibleTypes.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QVERIFY(qvariant_cast<QQmlComponent *>(o->property("c")) != nullptr);
+ QObject *singleton = qvariant_cast<QObject *>(o->property("singleton"));
+ QVERIFY(singleton != nullptr);
+ QCOMPARE(singleton->metaObject()->className(), "SingletonModel");
+
+ QObject *attached = qvariant_cast<QObject *>(o->property("attached"));
+ QVERIFY(attached != nullptr);
+ QCOMPARE(attached->metaObject()->className(), "AttachedAttached");
+
+// TODO: This doesn't work in interpreted mode:
+// const QMetaObject *meta = qvariant_cast<const QMetaObject *>(o->property("metaobject"));
+// QVERIFY(meta != nullptr);
+// QCOMPARE(meta->className(), "DerivedFromInvisible");
}
-void tst_QmlCppCodegen::deadShoeSize()
+void tst_QmlCppCodegen::iteration()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/deadShoeSize.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/iteration.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/deadShoeSize.qml:5: Error: ouch");
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->property("shoeSize").toInt(), 0);
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->objectName(), "a345b345c345"_L1);
}
-void tst_QmlCppCodegen::listIndices()
+void tst_QmlCppCodegen::javaScriptArgument()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listIndices.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/javaScriptArgument.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ QVERIFY(!o.isNull());
- QQmlListReference list(o.data(), "items");
- QCOMPARE(list.count(), 3);
- for (int i = 0; i < 3; ++i)
- QCOMPARE(list.at(i), o.data());
- QCOMPARE(o->property("numItems").toInt(), 3);
- QCOMPARE(qvariant_cast<QObject *>(o->property("fractional")), nullptr);
- QCOMPARE(qvariant_cast<QObject *>(o->property("negativeZero")), o.data());
- QCOMPARE(qvariant_cast<QObject *>(o->property("infinity")), nullptr);
- QCOMPARE(qvariant_cast<QObject *>(o->property("nan")), nullptr);
+ QCOMPARE(o->property("a").toDouble(), 4.0);
+ QCOMPARE(o->property("b").toDouble(), 9.0);
+ QCOMPARE(o->property("c").toString(), u"5t-1"_s);
+ QCOMPARE(o->property("d").toString(), u"9"_s);
+ QCOMPARE(o->property("e").toString(), u"10"_s);
+ QCOMPARE(o->property("f").toString(), u"-10"_s);
+
+ const QStringList scales {
+ "0 ", "1 ", "10 ", "100 ", "1000 ", "9.77k", "97.7k", "977k", "9.54M", "95.4M", "954M",
+ "9.31G", "93.1G", "931G", "9.09T", "-1 ", "-10 ", "-100 ", "-1000 ", "-9.77k", "-97.7k",
+ "-977k", "-9.54M", "-95.4M", "-954M", "-9.31G", "-93.1G", "-931G", "-9.09T"
+ };
+
+ QCOMPARE(o->property("scales").value<QStringList>(), scales);
+
+ double thing = 12.0;
+ QString result;
+ QMetaObject::invokeMethod(
+ o.data(), "forwardArg", Q_RETURN_ARG(QString, result), Q_ARG(double, thing));
+ QCOMPARE(result, u"12 ");
}
-static const double numbers[] = {
- qQNaN(), -qInf(),
- std::numeric_limits<double>::min(),
- std::numeric_limits<float>::min(),
- std::numeric_limits<qint32>::min(),
- -1000.2, -100, -2, -1.333, -1, -0.84, -0.5,
+void tst_QmlCppCodegen::jsArrayMethods()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/jsArrayMethods.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- // -0 and 0 are not different on the QML side. Therefore, don't keep them adjacent.
- // Otherwise the bindings won't get re-evaluated.
- std::copysign(0.0, -1), 1, 0.0,
+ QQmlComponent untyped(&engine, QUrl(u"qrc:/qt/qml/TestTypes/jsArrayMethodsUntyped.qml"_s));
+ QVERIFY2(untyped.isReady(), qPrintable(untyped.errorString()));
+ QScopedPointer<QObject> check(untyped.create());
+ QVERIFY(!check.isNull());
- 0.5, 0.77, 1.4545, 2, 199, 2002.13,
- std::numeric_limits<qint32>::max(),
- std::numeric_limits<quint32>::max(),
- std::numeric_limits<float>::max(),
- std::numeric_limits<double>::max(),
- qInf()
-};
+ check->setProperty("l1", object->property("l1"));
+ check->setProperty("l2", object->property("l2"));
+ check->setProperty("l3", object->property("l3"));
+
+ QCOMPARE(object->property("listPropertyToString"), object->property("jsArrayToString"));
+ QCOMPARE(object->property("listPropertyToString"), check->property("jsArrayToString"));
+
+ QCOMPARE(object->property("listPropertyIncludes"), object->property("jsArrayIncludes"));
+ QVERIFY(object->property("listPropertyIncludes").toBool());
+
+ QCOMPARE(object->property("listPropertyJoin"), object->property("jsArrayJoin"));
+ QCOMPARE(object->property("listPropertyJoin"), check->property("jsArrayJoin"));
+ QVERIFY(object->property("listPropertyJoin").toString().contains(QStringLiteral("klaus")));
+
+ QCOMPARE(object->property("listPropertyIndexOf"), object->property("jsArrayIndexOf"));
+ QCOMPARE(object->property("listPropertyIndexOf").toInt(), 1);
+
+ QCOMPARE(object->property("listPropertyLastIndexOf"), object->property("jsArrayLastIndexOf"));
+ QCOMPARE(object->property("listPropertyLastIndexOf").toInt(), 5);
+}
+
+void tst_QmlCppCodegen::jsArrayMethodsWithParams()
+{
+ QFETCH(int, i);
+ QFETCH(int, j);
+ QFETCH(int, k);
+ QQmlEngine engine;
+ QQmlComponent component
+ (&engine, QUrl(u"qrc:/qt/qml/TestTypes/jsArrayMethodsWithParams.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QQmlComponent untyped(
+ &engine, QUrl(u"qrc:/qt/qml/TestTypes/jsArrayMethodsWithParamsUntyped.qml"_s));
+ QVERIFY2(untyped.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.createWithInitialProperties({
+ {QStringLiteral("i"), i},
+ {QStringLiteral("j"), j},
+ {QStringLiteral("k"), k}
+ }));
+ QVERIFY(!object.isNull());
+ QScopedPointer<QObject> check(untyped.createWithInitialProperties({
+ {QStringLiteral("i"), i},
+ {QStringLiteral("j"), j},
+ {QStringLiteral("k"), k}
+ }));
+ QVERIFY(!check.isNull());
+ check->setProperty("l1", object->property("l1"));
+ check->setProperty("l2", object->property("l2"));
+ check->setProperty("l3", object->property("l3"));
+
+ listsEqual(object.data(), object.data(), "Slice");
+ listsEqual(object.data(), check.data(), "Slice");
+ QCOMPARE(object->property("listPropertyIndexOf"), object->property("jsArrayIndexOf"));
+ QCOMPARE(object->property("listPropertyIndexOf"), check->property("jsArrayIndexOf"));
+ QCOMPARE(object->property("listPropertyLastIndexOf"), object->property("jsArrayLastIndexOf"));
+ QCOMPARE(object->property("listPropertyLastIndexOf"), check->property("jsArrayLastIndexOf"));
+}
+
+void tst_QmlCppCodegen::jsArrayMethodsWithParams_data()
+{
+ QTest::addColumn<int>("i");
+ QTest::addColumn<int>("j");
+ QTest::addColumn<int>("k");
+
+ const int indices[] = {
+ std::numeric_limits<int>::min(),
+ -10, -3, -2, -1, 0, 1, 2, 3, 10,
+ std::numeric_limits<int>::max(),
+ };
+
+ // We cannot test the full cross product. So, take a random sample instead.
+ const qsizetype numIndices = sizeof(indices) / sizeof(int);
+ qsizetype seed = QRandomGenerator::global()->generate();
+ const int numSamples = 4;
+ for (int i = 0; i < numSamples; ++i) {
+ seed = qHash(i, seed);
+ const int vi = indices[qAbs(seed) % numIndices];
+ for (int j = 0; j < numSamples; ++j) {
+ seed = qHash(j, seed);
+ const int vj = indices[qAbs(seed) % numIndices];
+ for (int k = 0; k < numSamples; ++k) {
+ seed = qHash(k, seed);
+ const int vk = indices[qAbs(seed) % numIndices];
+ const QString tag = QLatin1String("%1/%2/%3").arg(
+ QString::number(vi), QString::number(vj), QString::number(vk));
+ QTest::newRow(qPrintable(tag)) << vi << vj << vk;
+
+ // output all the tags so that we can find out
+ // what combination caused a test to hang.
+ qDebug().noquote() << "scheduling" << tag;
+ }
+ }
+ }
+}
+
+void tst_QmlCppCodegen::jsImport()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/jsimport.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("value").toInt(), 42);
+}
void tst_QmlCppCodegen::jsMathObject()
{
@@ -1707,708 +2876,1247 @@ void tst_QmlCppCodegen::jsMathObject()
qDebug() << name << "failed.";
}
-void tst_QmlCppCodegen::intEnumCompare()
+void tst_QmlCppCodegen::jsmoduleImport()
{
QQmlEngine engine;
- {
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/intEnumCompare.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->property("a").toBool(), true);
- QCOMPARE(o->property("b").toBool(), false);
- QCOMPARE(o->property("c").toBool(), true);
- QCOMPARE(o->property("d").toBool(), false);
- }
-
- {
- // We cannot use Qt.red in QML because it's lower case.
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumInvalid.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->property("c").toBool(), true);
- QCOMPARE(o->property("d").toBool(), false);
- }
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/jsmoduleimport.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("ok").toBool(), true);
+ QVariant okFunc = object->property("okFunc");
+ QCOMPARE(okFunc.metaType(), QMetaType::fromType<QJSValue>());
+ QJSValue val = engine.toScriptValue(okFunc);
+ QJSValue result = val.call();
+ QVERIFY(result.isBool());
+ QVERIFY(result.toBool());
}
-void tst_QmlCppCodegen::attachedSelf()
+void tst_QmlCppCodegen::lengthAccessArraySequenceCompat()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/SelectionRectangle.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ArraySequenceLengthInterop.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("length").toInt(), 100);
+}
- QObject *handle = qvariant_cast<QObject *>(o->property("aa"));
- QVERIFY(handle);
- QVERIFY(qvariant_cast<QObject *>(handle->property("rect")) != nullptr);
+void tst_QmlCppCodegen::letAndConst()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/letAndConst.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), u"ab"_s);
}
-void tst_QmlCppCodegen::functionReturningVoid()
+void tst_QmlCppCodegen::listAsArgument()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/functionReturningVoid.qml"_s));
+
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listAsArgument.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ QCOMPARE(o->property("i").toInt(), 4);
+ QCOMPARE(o->property("j").toInt(), 2);
+ QCOMPARE(o->property("i1").toInt(), 2);
+ QCOMPARE(o->property("i2").toInt(), 4);
+ QCOMPARE(o->property("d").value<QObject *>()->objectName(), u"this one"_s);
- // It should be able to call the methods and wrap the void values into invalid QVariants,
- // without crashing.
- QVERIFY(o->metaObject()->indexOfProperty("aa") >= 0);
- QVERIFY(o->metaObject()->indexOfProperty("bb") >= 0);
- QVERIFY(!o->property("aa").isValid());
- QVERIFY(!o->property("bb").isValid());
+ int singleInt = 0;
+ QList<int> moreInts;
+ QMetaObject::invokeMethod(o.data(), "returnInts1", Q_RETURN_ARG(QList<int>, moreInts));
+ QCOMPARE(moreInts, QList<int>({5, 4, 3, 2, 1}));
+ QMetaObject::invokeMethod(o.data(), "selectSecondInt", Q_RETURN_ARG(int, singleInt), Q_ARG(QList<int>, moreInts));
+ QCOMPARE(singleInt, 4);
}
-void tst_QmlCppCodegen::functionCallOnNamespaced()
+void tst_QmlCppCodegen::listConversion()
{
- QQmlEngine engine;
- {
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/themergood.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->property("i").toInt(), 12);
- }
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/listConversion.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- {
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/themerbad.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->property("r"), QVariant::fromValue(QRectF(5.0, 10.0, 1.0, 1.0)));
+ QQmlListProperty<QObject> list = o->property("o").value<QQmlListProperty<QObject>>();
+ QCOMPARE(list.count(&list), 3);
+ for (int i = 0; i < 3; ++i) {
+ QObject *entry = list.at(&list, i);
+ Person *person = qobject_cast<Person *>(entry);
+ QVERIFY(person);
+ QCOMPARE(person->name(), u"Horst %1"_s.arg(i + 1));
}
+
+ QStringList strings = o->property("s").value<QStringList>();
+ QCOMPARE(strings, QStringList({u"Horst 1"_s, u"Horst 2"_s, u"Horst 3"_s}));
+
+ QVariantList vars = o->property("v").toList();
+ QCOMPARE(vars, QVariantList({
+ QString(),
+ QVariant::fromValue<qsizetype>(3),
+ QVariant::fromValue<Person *>(nullptr)
+ }));
}
-void tst_QmlCppCodegen::flushBeforeCapture()
+void tst_QmlCppCodegen::listIndices()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/noBindingLoop.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listIndices.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(o);
- QCOMPARE(o->property("deviation").toDouble(), 9.0 / 3.3333);
- QCOMPARE(o->property("samples").toInt(), 16);
- QCOMPARE(o->property("radius").toDouble(), 8.0);
+ QQmlListReference list(o.data(), "items");
+ QCOMPARE(list.count(), 3);
+ for (int i = 0; i < 3; ++i)
+ QCOMPARE(list.at(i), o.data());
+ QCOMPARE(o->property("numItems").toInt(), 3);
+ QCOMPARE(qvariant_cast<QObject *>(o->property("fractional")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(o->property("negativeZero")), o.data());
+ QCOMPARE(qvariant_cast<QObject *>(o->property("infinity")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(o->property("nan")), nullptr);
}
-void tst_QmlCppCodegen::unknownAttached()
+void tst_QmlCppCodegen::listLength()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unknownAttached.qml"_s));
- QVERIFY(c.isError());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listlength.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("l").toInt(), 2);
}
-void tst_QmlCppCodegen::variantlist()
+void tst_QmlCppCodegen::listOfInvisible()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/variantlist.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
-
- const QVariantList things = qvariant_cast<QVariantList>(o->property("things"));
- QCOMPARE(things.size(), 2);
- QCOMPARE(things[0].toString(), u"thing"_s);
- QCOMPARE(things[1].toInt(), 30);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listOfInvisible.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("width").toDouble(), 27.0);
}
-void tst_QmlCppCodegen::popContextAfterRet()
+void tst_QmlCppCodegen::listPropertyAsModel()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/popContextAfterRet.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listPropertyAsModel.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->objectName(), QString());
- o->setProperty("stackViewDepth", 1);
- QCOMPARE(o->objectName(), u"backgroundImage"_s);
- o->setProperty("stackViewDepth", 2);
- QCOMPARE(o->objectName(), u"backgroundBlur"_s);
- o->setProperty("stackViewDepth", 1);
- QCOMPARE(o->objectName(), u"backgroundImage"_s);
+ QQmlListReference children(o.data(), "children");
+ QCOMPARE(children.count(), 5);
}
-void tst_QmlCppCodegen::revisions()
+void tst_QmlCppCodegen::listToString()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/revisions.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listToString.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(QtDebugMsg, "[one,two]");
+ QTest::ignoreMessage(QtDebugMsg, "one,two");
+ QTest::ignoreMessage(QtDebugMsg, "[1,2]");
+ QTest::ignoreMessage(QtDebugMsg, "1,2");
+ QTest::ignoreMessage(
+ QtDebugMsg,
+ QRegularExpression("\\[QObject_QML_[0-9]+\\(0x[0-9a-f]+\\),"
+ "QObject_QML_[0-9]+\\(0x[0-9a-f]+\\)\\]"));
+ QTest::ignoreMessage(
+ QtDebugMsg,
+ QRegularExpression("QObject_QML_[0-9]+\\(0x[0-9a-f]+\\),"
+ "QObject_QML_[0-9]+\\(0x[0-9a-f]+\\)"));
+
+ QTest::ignoreMessage(QtDebugMsg, "[a,b]");
+
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+}
- QCOMPARE(o->property("delayed").toBool(), true);
- QCOMPARE(o->property("gotten").toInt(), 5);
+void tst_QmlCppCodegen::lotsOfRegisters()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/page.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ const auto compare = [&]() {
+ const qreal implicitBackgroundWidth = object->property("implicitBackgroundWidth").toDouble();
+ const qreal leftInset = object->property("leftInset").toDouble();
+ const qreal rightInset = object->property("rightInset").toDouble();
+ const qreal contentWidth = object->property("contentWidth").toDouble();
+ const qreal leftPadding = object->property("leftPadding").toDouble();
+ const qreal rightPadding = object->property("rightPadding").toDouble();
+ const qreal implicitFooterWidth = object->property("implicitFooterWidth").toDouble();
+ const qreal implicitHeaderWidth = object->property("implicitHeaderWidth").toDouble();
+
+ const qreal implicitWidth = object->property("implicitWidth").toDouble();
+ QCOMPARE(implicitWidth, qMax(qMax(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding),
+ qMax(implicitHeaderWidth, implicitFooterWidth)));
+ };
+
+ compare();
+
+ const QList<const char *> props = {
+ "leftInset", "rightInset", "contentWidth", "leftPadding", "rightPadding"
+ };
+
+ for (int i = 0; i < 100; ++i) {
+ QVERIFY(object->setProperty(props[i % props.size()], (i * 17) % 512));
+ compare();
+ }
}
-void tst_QmlCppCodegen::invisibleBase()
+void tst_QmlCppCodegen::math()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/invisibleBase.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(qvariant_cast<QObject *>(o->property("n")), o.data());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/math.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("a").toInt(), 9);
+ QCOMPARE(object->property("b").toDouble(), 50.0 / 22.0);
+ QCOMPARE(object->property("c").toDouble(), std::atan(1.0) * 8.0);
}
-void tst_QmlCppCodegen::notEqualsInt()
+void tst_QmlCppCodegen::mathMinMax()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/notEqualsInt.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/mathMinMax.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ // Math.max()
+ QTest::ignoreMessage(QtDebugMsg, "1");
+ QTest::ignoreMessage(QtDebugMsg, "2");
+ QTest::ignoreMessage(QtDebugMsg, "2");
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "1");
+ QTest::ignoreMessage(QtDebugMsg, "2");
+ QTest::ignoreMessage(QtDebugMsg, "2");
+ QTest::ignoreMessage(QtDebugMsg, "9");
+
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "0.002");
+ QTest::ignoreMessage(QtDebugMsg, "5.4");
+ QTest::ignoreMessage(QtDebugMsg, "NaN");
+ QTest::ignoreMessage(QtDebugMsg, "Infinity");
+ QTest::ignoreMessage(QtDebugMsg, "1");
+ QTest::ignoreMessage(QtDebugMsg, "0.08");
+ QTest::ignoreMessage(QtDebugMsg, "Infinity");
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "NaN");
+
+ // Math.min()
+ QTest::ignoreMessage(QtDebugMsg, "1");
+ QTest::ignoreMessage(QtDebugMsg, "1");
+ QTest::ignoreMessage(QtDebugMsg, "1");
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "-2");
+ QTest::ignoreMessage(QtDebugMsg, "-2");
+ QTest::ignoreMessage(QtDebugMsg, "0");
+
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "-0.001");
+ QTest::ignoreMessage(QtDebugMsg, "0.002");
+ QTest::ignoreMessage(QtDebugMsg, "NaN");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+ QTest::ignoreMessage(QtDebugMsg, "-8");
+ QTest::ignoreMessage(QtDebugMsg, "NaN");
+
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QObject *t = qmlContext(o.data())->objectForName(u"t"_s);
- QVERIFY(t);
- QCOMPARE(t->property("text").toString(), u"Foo"_s);
- QMetaObject::invokeMethod(o.data(), "foo");
- QCOMPARE(t->property("text").toString(), u"Bar"_s);
+ QVERIFY(!o.isNull());
}
-void tst_QmlCppCodegen::infinities()
+void tst_QmlCppCodegen::mathOperations()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/infinities.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/mathOperations.qml"_s));
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 QMetaObject *metaObject = o->metaObject();
- const double positiveZero = o->property("positiveZero").toDouble();
- QCOMPARE(positiveZero, 0.0);
- QVERIFY(!std::signbit(positiveZero));
+ char t1;
+ char t2;
+ QString name;
+ const auto guard = qScopeGuard([&]() {
+ if (QTest::currentTestFailed()) {
+ qDebug() << t1 << t2 << name << "failed on:";
+ qDebug() << "doubles" << o->property("a").toDouble() << o->property("b").toDouble();
+ qDebug() << "integers" << o->property("ia").toInt() << o->property("ib").toInt();
+ qDebug() << "booleans" << o->property("ba").toBool() << o->property("bb").toBool();
+ }
+ });
- const double negativeZero = o->property("negativeZero").toDouble();
- QCOMPARE(negativeZero, -0.0);
- QVERIFY(std::signbit(negativeZero));
+ for (double a : numbers) {
+ for (double b : numbers) {
+ o->setProperty("a", a);
+ o->setProperty("b", b);
+ for (int i = 0, end = metaObject->propertyCount(); i != end; ++i) {
+ const QMetaProperty prop = metaObject->property(i);
+ const QByteArray propName = prop.name();
- QVERIFY(qIsNaN(o->property("naN").toDouble()));
+ if (propName.size() < 3 || propName == "objectName")
+ continue;
+
+ t1 = propName[0];
+ t2 = propName[1];
+ name = QString::fromUtf8(propName.mid(2));
+
+ double expected;
+
+ switch (t2) {
+ case 'd':
+ case '_':
+ switch (t1) {
+ case 'd':
+ expected = jsEval<double, double>(a, b, name, &engine);
+ break;
+ case 'i':
+ expected = jsEval<int, double>(a, b, name, &engine);
+ break;
+ case 'b':
+ expected = jsEval<bool, double>(a, b, name, &engine);
+ break;
+ }
+ break;
+ case 'i':
+ switch (t1) {
+ case 'd':
+ expected = jsEval<double, int>(a, b, name, &engine);
+ break;
+ case 'i':
+ expected = jsEval<int, int>(a, b, name, &engine);
+ break;
+ case 'b':
+ expected = jsEval<bool, int>(a, b, name, &engine);
+ break;
+ }
+ break;
+ case 'b':
+ switch (t1) {
+ case 'd':
+ expected = jsEval<double, bool>(a, b, name, &engine);
+ break;
+ case 'i':
+ expected = jsEval<int, bool>(a, b, name, &engine);
+ break;
+ case 'b':
+ expected = jsEval<bool, bool>(a, b, name, &engine);
+ break;
+ }
+ break;
+ }
+
+ const double result = prop.read(o.data()).toDouble();
+ QCOMPARE(result, expected);
+ }
+ }
+ }
}
-void tst_QmlCppCodegen::blockComments()
+void tst_QmlCppCodegen::mathStaticProperties()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/blockComments.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->property("implicitHeight").toDouble(), 8.0);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/mathStaticProperties.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ // Approximate values based on
+ // https://262.ecma-international.org/14.0/#sec-value-properties-of-the-math-object
+ QCOMPARE(object->property("e").toDouble(), 2.7182818284590452354);
+ QCOMPARE(object->property("ln10").toDouble(), 2.302585092994046);
+ QCOMPARE(object->property("ln2").toDouble(), 0.6931471805599453);
+ QCOMPARE(object->property("log10e").toDouble(), 0.4342944819032518);
+ QCOMPARE(object->property("log2e").toDouble(), 1.4426950408889634);
+ QCOMPARE(object->property("pi").toDouble(), 3.1415926535897932);
+ QCOMPARE(object->property("sqrt1_2").toDouble(), 0.7071067811865476);
+ QCOMPARE(object->property("sqrt2").toDouble(), 1.4142135623730951);
}
-void tst_QmlCppCodegen::functionLookup()
+void tst_QmlCppCodegen::mergedObjectReadWrite()
+{
+ QQmlEngine e;
+ {
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/mergedObjectRead.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtDebugMsg, "null");
+ QTest::ignoreMessage(
+ QtWarningMsg, QRegularExpression("TypeError: Cannot read property 'x' of null"));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ }
+
+ {
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/mergedObjectWrite.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ QRegularExpression(
+ "TypeError: Value is null and could not be converted to an object"));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ }
+}
+
+void tst_QmlCppCodegen::methodOnListLookup()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/functionLookup.qml"_s));
- 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"));
+ const QUrl url(u"qrc:/qt/qml/TestTypes/methodOnListLookup.qml"_s);
+ QQmlComponent component(&engine, url);
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->objectName(), u"no one");
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString()
+ + ":14: TypeError: Cannot call method 'getName' of undefined"_L1));
+ QMetaObject::invokeMethod(o.data(), "boom");
}
-void tst_QmlCppCodegen::objectInVar()
+void tst_QmlCppCodegen::methods()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/objectInVar.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(qvariant_cast<QObject*>(o->property("thing")), o.data());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/methods.qml"_s));
+ QVERIFY(component.isReady());
- bool result = false;
- QVERIFY(QMetaObject::invokeMethod(o.data(), "doThing", Q_RETURN_ARG(bool, result)));
- QVERIFY(result);
+ QTest::ignoreMessage(QtDebugMsg, "The Bar");
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(u"TypeError: .* is not a function"_s));
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj);
+ BirthdayParty *party(qobject_cast<BirthdayParty *>(obj.data()));
- o->setProperty("thing", QVariant::fromValue<std::nullptr_t>(nullptr));
- QVERIFY(QMetaObject::invokeMethod(o.data(), "doThing", Q_RETURN_ARG(bool, result)));
- QVERIFY(!result);
+ QVERIFY(party && party->host());
+ QCOMPARE(party->guestCount(), 5);
+
+ bool foundGreen = false;
+ bool foundFoo = false;
+ for (int ii = 0; ii < party->guestCount(); ++ii) {
+ if (party->guest(ii)->name() == u"William Green"_s)
+ foundGreen = true;
+ if (party->guest(ii)->name() == u"The Foo"_s)
+ foundFoo = true;
+ }
+
+ QVERIFY(foundGreen);
+ QVERIFY(foundFoo);
+
+ QCOMPARE(obj->property("n1").toString(), u"onGurk"_s);
+ QCOMPARE(obj->property("n2").toString(), u"onSemmeln"_s);
+ QCOMPARE(obj->property("n3"), QVariant());
+
+ {
+ QVariant ret;
+ obj->metaObject()->invokeMethod(obj.data(), "retrieveVar", Q_RETURN_ARG(QVariant, ret));
+ QCOMPARE(ret.typeId(), QMetaType::QString);
+ QCOMPARE(ret.toString(), u"Jack Smith"_s);
+ }
+
+ {
+ QString ret;
+ obj->metaObject()->invokeMethod(obj.data(), "retrieveString", Q_RETURN_ARG(QString, ret));
+ QCOMPARE(ret, u"Jack Smith"_s);
+ }
+
+ QCOMPARE(party->host()->shoeSize(), 12);
+ obj->metaObject()->invokeMethod(obj.data(), "storeElement");
+ QCOMPARE(party->host()->shoeSize(), 13);
+ QJSManagedValue v = engine.toManagedValue(obj->property("dresses"));
+ QVERIFY(v.isArray());
+
+ QJSManagedValue inner(v.property(2), &engine);
+ QVERIFY(inner.isArray());
+ QCOMPARE(inner.property(0).toInt(), 1);
+ QCOMPARE(inner.property(1).toInt(), 2);
+ QCOMPARE(inner.property(2).toInt(), 3);
+
+ QCOMPARE(obj->property("enumValue").toInt(), 2);
}
-void tst_QmlCppCodegen::functionTakingVar()
+void tst_QmlCppCodegen::modulePrefix()
{
QQmlEngine engine;
- const QUrl document(u"qrc:/qt/qml/TestTypes/functionTakingVar.qml"_s);
- QQmlComponent c(&engine, document);
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/modulePrefix.qml"_s));
- QVERIFY(!o->property("c").isValid());
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
- 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(rootObject->property("foo").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
+ QCOMPARE(rootObject->property("bar").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
+ QCOMPARE(rootObject->property("baz").toString(), QStringLiteral("ItIsTheSingleton"));
+}
- QCOMPARE(o->property("c"), QVariant::fromValue<int>(11));
+void tst_QmlCppCodegen::multiDirectory_data()
+{
+ QTest::addColumn<QUrl>("url");
+ QTest::addRow("from qt_add_qml_module")
+ << QUrl(u"qrc:/qt/qml/TestTypes/extra/extra.qml"_s);
+#ifndef VERY_OLD_CMAKE
+ QTest::addRow("from qt_target_qml_sources")
+ << QUrl(u"qrc:/qt/qml/TestTypes/extra2/extra.qml"_s);
+#endif
}
-void tst_QmlCppCodegen::testIsnan()
+void tst_QmlCppCodegen::multiDirectory()
{
+ QFETCH(QUrl, url);
QQmlEngine engine;
- const QUrl document(u"qrc:/qt/qml/TestTypes/isnan.qml"_s);
- QQmlComponent c(&engine, document);
+ QQmlComponent component(&engine, url);
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
+
+ QCOMPARE(rootObject->property("r").value<QRectF>(), QRectF(4, 6, 8, 10));
+}
+
+void tst_QmlCppCodegen::multiForeign()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/multiforeign.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), u"not here and not there"_s);
+}
- QCOMPARE(o->property("good").toDouble(), 10.1);
- QVERIFY(qIsNaN(o->property("bad").toDouble()));
+void tst_QmlCppCodegen::multiLookup()
+{
+ // Multiple lookups of singletons (Qt in this case) don't clash with one another.
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/immediateQuit.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
- const QVariant a = o->property("a");
- QCOMPARE(a.metaType(), QMetaType::fromType<bool>());
- QVERIFY(!a.toBool());
+ const QByteArray message = QByteArray("End: ") + arg1();
+ QTest::ignoreMessage(QtDebugMsg, message.constData());
- const QVariant b = o->property("b");
- QCOMPARE(b.metaType(), QMetaType::fromType<bool>());
- QVERIFY(b.toBool());
+ QSignalSpy quitSpy(&engine, &QQmlEngine::quit);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(quitSpy.size(), 1);
}
-void tst_QmlCppCodegen::fallbackLookups()
+void tst_QmlCppCodegen::multipleCtors()
{
QQmlEngine engine;
- const QUrl document(u"qrc:/qt/qml/TestTypes/fallbacklookups.qml"_s);
- QQmlComponent c(&engine, document);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/multipleCtors.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("wr").value<ValueTypeWithLength>().length(), 3);
+ QCOMPARE(o->property("wp").value<ValueTypeWithLength>().length(), 11);
+ QCOMPARE(o->property("wi").value<ValueTypeWithLength>().length(), 17);
+}
- QCOMPARE(o->objectName(), QString());
- int result = 0;
+void tst_QmlCppCodegen::namespaceWithEnum()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/namespaceWithEnum.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("i").toInt(), 2);
+}
- QMetaObject::invokeMethod(o.data(), "withContext", Q_RETURN_ARG(int, result));
- QCOMPARE(result, 16);
- QCOMPARE(o->objectName(), QStringLiteral("aa93"));
+void tst_QmlCppCodegen::noQQmlData()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/noQQmlData.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QMetaObject::invokeMethod(o.data(), "withId", Q_RETURN_ARG(int, result));
- QCOMPARE(result, 17);
- QCOMPARE(o->objectName(), QStringLiteral("bb94"));
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/noQQmlData.qml:7: TypeError: "
+ "Cannot read property 'name' of null");
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
- QObject *singleton = nullptr;
- QMetaObject::invokeMethod(o.data(), "getSingleton", Q_RETURN_ARG(QObject*, singleton));
- QVERIFY(singleton);
+ BirthdayParty *party = qobject_cast<BirthdayParty *>(root.data());
+ QVERIFY(party != nullptr);
- QMetaObject::invokeMethod(o.data(), "withSingleton", Q_RETURN_ARG(int, result));
- QCOMPARE(result, 18);
- QCOMPARE(singleton->objectName(), QStringLiteral("cc95"));
+ QCOMPARE(party->host(), nullptr);
+ QCOMPARE(party->property("n").toString(), QString());
- QMetaObject::invokeMethod(o.data(), "withProperty", Q_RETURN_ARG(int, result));
- QCOMPARE(result, 19);
- QCOMPARE(singleton->objectName(), QStringLiteral("dd96"));
+ Person *host1 = new Person(party);
+ party->setHost(host1);
+ QCOMPARE(party->property("n").toString(), u"Bart in da house!"_s);
+ host1->setName(u"Marge"_s);
+ QCOMPARE(party->property("n").toString(), u"Marge in da house!"_s);
+
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/noQQmlData.qml:7: TypeError: "
+ "Cannot read property 'name' of null");
+
+ // Doesn't crash
+ party->setHost(nullptr);
+
+ // Lookups are initialized now, and we introduce an object without QQmlData
+ Person *host2 = new Person(party);
+ party->setHost(host2);
+ QCOMPARE(party->property("n").toString(), u"Bart in da house!"_s);
+ host2->setName(u"Homer"_s);
+ QCOMPARE(party->property("n").toString(), u"Homer in da house!"_s);
+
+ QMetaObject::invokeMethod(party, "burn");
+ engine.collectGarbage();
+
+ // Does not crash
+ party->setProperty("inDaHouse", u" burns!"_s);
+
+ // Mr Burns may or may not burn, depending on whether we use lookups.
+ // If using lookups, the binding is aborted when we find the isQueuedForDeletion flag.
+ // If reading the property directly, we don't have to care about it.
+ QVERIFY(party->property("n").toString().startsWith(u"Mr Burns"_s));
}
-void tst_QmlCppCodegen::typedArray()
+void tst_QmlCppCodegen::nonNotifyable()
{
QQmlEngine engine;
- const QUrl document(u"qrc:/qt/qml/TestTypes/typedArray.qml"_s);
- QQmlComponent c(&engine, document);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nonNotifyable.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QCOMPARE(qvariant_cast<QDateTime>(object->property("dayz")),
+ QDateTime(QDate(2121, 1, 12), QTime()));
+ QCOMPARE(qvariant_cast<QDateTime>(object->property("oParty")),
+ QDateTime(QDate(2111, 12, 11), QTime()));
+}
+
+void tst_QmlCppCodegen::notEqualsInt()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/notEqualsInt.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(o);
- QDateTime date;
- QVERIFY(qvariant_cast<QList<int>>(o->property("values2")).isEmpty());
- QCOMPARE(qvariant_cast<QList<int>>(o->property("values3")),
- QList<int>({1, 2, 3, 4}));
- QCOMPARE(qvariant_cast<QList<QDateTime>>(o->property("values4")),
- QList<QDateTime>({date, date, date}));
- QCOMPARE(qvariant_cast<QList<double>>(o->property("values5")),
- QList<double>({1, 2, 3.4, 30, 0, 0}));
- date = QDateTime::currentDateTime();
- o->setProperty("aDate", date);
- QCOMPARE(qvariant_cast<QList<QDateTime>>(o->property("values4")),
- QList<QDateTime>({date, date, date}));
+ QObject *t = qmlContext(o.data())->objectForName(u"t"_s);
+ QVERIFY(t);
+ QCOMPARE(t->property("text").toString(), u"Foo"_s);
+ QMetaObject::invokeMethod(o.data(), "foo");
+ QCOMPARE(t->property("text").toString(), u"Bar"_s);
+}
- QQmlListProperty<QObject> values6
- = qvariant_cast<QQmlListProperty<QObject>>(o->property("values6"));
- QCOMPARE(values6.count(&values6), 3);
- for (int i = 0; i < 3; ++i)
- QCOMPARE(values6.at(&values6, i), o.data());
+void tst_QmlCppCodegen::notNotString()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/notNotString.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
- QCOMPARE(o->property("inIntList").toInt(), 2);
- QCOMPARE(qvariant_cast<QDateTime>(o->property("inDateList")), date);
- QCOMPARE(o->property("inRealList").toDouble(), 30.0);
- QCOMPARE(o->property("inCharList").toString(), QStringLiteral("f"));
+ QCOMPARE(o->property("notNotString").value<bool>(), false);
+ o->setObjectName(u"a"_s);
+ QCOMPARE(o->property("notNotString").value<bool>(), true);
+}
- const QMetaObject *metaObject = o->metaObject();
- QMetaMethod method = metaObject->method(metaObject->indexOfMethod("stringAt10(QString)"));
- QVERIFY(method.isValid());
+void tst_QmlCppCodegen::nullAccess()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nullAccess.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
- // If LoadElement threw an exception the function would certainly return neither 10 nor 20.
- int result = 0;
- method.invoke(
- o.data(), Q_RETURN_ARG(int, result), Q_ARG(QString, QStringLiteral("a")));
- QCOMPARE(result, 10);
- method.invoke(
- o.data(), Q_RETURN_ARG(int, result), Q_ARG(QString, QStringLiteral("aaaaaaaaaaa")));
- QCOMPARE(result, 20);
+ QTest::ignoreMessage(QtWarningMsg,
+ "qrc:/qt/qml/TestTypes/nullAccess.qml:4:5: TypeError: "
+ "Cannot read property 'width' of null");
+ QTest::ignoreMessage(QtWarningMsg,
+ "qrc:/qt/qml/TestTypes/nullAccess.qml:5:5: TypeError: "
+ "Cannot read property 'height' of null");
+ QTest::ignoreMessage(QtWarningMsg,
+ "qrc:/qt/qml/TestTypes/nullAccess.qml:6: TypeError: Value is null and "
+ "could not be converted to an object");
+ QScopedPointer<QObject> object(component.create());
+
+ QCOMPARE(object->property("width").toDouble(), 0.0);
+ QCOMPARE(object->property("height").toDouble(), 0.0);
}
-void tst_QmlCppCodegen::prefixedType()
+void tst_QmlCppCodegen::nullAccessInsideSignalHandler()
{
QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nullAccessInsideSignalHandler.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QTest::ignoreMessage(QtWarningMsg,
+ "qrc:/qt/qml/TestTypes/nullAccessInsideSignalHandler.qml:15: ReferenceError: "
+ "text is not defined");
+ QScopedPointer<QObject> object(component.create());
+ QSignalSpy spy(object.data(), SIGNAL(say_hello()));
+ QTRY_VERIFY(spy.size() > 0);
+}
- // We need to add an import path here because we cannot namespace the implicit import.
- // The implicit import is what we use for all the other tests, even if we explicitly
- // import TestTypes. That is because the TestTypes module is in a subdirectory "data".
- engine.addImportPath(u":/"_s);
- const QUrl document(u"qrc:/qt/qml/TestTypes/prefixedMetaType.qml"_s);
- QQmlComponent c(&engine, document);
+void tst_QmlCppCodegen::nullComparison()
+{
+ QQmlEngine engine;
+
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nullComparison.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ QVERIFY(!o.isNull());
- QCOMPARE(o->property("state").toInt(), 2);
- QVERIFY(qvariant_cast<QObject *>(o->property("a")) != nullptr);
- QVERIFY(qvariant_cast<QObject *>(o->property("b")) != nullptr);
- QVERIFY(qvariant_cast<QObject *>(o->property("c")) == nullptr);
+ QCOMPARE(o->property("v").toInt(), 1);
+ QCOMPARE(o->property("w").toInt(), 3);
+ QCOMPARE(o->property("x").toInt(), 1);
+ QCOMPARE(o->property("y").toInt(), 5);
+ QCOMPARE(o->property("z").toInt(), 18);
+}
- QVERIFY(qvariant_cast<QObject *>(o->property("d")) != nullptr);
- QVERIFY(qvariant_cast<QObject *>(o->property("e")) != nullptr);
- QVERIFY(qvariant_cast<QObject *>(o->property("f")) == nullptr);
+void tst_QmlCppCodegen::nullishCoalescing_data()
+{
+ QTest::addColumn<QString>("propertyName");
+ QTest::addColumn<QVariant>("expected");
- QVERIFY(qvariant_cast<QObject *>(o->property("g")) != nullptr);
- QVERIFY(qvariant_cast<QObject *>(o->property("h")) != nullptr);
+ const auto undefinedValue = QVariant();
+ const auto nullValue = QVariant::fromMetaType(QMetaType::fromType<std::nullptr_t>(), nullptr);
- QCOMPARE(o->property("countG").toInt(), 11);
- QCOMPARE(o->property("countH").toInt(), 11);
-}
+ QTest::addRow("trivial-good-int") << "p1" << QVariant(5);
+ QTest::addRow("trivial-good-string") << "p2" << QVariant("6");
-void tst_QmlCppCodegen::evadingAmbiguity()
-{
- QQmlEngine engine;
+ QTest::addRow("trivial-bad-undefined-undefined") << "p3" << undefinedValue;
+ QTest::addRow("trivial-bad-undefined-null") << "p4" << nullValue;
+ QTest::addRow("trivial-bad-undefined-int") << "p5" << QVariant(-1);
+ QTest::addRow("trivial-bad-undefined-string") << "p6" << QVariant("-1");
- // We need to add an import path here because we cannot namespace the implicit import.
- // The implicit import is what we use for all the other tests, even if we explicitly
- // import TestTypes. That is because the TestTypes module is in a subdirectory "data".
- engine.addImportPath(u":/"_s);
+ QTest::addRow("trivial-bad-null-undefined") << "p7" << undefinedValue;
+ QTest::addRow("trivial-bad-null-null") << "p8" << nullValue;
+ QTest::addRow("trivial-bad-null-int") << "p9" << QVariant(-1);
+ QTest::addRow("trivial-bad-null-string") << "p10" << QVariant("-1");
- QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ambiguous1/Ambiguous.qml"_s));
- QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
- QScopedPointer<QObject> o1(c1.create());
- QCOMPARE(o1->objectName(), QStringLiteral("Ambiguous"));
- QCOMPARE(o1->property("i").toString(), QStringLiteral("Ambiguous1"));
+ QTest::addRow("enum1") << "p11" << QVariant(1);
- QQmlComponent c2(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ambiguous2/Ambiguous.qml"_s));
- QVERIFY2(c2.isReady(), qPrintable(c2.errorString()));
- QScopedPointer<QObject> o2(c2.create());
- QCOMPARE(o2->objectName(), QStringLiteral("Ambiguous"));
- QCOMPARE(o2->property("i").toString(), QStringLiteral("Ambiguous2"));
+ QTest::addRow("multiple ?? int") << "p12" << QVariant(1);
+ QTest::addRow("multiple ?? string") << "p13" << QVariant("1");
+ QTest::addRow("multiple ?? mixed2") << "p14" << QVariant("2");
+ QTest::addRow("multiple ?? mixed3") << "p15" << QVariant(1);
+
+ QTest::addRow("optional + nullish bad") << "p16" << QVariant(-1);
+ QTest::addRow("optional + nullish good") << "p17" << QVariant(5);
}
-void tst_QmlCppCodegen::fromBoolValue()
+void tst_QmlCppCodegen::nullishCoalescing()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/fromBoolValue.qml"_s));
+ const QUrl document(u"qrc:/qt/qml/TestTypes/nullishCoalescing.qml"_s);
+ QQmlComponent c(&engine, document);
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QCOMPARE(o->property("a").toBool(), true);
- o->setProperty("x", 100);
- QCOMPARE(o->property("a").toBool(), false);
-
- QCOMPARE(o->property("width").toInt(), 100);
- QCOMPARE(o->property("b").toBool(), false);
+ QVERIFY(o);
- QScopedPointer<QObject> parent(c.create());
- o->setProperty("parent", QVariant::fromValue(parent.data()));
- QCOMPARE(o->property("width").toInt(), 100);
- QCOMPARE(o->property("b").toBool(), false);
+ QFETCH(QString, propertyName);
+ QFETCH(QVariant, expected);
- o->setProperty("state", QVariant::fromValue(u"foo"_s));
- QCOMPARE(o->property("width").toInt(), 0);
- QCOMPARE(o->property("b").toBool(), false);
+ QVariant actual = o->property(propertyName.toLocal8Bit());
+ QCOMPARE(actual, expected);
}
-void tst_QmlCppCodegen::invisibleTypes()
+void tst_QmlCppCodegen::numbersInJsPrimitive()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/invisibleTypes.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/numbersInJsPrimitive.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- QObject *singleton = qvariant_cast<QObject *>(o->property("singleton"));
- QVERIFY(singleton != nullptr);
- QCOMPARE(singleton->metaObject()->className(), "SingletonModel");
+ const QList<qint64> zeroes
+ = {0, 0, 0, 0, 0, 0, 0, 0};
+ const QList<qint64> written
+ = {35, 36, 37, 38, 39, 40, 41, 42};
+ const QList<qint64> writtenNegative
+ = {-35, 220, -37, 65498, -39, 4294967256, -41, 4294967254};
+ const QList<QList<qint64>> writtenShuffled = {
+ { -36, 219, -38, 65497, -40, 4294967255, -42, 4294967260 },
+ { -37, 218, -39, 65496, -41, 4294967254, -36, 4294967259 },
+ { -38, 217, -40, 65495, -42, 4294967260, -37, 4294967258 },
+ { -39, 216, -41, 65494, -36, 4294967259, -38, 4294967257 },
+ { -40, 215, -42, 65500, -37, 4294967258, -39, 4294967256 },
+ { -41, 214, -36, 65499, -38, 4294967257, -40, 4294967255 },
+ { -42, 220, -37, 65498, -39, 4294967256, -41, 4294967254 },
+ { -36, 219, -38, 65497, -40, 4294967255, -42, 4294967260 },
+ };
- QObject *attached = qvariant_cast<QObject *>(o->property("attached"));
- QVERIFY(attached != nullptr);
- QCOMPARE(attached->metaObject()->className(), "AttachedAttached");
+ const QList<qint64> stored
+ = {50, 51, 1332, 1333, 1334, 1335, 1336, 1337};
+ const QList<qint64> storedNegative
+ = {-50, 205, -1332, 64203, -1334, 4294965961, -1336, 4294965959};
+ const QList<QList<qint64>> storedShuffled = {
+ { -51, 204, -1333, 64202, -1335, 4294965960, -1337, 4294967245 },
+ { -52, 203, -1334, 64201, -1336, 4294965959, -51, 4294967244 },
+ { -53, 202, -1335, 64200, -1337, 4294967245, -52, 4294967243 },
+ { -54, 201, -1336, 64199, -51, 4294967244, -53, 4294967242 },
+ { -55, 200, -1337, 65485, -52, 4294967243, -54, 4294967241 },
+ { -56, 199, -51, 65484, -53, 4294967242, -55, 4294967240 },
+ { -57, 205, -52, 65483, -54, 4294967241, -56, 4294967239 },
+ { -51, 204, -53, 65482, -55, 4294967240, -57, 4294967245 },
+ };
-// TODO: This doesn't work in interpreted mode:
-// const QMetaObject *meta = qvariant_cast<const QMetaObject *>(o->property("metaobject"));
-// QVERIFY(meta != nullptr);
-// QCOMPARE(meta->className(), "DerivedFromInvisible");
-}
+ QStringList asStrings(8);
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(zeroes));
-class MyCppType : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(bool useListDelegate
- READ useListDelegate
- WRITE setUseListDelegate
- NOTIFY useListDelegateChanged)
-public:
- explicit MyCppType(QObject * parent = nullptr) : QObject(parent) {}
+ QMetaObject::invokeMethod(o.data(), "writeValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(written));
- bool useListDelegate() const { return m_useListDelegate; }
- void setUseListDelegate(bool useListDelegate)
- {
- if (useListDelegate != m_useListDelegate) {
- m_useListDelegate = useListDelegate;
- emit useListDelegateChanged();
+ QMetaObject::invokeMethod(o.data(), "negateValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(writtenNegative));
+
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(o.data(), "shuffleValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
}
+ QCOMPARE(asStrings, convertToStrings(writtenShuffled[i]));
}
-signals:
- void useListDelegateChanged();
+ QMetaObject::invokeMethod(o.data(), "storeValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(stored));
-private:
- bool m_useListDelegate = false;
-};
+ QMetaObject::invokeMethod(o.data(), "negateValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(storedNegative));
+
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(o.data(), "shuffleValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(storedShuffled[i]));
+ }
+}
-void tst_QmlCppCodegen::invalidPropertyType()
+void tst_QmlCppCodegen::objectInVar()
{
- // Invisible on purpose
- qmlRegisterType<MyCppType>("App", 1, 0, "MyCppType");
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/objectInVar.qml"_s));
+ 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::objectLookupOnListElement()
+{
QQmlEngine engine;
- QQmlComponent okComponent(&engine, QUrl(u"qrc:/qt/qml/TestTypes/OkType.qml"_s));
- QVERIFY2(okComponent.isReady(), qPrintable(okComponent.errorString()));
- QScopedPointer<QObject> picker(okComponent.create());
- QVERIFY2(!picker.isNull(), qPrintable(okComponent.errorString()));
- QObject *inner = qmlContext(picker.data())->objectForName(u"inner"_s);
- QVERIFY(inner);
- MyCppType *myCppType = qobject_cast<MyCppType *>(inner);
- QVERIFY(myCppType);
- QVERIFY(!myCppType->useListDelegate());
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/BadType.qml"_s));
+ const QUrl url(u"qrc:/qt/qml/TestTypes/objectLookupOnListElement.qml"_s);
+ QQmlComponent c1(&engine, url);
+ QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
+
+ QScopedPointer<QObject> object(c1.create());
+ QVERIFY(!object.isNull());
+
+ QList<int> zOrders;
+ QMetaObject::invokeMethod(object.data(), "zOrders", Q_RETURN_ARG(QList<int>, zOrders));
+ QCOMPARE(zOrders, (QList<int>{1, 0, 0}));
+ object->setProperty("current", 1);
+ QMetaObject::invokeMethod(object.data(), "zOrders", Q_RETURN_ARG(QList<int>, zOrders));
+ QCOMPARE(zOrders, (QList<int>{0, 1, 0}));
+
+ QMetaObject::invokeMethod(object.data(), "clearChildren");
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString()
+ + u":21: TypeError: Cannot read property 'z' of undefined"_s));
+ QMetaObject::invokeMethod(object.data(), "zOrders", Q_RETURN_ARG(QList<int>, zOrders));
+ QCOMPARE(zOrders, (QList<int>()));
+}
+
+void tst_QmlCppCodegen::objectToString()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/toString.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.createWithInitialProperties(
- QVariantMap {{u"picker"_s, QVariant::fromValue(picker.data())}}));
- QVERIFY2(!o.isNull(), qPrintable(c.errorString()));
- QVERIFY(!myCppType->useListDelegate());
- o->setProperty("useListDelegate", QVariant::fromValue<bool>(true));
- QVERIFY(myCppType->useListDelegate());
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/toString.qml:6: no");
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("yes").toString(), u"yes yes"_s);
+ QCOMPARE(o->property("no").toString(), u" no"_s); // throws, but that is ignored
}
-void tst_QmlCppCodegen::valueTypeLists()
+void tst_QmlCppCodegen::objectWithStringListMethod()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/valueTypeLists.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/objectWithStringListMethod.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtDebugMsg, "2");
QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
- QCOMPARE(qvariant_cast<QRectF>(o->property("rectInBounds")), QRectF(1, 2, 3, 4));
- QVERIFY(o->metaObject()->indexOfProperty("rectOutOfBounds") > 0);
- QVERIFY(!o->property("rectOutOfBounds").isValid());
+void tst_QmlCppCodegen::onAssignment()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/pressAndHoldButton.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
- QCOMPARE(qvariant_cast<QString>(o->property("stringInBounds")), QStringLiteral("bbb"));
- QVERIFY(o->metaObject()->indexOfProperty("stringOutOfBounds") > 0);
- QVERIFY(!o->property("stringOutOfBounds").isValid());
+ QCOMPARE(object->property("pressed").toBool(), false);
+ QCOMPARE(object->property("scale").toDouble(), 1.0);
- QCOMPARE(qvariant_cast<int>(o->property("intInBounds")), 7);
- QVERIFY(o->metaObject()->indexOfProperty("intOutOfBounds") > 0);
- QVERIFY(!o->property("intOutOfBounds").isValid());
+ object->metaObject()->invokeMethod(object.data(), "press");
+ QTRY_COMPARE(object->property("pressed").toBool(), true);
+ QCOMPARE(object->property("scale").toDouble(), 0.9);
- QCOMPARE(qvariant_cast<QString>(o->property("charInBounds")), QStringLiteral("d"));
- QVERIFY(o->metaObject()->indexOfProperty("charOutOfBounds") > 0);
- QVERIFY(!o->property("charOutOfBounds").isValid());
+ object->metaObject()->invokeMethod(object.data(), "release");
+ QCOMPARE(object->property("pressed").toBool(), false);
+ QCOMPARE(object->property("scale").toDouble(), 1.0);
}
-void tst_QmlCppCodegen::boundComponents()
+void tst_QmlCppCodegen::optionalComparison()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/boundComponents.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/optionalComparison.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- QObject *c1o = o->property("o").value<QObject *>();
- QVERIFY(c1o != nullptr);
- QCOMPARE(c1o->objectName(), u"bar"_s);
+ QCOMPARE(object->property("found").toInt(), 1);
+ QCOMPARE(object->property("foundStrict").toInt(), 1);
+ QCOMPARE(object->property("foundNot").toInt(), 2);
+ QCOMPARE(object->property("foundStrictNot").toInt(), 2);
- QObject *c2o = c1o->property("o").value<QObject *>();
- QVERIFY(c2o != nullptr);
- QCOMPARE(c2o->objectName(), u"bar12"_s);
+ // this === this, null === null (x4), undefined === undefined
+ QCOMPARE(object->property("undefinedEqualsUndefined").toInt(), 6);
+
+ QCOMPARE(object->property("optionalNull").toBool(), true);
+ object->setObjectName("foo"_L1);
+ QCOMPARE(object->property("optionalNull").toBool(), false);
}
-class InvisibleListElementType : public QObject
+void tst_QmlCppCodegen::outOfBoundsArray()
{
- Q_OBJECT
-public:
- InvisibleListElementType(QObject *parent = nullptr) : QObject(parent) {}
-};
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/outOfBounds.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
-void tst_QmlCppCodegen::invisibleListElementType()
+ QTest::ignoreMessage(QtDebugMsg, "oob undefined");
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QVERIFY(object->metaObject()->indexOfProperty("oob") > 0);
+ QVERIFY(!object->property("oob").isValid());
+ const QVariant oob2 = object->property("oob2");
+ QCOMPARE(oob2.metaType(), QMetaType::fromType<QObject *>());
+ QCOMPARE(oob2.value<QObject *>(), nullptr);
+}
+
+void tst_QmlCppCodegen::overriddenProperty()
{
- qmlRegisterType<InvisibleListElementType>("Invisible", 1, 0, "InvisibleListElement");
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/invisibleListElementType.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/childobject.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- QObject *a = o->property("a").value<QObject *>();
- QVERIFY(a);
+ QObject *child = object->property("child").value<QObject *>();
+ QVERIFY(child);
- const QVariant x = a->property("x");
- QCOMPARE(x.metaType(), QMetaType::fromType<QQmlListReference>());
- const QQmlListReference ref = x.value<QQmlListReference>();
- QVERIFY(ref.isValid());
- QCOMPARE(ref.size(), 0);
+ QCOMPARE(object->objectName(), u"kraut"_s);
+ QCOMPARE(object->property("doneThing").toInt(), 5);
+ QCOMPARE(object->property("usingFinal").toInt(), 5);
+
+ auto checkAssignment = [&]() {
+ const QString newName = u"worscht"_s;
+ QMetaObject::invokeMethod(object.data(), "setChildObjectName", Q_ARG(QString, newName));
+ QCOMPARE(object->objectName(), newName);
+ };
+ checkAssignment();
+
+ QMetaObject::invokeMethod(child, "doString");
+ QCOMPARE(child->objectName(), u"string"_s);
+ QMetaObject::invokeMethod(child, "doNumber");
+ QCOMPARE(child->objectName(), u"double"_s);
+ QMetaObject::invokeMethod(child, "doArray");
+ QCOMPARE(child->objectName(), u"javaScript"_s);
+
+ QMetaObject::invokeMethod(child, "doString2");
+ QCOMPARE(child->objectName(), u"string"_s);
+ QMetaObject::invokeMethod(child, "doNumber2");
+ QCOMPARE(child->objectName(), u"double"_s);
+ QMetaObject::invokeMethod(child, "doArray2");
+ QCOMPARE(child->objectName(), u"javaScript"_s);
+
+ QMetaObject::invokeMethod(child, "doFoo");
+ QCOMPARE(child->objectName(), u"ObjectWithMethod"_s);
+
+ ObjectWithMethod *benign = new ObjectWithMethod(object.data());
+ benign->theThing = 10;
+ benign->setObjectName(u"cabbage"_s);
+ object->setProperty("child", QVariant::fromValue(benign));
+ QCOMPARE(object->objectName(), u"cabbage"_s);
+ checkAssignment();
+ QCOMPARE(object->property("doneThing").toInt(), 10);
+ QCOMPARE(object->property("usingFinal").toInt(), 10);
+
+ OverriddenObjectName *evil = new OverriddenObjectName(object.data());
+ QTest::ignoreMessage(QtWarningMsg,
+ "Final member fff is overridden in class OverriddenObjectName. "
+ "The override won't be used.");
+ object->setProperty("child", QVariant::fromValue(evil));
+
+ QCOMPARE(object->objectName(), u"borschtsch"_s);
+
+ checkAssignment();
+ QCOMPARE(object->property("doneThing").toInt(), 7);
+ QCOMPARE(object->property("usingFinal").toInt(), 5);
}
-void tst_QmlCppCodegen::typePropertyClash()
+void tst_QmlCppCodegen::ownPropertiesNonShadowable()
{
QQmlEngine engine;
- engine.rootContext()->setContextProperty(u"size"_s, 5);
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/typePropertyClash.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- QCOMPARE(o->objectName(), u"Size: 5"_s);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/overriddenMember.qml"_s));
+
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
+
+ QCOMPARE(rootObject->property("ppp").toInt(), 16);
+ QCOMPARE(rootObject->property("ppp2").toInt(), 9);
+ QCOMPARE(rootObject->property("ppp3").toInt(), 12);
}
-void tst_QmlCppCodegen::objectToString()
+void tst_QmlCppCodegen::parentProperty()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/toString.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/parentProp.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("c").toInt(), 11);
+ QCOMPARE(object->property("i").toInt(), 22);
+ object->setProperty("a", QVariant::fromValue(22));
+ QCOMPARE(object->property("c").toInt(), 28);
+ object->setProperty("implicitWidth", QVariant::fromValue(14));
+ QCOMPARE(object->property("i").toInt(), 26);
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/toString.qml:6: no");
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
+ QObject *child = qmlContext(object.data())->objectForName(u"child"_s);
+ QObject *sibling = qmlContext(object.data())->objectForName(u"sibling"_s);
+ QObject *evil = qmlContext(object.data())->objectForName(u"evil"_s);
- QCOMPARE(o->property("yes").toString(), u"yes yes"_s);
- QCOMPARE(o->property("no").toString(), u" no"_s); // throws, but that is ignored
+ child->setProperty("parent", QVariant::fromValue(sibling));
+
+ QCOMPARE(child->property("b").toInt(), 0);
+ QCOMPARE(child->property("i").toInt(), 28);
+ QCOMPARE(object->property("i").toInt(), 56);
+
+ child->setProperty("parent", QVariant::fromValue(evil));
+
+ QCOMPARE(child->property("b").toInt(), 5994);
+ QCOMPARE(object->property("c").toInt(), 5996);
+
+ QCOMPARE(child->property("i").toInt(), 443);
+ QCOMPARE(object->property("i").toInt(), 886);
+
+ {
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/specificParent.qml"_s));
+
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
+
+ QCOMPARE(rootObject->property("a").toReal(), 77.0);
+ }
}
-void tst_QmlCppCodegen::throwObjectName()
+void tst_QmlCppCodegen::popContextAfterRet()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/throwObjectName.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/popContextAfterRet.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
-
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/throwObjectName.qml:5:5: ouch");
QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- QVERIFY(o->objectName().isEmpty());
+ QVERIFY(o);
+
+ QCOMPARE(o->objectName(), QString());
+ o->setProperty("stackViewDepth", 1);
+ QCOMPARE(o->objectName(), u"backgroundImage"_s);
+ o->setProperty("stackViewDepth", 2);
+ QCOMPARE(o->objectName(), u"backgroundBlur"_s);
+ o->setProperty("stackViewDepth", 1);
+ QCOMPARE(o->objectName(), u"backgroundImage"_s);
}
-void tst_QmlCppCodegen::javaScriptArgument()
+void tst_QmlCppCodegen::prefixedType()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/javaScriptArgument.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ // We need to add an import path here because we cannot namespace the implicit import.
+ // The implicit import is what we use for all the other tests, even if we explicitly
+ // import TestTypes. That is because the TestTypes module is in a subdirectory "data".
+ engine.addImportPath(u":/"_s);
+
+ const QUrl document(u"qrc:/qt/qml/TestTypes/prefixedMetaType.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
+ QVERIFY(o);
- QCOMPARE(o->property("a").toDouble(), 4.0);
- QCOMPARE(o->property("b").toDouble(), 9.0);
- QCOMPARE(o->property("c").toString(), u"5t-1"_s);
- QCOMPARE(o->property("d").toString(), u"9"_s);
- QCOMPARE(o->property("e").toString(), u"10"_s);
- QCOMPARE(o->property("f").toString(), u"-10"_s);
+ QCOMPARE(o->property("state").toInt(), 2);
+ QVERIFY(qvariant_cast<QObject *>(o->property("a")) != nullptr);
+ QVERIFY(qvariant_cast<QObject *>(o->property("b")) != nullptr);
+ QVERIFY(qvariant_cast<QObject *>(o->property("c")) == nullptr);
- const QStringList scales {
- "0 ", "1 ", "10 ", "100 ", "1000 ", "9.77k", "97.7k", "977k", "9.54M", "95.4M", "954M",
- "9.31G", "93.1G", "931G", "9.09T", "-1 ", "-10 ", "-100 ", "-1000 ", "-9.77k", "-97.7k",
- "-977k", "-9.54M", "-95.4M", "-954M", "-9.31G", "-93.1G", "-931G", "-9.09T"
- };
+ QVERIFY(qvariant_cast<QObject *>(o->property("d")) != nullptr);
+ QVERIFY(qvariant_cast<QObject *>(o->property("e")) != nullptr);
+ QVERIFY(qvariant_cast<QObject *>(o->property("f")) == nullptr);
- QCOMPARE(o->property("scales").value<QStringList>(), scales);
+ QVERIFY(qvariant_cast<QObject *>(o->property("g")) != nullptr);
+ QVERIFY(qvariant_cast<QObject *>(o->property("h")) != nullptr);
- double thing = 12.0;
- QString result;
- QMetaObject::invokeMethod(
- o.data(), "forwardArg", Q_RETURN_ARG(QString, result), Q_ARG(double, thing));
- QCOMPARE(result, u"12 ");
+ QCOMPARE(o->property("countG").toInt(), 11);
+ QCOMPARE(o->property("countH").toInt(), 11);
}
-void tst_QmlCppCodegen::translation()
+void tst_QmlCppCodegen::propertyOfParent()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/translation.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/RootWithoutId.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
- QCOMPARE(o->property("translate2"), u"s"_s);
- QCOMPARE(o->property("translate3"), u"s"_s);
- QCOMPARE(o->property("translate4"), u"s"_s);
+ QObject *child = qmlContext(object.data())->objectForName(u"item"_s);
- QCOMPARE(o->property("translateNoop2"), u"s"_s);
- QCOMPARE(o->property("translateNoop3"), u"s"_s);
+ bool expected = false;
- QCOMPARE(o->property("tr1"), u"s"_s);
- QCOMPARE(o->property("tr2"), u"s"_s);
- QCOMPARE(o->property("tr3"), u"s"_s);
+ for (int i = 0; i < 3; ++i) {
+ const QVariant foo = object->property("foo");
+ QCOMPARE(foo.metaType(), QMetaType::fromType<bool>());
+ QCOMPARE(foo.toBool(), expected);
- QCOMPARE(o->property("trNoop1"), u"s"_s);
- QCOMPARE(o->property("trNoop2"), u"s"_s);
+ const QVariant bar = object->property("bar");
+ QCOMPARE(bar.metaType(), QMetaType::fromType<bool>());
+ QCOMPARE(bar.toBool(), expected);
- QCOMPARE(o->property("trId1"), u"s"_s);
- QCOMPARE(o->property("trId2"), u"s"_s);
+ const QVariant visible = child->property("visible");
+ QCOMPARE(visible.metaType(), QMetaType::fromType<bool>());
+ QCOMPARE(visible.toBool(), expected);
- QCOMPARE(o->property("trIdNoop1"), u"s"_s);
+ expected = !expected;
+ object->setProperty("foo", expected);
+ }
}
-void tst_QmlCppCodegen::stringArg()
+void tst_QmlCppCodegen::reduceWithNullThis()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/stringArg.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/reduceWithNullThis.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- QCOMPARE(o->property("stringArg"), u"a foozly thing"_s);
- QCOMPARE(o->property("falseArg"), u"a 0 thing"_s);
- QCOMPARE(o->property("trueArg"), u"a 1 thing"_s);
- QCOMPARE(o->property("zeroArg"), u"a 0 thing"_s);
- QCOMPARE(o->property("intArg"), u"a 11 thing"_s);
- QCOMPARE(o->property("realArg"), u"a 12.25 thing"_s);
+ QCOMPARE(object->property("preferredHeight").toDouble(), 28.0);
+ QCOMPARE(object->property("preferredHeight2").toDouble(), 28.0);
}
-void tst_QmlCppCodegen::conversionDecrement()
+void tst_QmlCppCodegen::readEnumFromInstance()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/conversionDecrement.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ const QString url = u"qrc:/qt/qml/TestTypes/readEnumFromInstance.qml"_s;
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
+ QQmlComponent component(&engine, QUrl(url));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QCOMPARE(o->property("currentPageIndex").toInt(), 0);
- o->setProperty("pages", 5);
- QCOMPARE(o->property("currentPageIndex").toInt(), 3);
- o->setProperty("pages", 4);
- QCOMPARE(o->property("currentPageIndex").toInt(), 0);
- o->setProperty("pages", 6);
- QCOMPARE(o->property("currentPageIndex").toInt(), 4);
- o->setProperty("pages", 60);
- QCOMPARE(o->property("currentPageIndex").toInt(), 3);
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(url + ":7:5: Unable to assign [undefined] to int"_L1));
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QCOMPARE(object->property("priority"), QVariant::fromValue<int>(0));
+ QCOMPARE(object->property("prop2"), QVariant::fromValue<int>(1));
+ QCOMPARE(object->property("priorityIsVeryHigh"), QVariant::fromValue<bool>(false));
+
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(url + ":13: Error: Cannot assign [undefined] to int"_L1));
+
+ int result = 0;
+ QMetaObject::invokeMethod(object.data(), "cyclePriority", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 0);
}
-void tst_QmlCppCodegen::unstoredUndefined()
+void tst_QmlCppCodegen::readonlyListProperty()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unstoredUndefined.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QCOMPARE(o->objectName(), u"NaN"_s);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/readonlyListProperty.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QCOMPARE(object->property("l").toInt(), 4);
+}
+
+void tst_QmlCppCodegen::registerElimination()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/registerelimination.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ // Increment of 23 hits both 0 and 460
+ for (int input = -23; input < 700; input += 23) {
+ object->setProperty("input", input);
+ if (input <= 0 || input >= 460)
+ QCOMPARE(object->property("output").toInt(), 459);
+ else
+ QCOMPARE(object->property("output").toInt(), input);
+ }
}
void tst_QmlCppCodegen::registerPropagation()
@@ -2431,784 +4139,989 @@ void tst_QmlCppCodegen::registerPropagation()
QCOMPARE(undefined, u"undefined"_s);
}
-void tst_QmlCppCodegen::argumentConversion()
+void tst_QmlCppCodegen::renameAdjust()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/argumentConversion.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/renameAdjust.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- auto checkNaN = [&](const char *propName) {
- const QVariant prop = o->property(propName);
- QCOMPARE(prop.metaType(), QMetaType::fromType<double>());
- QVERIFY(qIsNaN(prop.toDouble()));
- };
+ QTest::ignoreMessage(QtDebugMsg, "success");
+ QTest::ignoreMessage(QtCriticalMsg, "failed 10 11");
- checkNaN("a");
- checkNaN("b");
- checkNaN("e");
-
- QCOMPARE(o->property("c").toDouble(), 3.0);
- QCOMPARE(o->property("d").toDouble(), -1.0);
- QCOMPARE(o->property("f").toDouble(), 10.0);
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
}
-void tst_QmlCppCodegen::badSequence()
+void tst_QmlCppCodegen::resettableProperty()
{
+ QFETCH(QString, url);
+
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/badSequence.qml"_s));
+ QQmlComponent c(&engine, QUrl(url));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
-
- Person *self = qobject_cast<Person *>(o.data());
- QVERIFY(self);
- QVERIFY(self->barzles().isEmpty());
- QVERIFY(self->cousins().isEmpty());
-
- Person *other = o->property("other").value<Person *>();
- QVERIFY(other);
- QVERIFY(other->barzles().isEmpty());
- QVERIFY(other->cousins().isEmpty());
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(url + u":10:5: Unable to assign [undefined] to double"_s));
- Barzle f1;
- Barzle f2;
- const QList<Barzle *> barzles { &f1, &f2 };
- const QList<Person *> cousins { self, other };
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- other->setBarzles(barzles);
- QCOMPARE(self->barzles(), barzles);
- QCOMPARE(self->property("l").toInt(), 2);
+ QCOMPARE(o->property("value").toDouble(), 999);
+ QMetaObject::invokeMethod(o.data(), "doReset");
+ QCOMPARE(o->property("value").toDouble(), 0);
- other->setCousins(cousins);
- QCOMPARE(self->cousins(), cousins);
- QCOMPARE(self->property("m").toInt(), 2);
+ o->setProperty("value", double(82));
+ QCOMPARE(o->property("value").toDouble(), 82);
+ QMetaObject::invokeMethod(o.data(), "doReset2");
+ QCOMPARE(o->property("value").toDouble(), 0);
- QQmlListProperty<Person> others
- = self->property("others").value<QQmlListProperty<Person>>();
- QCOMPARE(others.count(&others), 2);
- QCOMPARE(others.at(&others, 0), cousins[0]);
- QCOMPARE(others.at(&others, 1), cousins[1]);
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(url + u":18: Error: Cannot assign [undefined] to double"_s));
+ QCOMPARE(o->property("notResettable").toDouble(), 10);
+ QMetaObject::invokeMethod(o.data(), "doNotReset");
+ QCOMPARE(o->property("notResettable").toDouble(), 10);
+ QCOMPARE(o->property("notResettable2").toDouble(), 0); // not NaN
- QQmlListProperty<Person> momsCousins
- = self->property("momsCousins").value<QQmlListProperty<Person>>();
- QCOMPARE(momsCousins.count(&momsCousins), 2);
- QCOMPARE(momsCousins.at(&momsCousins, 0), cousins[0]);
- QCOMPARE(momsCousins.at(&momsCousins, 1), cousins[1]);
+ o->setObjectName(u"namename"_s);
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(url + u":22: Error: Cannot assign [undefined] to QString"_s));
+ QMetaObject::invokeMethod(o.data(), "aaa");
+ QCOMPARE(o->objectName(), u"namename"_s);
+}
- QQmlListProperty<Person> dadsCousins
- = self->property("dadsCousins").value<QQmlListProperty<Person>>();
- QCOMPARE(dadsCousins.count(&dadsCousins), 1);
- QCOMPARE(dadsCousins.at(&dadsCousins, 0), other);
+void tst_QmlCppCodegen::resettableProperty_data()
+{
+ QTest::addColumn<QString>("url");
+ QTest::addRow("object lookups") << u"qrc:/qt/qml/TestTypes/resettable.qml"_s;
+ QTest::addRow("fallback lookups") << u"qrc:/qt/qml/TestTypes/fallbackresettable.qml"_s;
}
-void tst_QmlCppCodegen::enumLookup()
+void tst_QmlCppCodegen::returnAfterReject()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumLookup.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/returnAfterReject.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
-
- QCOMPARE(o->property("ready").toBool(), true);
+ QVERIFY(o);
+ QCOMPARE(o->property("bar").toInt(), 123);
}
-void tst_QmlCppCodegen::trivialSignalHandler()
+void tst_QmlCppCodegen::revisions()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/trivialSignalHandler.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/revisions.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QCOMPARE(o->property("a").toString(), u"no"_s);
- QCOMPARE(o->property("b").toInt(), -1);
- QCOMPARE(o->property("b").toDouble(), -1.0);
+ QCOMPARE(o->property("delayed").toBool(), true);
+ QCOMPARE(o->property("gotten").toInt(), 5);
+}
- o->setObjectName(u"yes"_s);
- QCOMPARE(o->property("a").toString(), u"yes"_s);
- QCOMPARE(o->property("b").toInt(), 5);
- QCOMPARE(o->property("c").toDouble(), 2.5);
+void tst_QmlCppCodegen::scopeIdLookup()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/scopeIdLookup.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("objectName").toString(), u"outer"_s);
}
-void tst_QmlCppCodegen::stringToByteArray()
+void tst_QmlCppCodegen::scopeObjectDestruction()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/stringToByteArray.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/fileDialog.qml"_s));
- Person *person = qobject_cast<Person *>(o.data());
- QVERIFY(person);
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
- QCOMPARE(person->dataBindable().value(), QByteArray("some data"));
- QCOMPARE(person->name(), u"some data"_s);
+ QObject *dialog = rootObject->property("dialog").value<QObject *>();
+ QVERIFY(dialog);
+
+ // We cannot check the warning messages. The AOT compiled code complains about reading the
+ // "parent" property of an object scheduled for deletion. The runtime silently returns undefined
+ // at that point and then complains about not being able to read a property on undefined.
+
+ // Doesn't crash, even though it triggers bindings on scope objects scheduled for deletion.
+ QMetaObject::invokeMethod(dialog, "open");
}
-void tst_QmlCppCodegen::listPropertyAsModel()
+void tst_QmlCppCodegen::scopeVsObject()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listPropertyAsModel.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
-
- QQmlListReference children(o.data(), "children");
- QCOMPARE(children.count(), 5);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/scopeVsObject.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("objectName").toString(), u"foobar"_s);
}
-void tst_QmlCppCodegen::notNotString()
+void tst_QmlCppCodegen::scopedEnum()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/notNotString.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
+ const QString url = u"qrc:/qt/qml/TestTypes/scopedEnum.qml"_s;
+ QQmlComponent component(&engine, QUrl(url));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QCOMPARE(o->property("notNotString").value<bool>(), false);
- o->setObjectName(u"a"_s);
- QCOMPARE(o->property("notNotString").value<bool>(), true);
-}
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url + u":6:5: Unable to assign [undefined] to int"_s));
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url + u":8: TypeError: Cannot read property 'C' of undefined"_s));
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url + u":14: TypeError: Cannot read property 'C' of undefined"_s));
-template<typename T>
-QString toOperand(double arg);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("good").toInt(), 27);
+ QCOMPARE(object->property("bad").toInt(), 0);
+ QCOMPARE(object->property("wrong").toInt(), 0);
+ QCOMPARE(object->property("right").toInt(), 7);
-template<>
-QString toOperand<double>(double arg)
-{
- if (qIsNull(arg))
- return std::signbit(arg) ? QStringLiteral("(-0)") : QStringLiteral("(0)");
+ QCOMPARE(object->property("notgood").toInt(), 26);
+ QCOMPARE(object->property("notbad").toInt(), 26);
+ QCOMPARE(object->property("notwrong").toInt(), 0);
+ QCOMPARE(object->property("notright").toInt(), 6);
- return u'(' + QJSPrimitiveValue(arg).toString() + u')';
+ QCOMPARE(object->property("passable").toInt(), 2);
+ QCOMPARE(object->property("wild").toInt(), 1);
}
-template<>
-QString toOperand<int>(double arg)
+void tst_QmlCppCodegen::sequenceToIterable()
{
- const int iArg = QJSPrimitiveValue(arg).toInteger();
- return u'(' + QJSPrimitiveValue(iArg).toString() + u')';
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/sequenceToIterable.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("c").toInt(), 11);
+
+ QQmlListReference children(object.data(), "children");
+ QCOMPARE(children.count(), 11);
+ static const QRegularExpression name("Entry\\(0x[0-9a-f]+, \"Item ([0-9])\"\\): ([0-9])");
+ for (int i = 0; i < 10; ++i) {
+ const auto match = name.match(children.at(i)->objectName());
+ QVERIFY(match.hasMatch());
+ QCOMPARE(match.captured(1), QString::number(i));
+ }
}
-template<>
-QString toOperand<bool>(double arg)
+void tst_QmlCppCodegen::setLookupConversion()
{
- const bool bArg = QJSPrimitiveValue(arg).toBoolean();
- return u'(' + QJSPrimitiveValue(bArg).toString() + u')';
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/setLookupConversion.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QVERIFY(o->objectName().isEmpty());
+ QMetaObject::invokeMethod(o.data(), "t");
+ QCOMPARE(o->objectName(), u"a"_s);
+ QCOMPARE(o->property("value").toInt(), 9);
}
-template<typename T1, typename T2>
-double jsEval(double arg1, double arg2, const QString &op, QJSEngine *engine)
+void tst_QmlCppCodegen::setLookupOriginalScope()
{
- auto evalBinary = [&](const QString &jsOp) {
- return engine->evaluate(toOperand<T1>(arg1) + jsOp + toOperand<T2>(arg2)).toNumber();
- };
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/setLookupOriginalScope.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- auto evalBinaryConst = [&](const QString &jsOp) {
- return engine->evaluate(toOperand<T1>(arg1) + jsOp + u'9').toNumber();
- };
+ QObject *v = o->property("variable").value<QObject *>();
+ QCOMPARE(v->property("value").toInt(), 0);
- auto evalUnary = [&](const QString &jsOp) {
- return engine->evaluate(jsOp + toOperand<T1>(arg1)).toNumber();
- };
+ QMetaObject::invokeMethod(o.data(), "trigger");
+ QObject *edit = o->property("edit").value<QObject *>();
+ QVERIFY(edit);
+ QCOMPARE(edit->property("myOutput").value<QObject *>(), v);
+ QCOMPARE(v->property("value").toInt(), 55);
+}
- auto evalInPlace = [&](const QString &jsOp) {
- return engine->evaluate(
- u"(function() {var a = "_s + toOperand<T1>(arg1)+ u"; return "_s
- + jsOp + u"a;})()"_s).toNumber();
- };
+void tst_QmlCppCodegen::shadowedAsCasts()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/shadowedAsCasts.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> obj(c.create());
+ QVERIFY(!obj.isNull());
+
+ QObject *shadowed1 = obj->property("shadowed1").value<QObject *>();
+ QVERIFY(shadowed1);
+ QVERIFY(shadowed1->objectName().isEmpty());
+ const QVariant name1 = shadowed1->property("objectName");
+ QCOMPARE(name1.metaType(), QMetaType::fromType<int>());
+ QCOMPARE(name1.toInt(), 43);
+
+ QObject *shadowed2 = obj->property("shadowed2").value<QObject *>();
+ QVERIFY(shadowed2);
+ QVERIFY(shadowed2->objectName().isEmpty());
+ const QVariant name2 = shadowed2->property("objectName");
+ QCOMPARE(name2.metaType(), QMetaType::fromType<int>());
+ QCOMPARE(name2.toInt(), 42);
+
+ QObject *shadowed3 = obj->property("shadowed3").value<QObject *>();
+ QVERIFY(shadowed3);
+ QVERIFY(shadowed3->objectName().isEmpty());
+ const QVariant name3 = shadowed3->property("objectName");
+ QCOMPARE(name3.metaType(), QMetaType::fromType<double>());
+ QCOMPARE(name3.toDouble(), 41.0);
+}
+
+void tst_QmlCppCodegen::shadowedMethod()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/shadowedMethod.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("athing"), QVariant::fromValue<bool>(false));
+ QCOMPARE(o->property("bthing"), QVariant::fromValue(u"b"_s));
+ QCOMPARE(o->property("cthing"), QVariant::fromValue(u"c"_s));
+}
- if (op == u"unot")
- return evalUnary(u"!"_s);
- if (op == u"uplus")
- return evalUnary(u"+"_s);
- if (op == u"uminus")
- return evalUnary(u"-"_s);
- if (op == u"ucompl")
- return evalUnary(u"~"_s);
+void tst_QmlCppCodegen::shadowedPrimitiveCmpEqNull()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/shadowedPrimitiveCmpEqNull.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
- if (op == u"increment")
- return evalInPlace(u"++"_s);
- if (op == u"decrement")
- return evalInPlace(u"--"_s);
+void tst_QmlCppCodegen::shifts()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/shifts.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- if (op == u"add")
- return evalBinary(u"+"_s);
- if (op == u"sub")
- return evalBinary(u"-"_s);
- if (op == u"mul")
- return evalBinary(u"*"_s);
- if (op == u"div")
- return evalBinary(u"/"_s);
- if (op == u"exp")
- return evalBinary(u"**"_s);
- if (op == u"mod")
- return evalBinary(u"%"_s);
+ QCOMPARE(object->property("a").toInt(), 9728);
+ QCOMPARE(object->property("b").toInt(), 4864);
+ QCOMPARE(object->property("c").toInt(), 19448);
+ QCOMPARE(object->property("d").toInt(), 9731);
+ QCOMPARE(object->property("e").toInt(), 0);
+}
- if (op == u"bitAnd")
- return evalBinary(u"&"_s);
- if (op == u"bitOr")
- return evalBinary(u"|"_s);
- if (op == u"bitXor")
- return evalBinary(u"^"_s);
+void tst_QmlCppCodegen::signalHandler()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/signal.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->objectName(), QString());
+ QCOMPARE(object->property("ff").toInt(), 4);
- if (op == u"bitAndConst")
- return evalBinaryConst(u"&"_s);
- if (op == u"bitOrConst")
- return evalBinaryConst(u"|"_s);
- if (op == u"bitXorConst")
- return evalBinaryConst(u"^"_s);
+ object->setObjectName(u"foo"_s);
+ QCOMPARE(object->property("ff").toInt(), 12);
+}
- if (op == u"ushr")
- return evalBinary(u">>>"_s);
- if (op == u"shr")
- return evalBinary(u">>"_s);
- if (op == u"shl")
- return evalBinary(u"<<"_s);
+void tst_QmlCppCodegen::signalIndexMismatch()
+{
+ QQmlEngine engine;
- if (op == u"ushrConst")
- return evalBinaryConst(u">>>"_s);
- if (op == u"shrConst")
- return evalBinaryConst(u">>"_s);
- if (op == u"shlConst")
- return evalBinaryConst(u"<<"_s);
+ QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/signalIndexMismatch.qml"_s));
+ QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
- qDebug() << op;
- Q_UNREACHABLE_RETURN(0);
+ QScopedPointer<QObject> item(c1.create());
+ const auto visualIndexBeforeMoveList = item->property("visualIndexBeforeMove").toList();
+ const auto visualIndexAfterMoveList = item->property("visualIndexAfterMove").toList();
+
+ QCOMPARE(visualIndexBeforeMoveList, QList<QVariant>({ 0, 1, 2 }));
+ QCOMPARE(visualIndexAfterMoveList, QList<QVariant>({ 0, 1, 2 }));
}
-void tst_QmlCppCodegen::mathOperations()
+void tst_QmlCppCodegen::signalsWithLists()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/mathOperations.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/signalsWithLists.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- const QMetaObject *metaObject = o->metaObject();
+ QVariantList varlist = o->property("varlist").toList();
+ QCOMPARE(varlist.size(), 5);
+ QCOMPARE(varlist[0], QVariant::fromValue(1));
+ QCOMPARE(varlist[1], QVariant::fromValue(u"foo"_s));
+ QCOMPARE(varlist[2], QVariant::fromValue(o.data()));
+ QCOMPARE(varlist[3], QVariant());
+ QCOMPARE(varlist[4], QVariant::fromValue(true));
- char t1;
- char t2;
- QString name;
- const auto guard = qScopeGuard([&]() {
- if (QTest::currentTestFailed()) {
- qDebug() << t1 << t2 << name << "failed on:";
- qDebug() << "doubles" << o->property("a").toDouble() << o->property("b").toDouble();
- qDebug() << "integers" << o->property("ia").toInt() << o->property("ib").toInt();
- qDebug() << "booleans" << o->property("ba").toBool() << o->property("bb").toBool();
- }
- });
+ QQmlListProperty<QObject> objlist = o->property("objlist").value<QQmlListProperty<QObject>>();
+ QCOMPARE(objlist.count(&objlist), 3);
+ QCOMPARE(objlist.at(&objlist, 0), o.data());
+ QCOMPARE(objlist.at(&objlist, 1), nullptr);
+ QCOMPARE(objlist.at(&objlist, 2), o.data());
- for (double a : numbers) {
- for (double b : numbers) {
- o->setProperty("a", a);
- o->setProperty("b", b);
- for (int i = 0, end = metaObject->propertyCount(); i != end; ++i) {
- const QMetaProperty prop = metaObject->property(i);
- const QByteArray propName = prop.name();
+ QCOMPARE(o->property("happening").toInt(), 0);
+ o->metaObject()->invokeMethod(o.data(), "sendSignals");
+ QCOMPARE(o->property("happening").toInt(), 8);
+}
- if (propName.size() < 3 || propName == "objectName")
- continue;
+void tst_QmlCppCodegen::signatureIgnored()
+{
+ QQmlEngine engine;
- t1 = propName[0];
- t2 = propName[1];
- name = QString::fromUtf8(propName.mid(2));
+ QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/signatureIgnored.qml"_s));
+ QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
- double expected;
+ QScopedPointer<QObject> ignored(c1.create());
+ QCOMPARE(ignored->property("l").toInt(), 5);
+ QCOMPARE(ignored->property("m").toInt(), 77);
+ QCOMPARE(ignored->property("n").toInt(), 67);
+}
- switch (t2) {
- case 'd':
- case '_':
- switch (t1) {
- case 'd':
- expected = jsEval<double, double>(a, b, name, &engine);
- break;
- case 'i':
- expected = jsEval<int, double>(a, b, name, &engine);
- break;
- case 'b':
- expected = jsEval<bool, double>(a, b, name, &engine);
- break;
- }
- break;
- case 'i':
- switch (t1) {
- case 'd':
- expected = jsEval<double, int>(a, b, name, &engine);
- break;
- case 'i':
- expected = jsEval<int, int>(a, b, name, &engine);
- break;
- case 'b':
- expected = jsEval<bool, int>(a, b, name, &engine);
- break;
- }
- break;
- case 'b':
- switch (t1) {
- case 'd':
- expected = jsEval<double, bool>(a, b, name, &engine);
- break;
- case 'i':
- expected = jsEval<int, bool>(a, b, name, &engine);
- break;
- case 'b':
- expected = jsEval<bool, bool>(a, b, name, &engine);
- break;
- }
- break;
- }
+void tst_QmlCppCodegen::simpleBinding()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Test.qml"_s));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY2(!object.isNull(), component.errorString().toUtf8().constData());
+ QCOMPARE(object->property("foo").toInt(), int(3));
- const double result = prop.read(o.data()).toDouble();
- QCOMPARE(result, expected);
- }
- }
+ {
+ CppBaseClass *base = qobject_cast<CppBaseClass *>(object.data());
+ Q_ASSERT(base);
+ QVERIFY(!base->cppProp.hasBinding());
+ QCOMPARE(base->cppProp.value(), 7);
+ QVERIFY(base->cppProp2.hasBinding());
+ QCOMPARE(base->cppProp2.value(), 14);
+ base->cppProp.setValue(9);
+ QCOMPARE(base->cppProp.value(), 9);
+ QCOMPARE(base->cppProp2.value(), 18);
}
}
-void tst_QmlCppCodegen::inaccessibleProperty()
+void tst_QmlCppCodegen::storeElementSideEffects()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/versionmismatch.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/storeElementSideEffects.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QCOMPARE(o->property("c").toInt(), 5);
+ const QJSValue prop = o->property("myItem").value<QJSValue>();
+ QVERIFY(prop.isArray());
+ QCOMPARE(prop.property(0).toInt(), 10);
}
-void tst_QmlCppCodegen::typePropagationLoop()
+void tst_QmlCppCodegen::storeMetaEnum()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/typePropagationLoop.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/StoreMetaEnum.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QCOMPARE(o->property("j").toInt(), 3);
+ QCOMPARE(o->property("bar").toInt(), 0);
+ QCOMPARE(o->property("baz").toInt(), 1);
}
-void tst_QmlCppCodegen::signatureIgnored()
+void tst_QmlCppCodegen::stringArg()
{
QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/stringArg.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
- QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/signatureIgnored.qml"_s));
- QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
-
- QScopedPointer<QObject> ignored(c1.create());
- QCOMPARE(ignored->property("l").toInt(), 5);
- QCOMPARE(ignored->property("m").toInt(), 77);
- QCOMPARE(ignored->property("n").toInt(), 67);
+ QCOMPARE(o->property("stringArg"), u"a foozly thing"_s);
+ QCOMPARE(o->property("falseArg"), u"a 0 thing"_s);
+ QCOMPARE(o->property("trueArg"), u"a 1 thing"_s);
+ QCOMPARE(o->property("zeroArg"), u"a 0 thing"_s);
+ QCOMPARE(o->property("intArg"), u"a 11 thing"_s);
+ QCOMPARE(o->property("realArg"), u"a 12.25 thing"_s);
}
-void tst_QmlCppCodegen::listAsArgument()
+void tst_QmlCppCodegen::stringLength()
{
QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/stringLength.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("stringLength").toInt(), 8);
+}
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listAsArgument.qml"_s));
+void tst_QmlCppCodegen::stringToByteArray()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/stringToByteArray.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
-
QScopedPointer<QObject> o(c.create());
- QCOMPARE(o->property("i").toInt(), 4);
- QCOMPARE(o->property("j").toInt(), 2);
- QCOMPARE(o->property("i1").toInt(), 2);
- QCOMPARE(o->property("i2").toInt(), 4);
- QCOMPARE(o->property("d").value<QObject *>()->objectName(), u"this one"_s);
- int singleInt = 0;
- QList<int> moreInts;
- QMetaObject::invokeMethod(o.data(), "returnInts1", Q_RETURN_ARG(QList<int>, moreInts));
- QCOMPARE(moreInts, QList<int>({5, 4, 3, 2, 1}));
- QMetaObject::invokeMethod(o.data(), "selectSecondInt", Q_RETURN_ARG(int, singleInt), Q_ARG(QList<int>, moreInts));
- QCOMPARE(singleInt, 4);
+ Person *person = qobject_cast<Person *>(o.data());
+ QVERIFY(person);
+
+ QCOMPARE(person->dataBindable().value(), QByteArray("some data"));
+ QCOMPARE(person->name(), u"some data"_s);
}
-void tst_QmlCppCodegen::letAndConst()
+void tst_QmlCppCodegen::structuredValueType()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/letAndConst.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/structuredValueType.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(!o.isNull());
- QCOMPARE(o->objectName(), u"ab"_s);
+
+ QCOMPARE(o->property("r").value<QRectF>(), QRectF(1, 2, 3, 4));
+ QCOMPARE(o->property("r2").value<QRectF>(), QRectF(42, 0, 0, 0));
+
+ WeatherModelUrl w;
+ w.setStrings(QStringList({"one", "two", "three"}));
+
+ QCOMPARE(o->property("w").value<WeatherModelUrl>(), w);
}
-void tst_QmlCppCodegen::signalIndexMismatch()
+void tst_QmlCppCodegen::testIsnan()
{
QQmlEngine engine;
+ const QUrl document(u"qrc:/qt/qml/TestTypes/isnan.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/signalIndexMismatch.qml"_s));
- QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
+ QCOMPARE(o->property("good").toDouble(), 10.1);
+ QVERIFY(qIsNaN(o->property("bad").toDouble()));
- QScopedPointer<QObject> item(c1.create());
- const auto visualIndexBeforeMoveList = item->property("visualIndexBeforeMove").toList();
- const auto visualIndexAfterMoveList = item->property("visualIndexAfterMove").toList();
+ const QVariant a = o->property("a");
+ QCOMPARE(a.metaType(), QMetaType::fromType<bool>());
+ QVERIFY(!a.toBool());
- QCOMPARE(visualIndexBeforeMoveList, QList<QVariant>({ 0, 1, 2 }));
- QCOMPARE(visualIndexAfterMoveList, QList<QVariant>({ 0, 1, 2 }));
+ const QVariant b = o->property("b");
+ QCOMPARE(b.metaType(), QMetaType::fromType<bool>());
+ QVERIFY(b.toBool());
}
-void tst_QmlCppCodegen::callWithSpread()
+void tst_QmlCppCodegen::thisObject()
{
- QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/callWithSpread.qml"_s));
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/thisObject.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QTest::ignoreMessage(QtCriticalMsg, "That is great!");
QScopedPointer<QObject> o(c.create());
QVERIFY(!o.isNull());
+ QCOMPARE(o->property("warned").value<QObject *>(), o.data());
}
-void tst_QmlCppCodegen::nullComparison()
+void tst_QmlCppCodegen::throwObjectName()
{
QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/throwObjectName.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nullComparison.qml"_s));
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/throwObjectName.qml:5:5: ouch");
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QVERIFY(o->objectName().isEmpty());
+}
+
+void tst_QmlCppCodegen::topLevelComponent()
+{
+ // TODO: Once we stop accepting top level Component elements, this test can be removed.
+
+ QQmlEngine e;
+
+ const QUrl url(u"qrc:/qt/qml/TestTypes/topLevelComponent.qml"_s);
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + u":4:1: Using a Component as the root of a QML document "
+ "is deprecated: types defined in qml documents are "
+ "automatically wrapped into Components when needed."_s));
+
+ QQmlComponent c(&e, url);
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(!o.isNull());
- QCOMPARE(o->property("v").toInt(), 1);
- QCOMPARE(o->property("w").toInt(), 3);
- QCOMPARE(o->property("x").toInt(), 1);
- QCOMPARE(o->property("y").toInt(), 5);
+ QQmlComponent *inner = qobject_cast<QQmlComponent *>(o.data());
+ QVERIFY(inner);
+
+ QScopedPointer<QObject> o2(inner->create());
+ QCOMPARE(o2->objectName(), u"foo"_s);
}
-void tst_QmlCppCodegen::consoleObject()
+void tst_QmlCppCodegen::translation()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/consoleObject.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/translation.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
- QTest::ignoreMessage(QtDebugMsg, "b 4.55");
- QTest::ignoreMessage(QtDebugMsg, "b 4.55");
- QTest::ignoreMessage(QtInfoMsg, "b 4.55");
- QTest::ignoreMessage(QtWarningMsg, "b 4.55");
- QTest::ignoreMessage(QtCriticalMsg, "b 4.55");
+ QCOMPARE(o->property("translate2"), u"s"_s);
+ QCOMPARE(o->property("translate3"), u"s"_s);
+ QCOMPARE(o->property("translate4"), u"s"_s);
- // Unfortunately we cannot check the logging category with QTest::ignoreMessage
- QTest::ignoreMessage(QtDebugMsg, "b 4.55");
- QTest::ignoreMessage(QtDebugMsg, "b 4.55");
- QTest::ignoreMessage(QtInfoMsg, "b 4.55");
- QTest::ignoreMessage(QtWarningMsg, "b 4.55");
- QTest::ignoreMessage(QtCriticalMsg, "b 4.55");
+ QCOMPARE(o->property("translateNoop2"), u"s"_s);
+ QCOMPARE(o->property("translateNoop3"), u"s"_s);
- const QRegularExpression re(u"QQmlComponentAttached\\(0x[0-9a-f]+\\) b 4\\.55"_s);
- QTest::ignoreMessage(QtDebugMsg, re);
- QTest::ignoreMessage(QtDebugMsg, re);
- QTest::ignoreMessage(QtInfoMsg, re);
- QTest::ignoreMessage(QtWarningMsg, re);
- QTest::ignoreMessage(QtCriticalMsg, re);
+ QCOMPARE(o->property("tr1"), u"s"_s);
+ QCOMPARE(o->property("tr2"), u"s"_s);
+ QCOMPARE(o->property("tr3"), u"s"_s);
- QTest::ignoreMessage(QtDebugMsg, "a undefined b false null 7");
- QTest::ignoreMessage(QtDebugMsg, "");
- QTest::ignoreMessage(QtDebugMsg, "4");
- QTest::ignoreMessage(QtDebugMsg, "");
+ QCOMPARE(o->property("trNoop1"), u"s"_s);
+ QCOMPARE(o->property("trNoop2"), u"s"_s);
- const QRegularExpression re2(u"QQmlComponentAttached\\(0x[0-9a-f]+\\)"_s);
- QTest::ignoreMessage(QtDebugMsg, re2);
+ QCOMPARE(o->property("trId1"), u"s"_s);
+ QCOMPARE(o->property("trId2"), u"s"_s);
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
+ QCOMPARE(o->property("trIdNoop1"), u"s"_s);
}
-void tst_QmlCppCodegen::multiForeign()
+void tst_QmlCppCodegen::trigraphs()
{
- QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/multiforeign.qml"_s));
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/trigraphs.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- QCOMPARE(o->objectName(), u"not here and not there"_s);
+ QCOMPARE(o->objectName(), u"?""?= ?""?/ ?""?' ?""?( ?""?) ?""?! ?""?< ?""?> ?""?-"_s);
}
-void tst_QmlCppCodegen::namespaceWithEnum()
+void tst_QmlCppCodegen::trivialSignalHandler()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/namespaceWithEnum.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/trivialSignalHandler.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- QCOMPARE(o->property("i").toInt(), 2);
+
+ QCOMPARE(o->property("a").toString(), u"no"_s);
+ QCOMPARE(o->property("b").toInt(), -1);
+ QCOMPARE(o->property("b").toDouble(), -1.0);
+
+ o->setObjectName(u"yes"_s);
+ QCOMPARE(o->property("a").toString(), u"yes"_s);
+ QCOMPARE(o->property("b").toInt(), 5);
+ QCOMPARE(o->property("c").toDouble(), 2.5);
}
-void tst_QmlCppCodegen::enumProblems()
+void tst_QmlCppCodegen::typePropagationLoop()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumProblems.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> outer(c.create());
- QVERIFY(!outer.isNull());
- QObject *inner = outer->property("o").value<QObject *>();
- QVERIFY(inner);
- Foo *bar = inner->property("bar").value<Foo *>();
- QVERIFY(bar);
- QCOMPARE(bar->type(), Foo::Component);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/typePropagationLoop.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
- Foo *fighter = inner->property("fighter").value<Foo *>();
- QVERIFY(fighter);
- QCOMPARE(fighter->type(), Foo::Fighter);
+ QCOMPARE(o->property("j").toInt(), 3);
}
-void tst_QmlCppCodegen::enumConversion()
+void tst_QmlCppCodegen::typePropertyClash()
{
QQmlEngine engine;
-
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumConversion.qml"_s));
+ engine.rootContext()->setContextProperty(u"size"_s, 5);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/typePropertyClash.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), u"Size: 5"_s);
+}
+void tst_QmlCppCodegen::typedArray()
+{
+ QQmlEngine engine;
+ const QUrl document(u"qrc:/qt/qml/TestTypes/typedArray.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(o);
- QCOMPARE(o->property("test").toInt(), 0x04);
- QCOMPARE(o->property("test_1").toBool(), true);
+ QDateTime date;
+ QVERIFY(qvariant_cast<QList<int>>(o->property("values2")).isEmpty());
+ QCOMPARE(qvariant_cast<QList<int>>(o->property("values3")),
+ QList<int>({1, 2, 3, 4}));
+ QCOMPARE(qvariant_cast<QList<QDateTime>>(o->property("values4")),
+ QList<QDateTime>({date, date, date}));
+ {
+ const QList<double> actual
+ = qvariant_cast<QList<double>>(o->property("values5"));
+ const QList<double> expected
+ = QList<double>({1, 2, 3.4, 30, std::numeric_limits<double>::quiet_NaN(), 0});
+ QCOMPARE(actual.size(), expected.size());
+ for (qsizetype i = 0, end = actual.size(); i != end; ++i) {
+ if (std::isnan(expected[i]))
+ QVERIFY(std::isnan(actual[i]));
+ else
+ QCOMPARE(actual[i], expected[i]);
+ }
+ }
+ date = QDateTime::currentDateTime();
+ o->setProperty("aDate", date);
+ QCOMPARE(qvariant_cast<QList<QDateTime>>(o->property("values4")),
+ QList<QDateTime>({date, date, date}));
+
+ QQmlListProperty<QObject> values6
+ = qvariant_cast<QQmlListProperty<QObject>>(o->property("values6"));
+ QCOMPARE(values6.count(&values6), 3);
+ for (int i = 0; i < 3; ++i)
+ QCOMPARE(values6.at(&values6, i), o.data());
+
+ QCOMPARE(o->property("inIntList").toInt(), 2);
+ QCOMPARE(qvariant_cast<QDateTime>(o->property("inDateList")), date);
+ QCOMPARE(o->property("inRealList").toDouble(), 30.0);
+ QCOMPARE(o->property("inCharList").toString(), QStringLiteral("f"));
+
+ const QMetaObject *metaObject = o->metaObject();
+ QMetaMethod method = metaObject->method(metaObject->indexOfMethod("stringAt10(QString)"));
+ QVERIFY(method.isValid());
+
+ // If LoadElement threw an exception the function would certainly return neither 10 nor 20.
+ int result = 0;
+ method.invoke(
+ o.data(), Q_RETURN_ARG(int, result), Q_ARG(QString, QStringLiteral("a")));
+ QCOMPARE(result, 10);
+ method.invoke(
+ o.data(), Q_RETURN_ARG(int, result), Q_ARG(QString, QStringLiteral("aaaaaaaaaaa")));
+ QCOMPARE(result, 20);
}
-void tst_QmlCppCodegen::storeElementSideEffects()
+void tst_QmlCppCodegen::undefinedResets()
{
QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/undefinedResets.qml"_s));
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/storeElementSideEffects.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ Person *person = qobject_cast<Person *>(rootObject.data());
+ QVERIFY(person);
+ QCOMPARE(person->shoeSize(), 0);
+ QCOMPARE(person->name(), u"Marge"_s);
- const QJSValue prop = o->property("myItem").value<QJSValue>();
- QVERIFY(prop.isArray());
- QCOMPARE(prop.property(0).toInt(), 10);
-};
+ person->setShoeSize(11);
-void tst_QmlCppCodegen::ambiguousSignals()
+ QCOMPARE(person->shoeSize(), 11);
+ QCOMPARE(person->name(), u"Bart"_s);
+
+ person->setShoeSize(10);
+ QCOMPARE(person->shoeSize(), 10);
+ QCOMPARE(person->name(), u"Marge"_s);
+
+ person->setName(u"no one"_s);
+ QCOMPARE(person->name(), u"no one"_s);
+
+ person->setObjectName(u"the one"_s);
+ QCOMPARE(person->name(), u"Bart"_s);
+}
+
+void tst_QmlCppCodegen::undefinedToDouble()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ambiguousSignals.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/undefinedToDouble.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(!o.isNull());
- QCOMPARE(o->objectName(), u"tomorrow"_s);
- Person *p = qobject_cast<Person *>(o.data());
- QVERIFY(p);
- emit p->ambiguous(12);
- QCOMPARE(o->objectName(), u"12foo"_s);
- emit p->ambiguous();
- QCOMPARE(o->objectName(), u"9foo"_s);
+ const QVariant d = o->property("d");
+ QCOMPARE(d.metaType(), QMetaType::fromType<double>());
+ QVERIFY(std::isnan(d.toDouble()));
}
-void tst_QmlCppCodegen::fileImportsContainCxxTypes()
+void tst_QmlCppCodegen::unknownAttached()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/usingCxxTypesFromFileImports.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- QCOMPARE(o->objectName(), u"horst guenther"_s);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unknownAttached.qml"_s));
+ QVERIFY(c.isError());
}
-void tst_QmlCppCodegen::lengthAccessArraySequenceCompat()
+void tst_QmlCppCodegen::unknownParameter()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ArraySequenceLengthInterop.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unknownParameter.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("cppProp").toInt(), 18);
+}
+
+void tst_QmlCppCodegen::unstoredUndefined()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unstoredUndefined.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- QCOMPARE(o->property("length").toInt(), 100);
+ QCOMPARE(o->objectName(), u"NaN"_s);
}
-static QList<QString> convertToStrings(const QList<int> &ints)
+void tst_QmlCppCodegen::unusedAttached()
{
- QList<QString> strings;
- for (int i : ints)
- strings.append(QString::number(i));
- return strings;
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unusedAttached.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+
+ const auto func = qmlAttachedPropertiesFunction(
+ object.data(), QMetaType::fromName("QQuickKeyNavigationAttached*").metaObject());
+ QObject *attached = qmlAttachedPropertiesObject(object.data(), func);
+ const QVariant prop = attached->property("priority");
+ QVERIFY(prop.isValid());
+ QCOMPARE(QByteArray(prop.metaType().name()), "QQuickKeyNavigationAttached::Priority");
+ bool ok = false;
+ QCOMPARE(prop.toInt(&ok), 0);
+ QVERIFY(ok);
}
-void tst_QmlCppCodegen::numbersInJsPrimitive()
+void tst_QmlCppCodegen::urlString()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/numbersInJsPrimitive.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/urlString.qml"_s));
- const QList<int> zeroes = {0, 0, 0, 0};
- const QList<int> written = {39, 40, 41, 42};
- const QList<int> stored = {1334, 1335, 1336, 1337};
- QStringList asStrings(4);
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
- for (int i = 0; i < 4; ++i) {
- QMetaObject::invokeMethod(
- o.data(), "readValueAsString",
- Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ QCOMPARE(qvariant_cast<QUrl>(rootObject->property("c")), QUrl(u"http://dddddd.com"_s));
+ QCOMPARE(qvariant_cast<QUrl>(rootObject->property("d")), QUrl(u"http://aaaaaa.com"_s));
+ QCOMPARE(qvariant_cast<QUrl>(rootObject->property("e")), QUrl(u"http://a112233.de"_s));
+ QCOMPARE(rootObject->objectName(), QLatin1String("http://dddddd.com"));
+}
+
+void tst_QmlCppCodegen::valueTypeBehavior()
+{
+ QQmlEngine engine;
+
+ {
+ const QUrl url(u"qrc:/qt/qml/TestTypes/valueTypeCopy.qml"_s);
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'e'));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'f'));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("e").toDouble(), 45.0);
+ QCOMPARE(o->property("f").toDouble(), 1.0);
}
- QCOMPARE(asStrings, convertToStrings(zeroes));
- QMetaObject::invokeMethod(o.data(), "writeValues");
- for (int i = 0; i < 4; ++i) {
- QMetaObject::invokeMethod(
- o.data(), "readValueAsString",
- Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ {
+ const QUrl url(u"qrc:/qt/qml/TestTypes/valueTypeReference.qml"_s);
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'e'));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'f'));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QVERIFY(qIsNaN(o->property("e").toDouble()));
+ QCOMPARE(o->property("f").toDouble(), 5.0);
}
- QCOMPARE(asStrings, convertToStrings(written));
- QMetaObject::invokeMethod(o.data(), "storeValues");
- for (int i = 0; i < 4; ++i) {
- QMetaObject::invokeMethod(
- o.data(), "readValueAsString",
- Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ {
+ const QUrl url(u"qrc:/qt/qml/TestTypes/valueTypeDefault.qml"_s);
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'e'));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'f'));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QVERIFY(qIsNaN(o->property("e").toDouble()));
+ QCOMPARE(o->property("f").toDouble(), 5.0);
+ }
+
+ {
+ const QUrl url(u"qrc:/qt/qml/TestTypes/valueTypeCast.qml"_s);
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("x"), 10);
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString()
+ + u":8: TypeError: Cannot read property 'x' of undefined"_s));
+ o->setProperty("v", QLatin1String("not a rect"));
+
+ // If the binding throws an exception, the value doesn't change.
+ QCOMPARE(o->property("x"), 10);
+
+ QCOMPARE(o->property("tv3"), 5);
+ QCOMPARE(o->property("tc3"), 5);
+ QCOMPARE(o->property("tc6"), QVariant());
+ QCOMPARE(o->property("tc7"), QVariant());
+ QCOMPARE(o->property("tc8"), 2);
+
+ // The default greeting is never applied because undefined can be coerced to string
+ QCOMPARE(o->property("greeting1"), QLatin1String("undefined"));
+ QCOMPARE(o->property("greeting2"), QLatin1String("Custom Greeting"));
}
- QCOMPARE(asStrings, convertToStrings(stored));
}
-void tst_QmlCppCodegen::infinitiesToInt()
+void tst_QmlCppCodegen::valueTypeLists()
{
QQmlEngine engine;
-
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/infinitiesToInt.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/valueTypeLists.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- const char *props[] = {"a", "b", "c"};
- for (const char *prop : props) {
- const QVariant i = o->property(prop);
- QCOMPARE(i.metaType(), QMetaType::fromType<int>());
- bool ok = false;
- QCOMPARE(i.toInt(&ok), 0);
- QVERIFY(ok);
- }
+ QCOMPARE(qvariant_cast<QRectF>(o->property("rectInBounds")), QRectF(1, 2, 3, 4));
+ QVERIFY(o->metaObject()->indexOfProperty("rectOutOfBounds") > 0);
+ QVERIFY(!o->property("rectOutOfBounds").isValid());
+
+ QCOMPARE(qvariant_cast<QString>(o->property("stringInBounds")), QStringLiteral("bbb"));
+ QVERIFY(o->metaObject()->indexOfProperty("stringOutOfBounds") > 0);
+ QVERIFY(!o->property("stringOutOfBounds").isValid());
+
+ QCOMPARE(qvariant_cast<int>(o->property("intInBounds")), 7);
+ QVERIFY(o->metaObject()->indexOfProperty("intOutOfBounds") > 0);
+ QVERIFY(!o->property("intOutOfBounds").isValid());
+
+ QCOMPARE(qvariant_cast<QString>(o->property("charInBounds")), QStringLiteral("d"));
+ QVERIFY(o->metaObject()->indexOfProperty("charOutOfBounds") > 0);
+ QVERIFY(!o->property("charOutOfBounds").isValid());
}
-void tst_QmlCppCodegen::equalityVarAndNonStorable()
+void tst_QmlCppCodegen::valueTypeProperty()
{
QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/valueTypeProperty.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
- QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalityVarAndNonStorable.qml"_s));
- QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
+ QFont font = qvariant_cast<QFont>(object->property("font"));
+ QCOMPARE(object->property("foo").toString(), font.family());
+ font.setFamily(u"Bar"_s);
+ object->setProperty("font", QVariant::fromValue(font));
+ QCOMPARE(object->property("foo").toString(), u"Bar"_s);
+}
- QScopedPointer<QObject> object(c1.create());
- QVERIFY(!object.isNull() && !c1.isError());
- QVERIFY(!object->property("aIsNull").toBool());
- QVERIFY(object->property("aIsNotNull").toBool());
- QVERIFY(object->property("aIsNotUndefined").toBool());
- QVERIFY(object->property("objectIsNotNull").toBool());
- QVERIFY(!object->property("typedArrayIsNull").toBool());
- QVERIFY(object->property("isUndefined").toBool());
- QVERIFY(!object->property("derivedIsNull").toBool());
+void tst_QmlCppCodegen::variantMapLookup()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/variantMapLookup.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("i"), 42);
+}
- QVERIFY(object->property("primitiveIsNull").toBool());
- QVERIFY(object->property("primitiveIsDefined").toBool());
- QVERIFY(object->property("primitiveIsUndefined").toBool());
+void tst_QmlCppCodegen::variantReturn()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/variantReturn.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QVERIFY(object->property("jsValueIsNull").toBool());
- QVERIFY(object->property("jsValueIsDefined").toBool());
- QVERIFY(object->property("jsValueIsUndefined").toBool());
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- QVERIFY(object->property("nullVarIsUndefined").toBool());
- QVERIFY(object->property("nullIsUndefined").toBool());
- QVERIFY(object->property("nullVarIsNull").toBool());
- QVERIFY(object->property("nullIsNotUndefined").toBool());
-};
+ QObject *a = o->property("a").value<QObject *>();
+ QVERIFY(a);
+ const QVariant x = a->property("x");
+ const QMetaObject *meta = x.metaType().metaObject();
+ QVERIFY(meta);
+ const QMetaProperty property = meta->property(meta->indexOfProperty("timeIndex"));
+ QVERIFY(property.isValid());
+ const QVariant timeIndex = property.readOnGadget(x.data());
+ QCOMPARE(timeIndex.metaType(), QMetaType::fromType<qsizetype>());
+ QCOMPARE(timeIndex.value<qsizetype>(), qsizetype(1));
-void tst_QmlCppCodegen::equalityQObjects()
+ QObject *b = o->property("b").value<QObject *>();
+ QVERIFY(b);
+ QCOMPARE(b->property("z").toInt(), 2);
+}
+
+void tst_QmlCppCodegen::variantlist()
{
QQmlEngine engine;
- QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalityQObjects.qml"_s));
- QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
- QScopedPointer<QObject> object(c1.create());
- QVERIFY(!object.isNull() && !c1.isError());
-
- QVERIFY(object->property("derivedIsNotNull").toBool());
- QVERIFY(object->property("nullObjectIsNull").toBool());
- QVERIFY(object->property("nonNullObjectIsNotNull").toBool());
- QVERIFY(object->property("compareSameObjects").toBool());
- QVERIFY(object->property("compareDifferentObjects").toBool());
- QVERIFY(object->property("compareObjectWithNullObject").toBool());
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/variantlist.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QVERIFY(object->property("nonStrict_derivedIsNotNull").toBool());
- QVERIFY(object->property("nonStrict_nullObjectIsNull").toBool());
- QVERIFY(object->property("nonStrict_nonNullObjectIsNotNull").toBool());
- QVERIFY(object->property("nonStrict_compareSameObjects").toBool());
- QVERIFY(object->property("nonStrict_compareDifferentObjects").toBool());
- QVERIFY(object->property("nonStrict_compareObjectWithNullObject").toBool());
+ const QVariantList things = qvariant_cast<QVariantList>(o->property("things"));
+ QCOMPARE(things.size(), 2);
+ QCOMPARE(things[0].toString(), u"thing"_s);
+ QCOMPARE(things[1].toInt(), 30);
}
-void tst_QmlCppCodegen::dateConversions()
+void tst_QmlCppCodegen::variantMap()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/dateConversions.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/variantMap.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- Druggeljug *ref = engine.singletonInstance<Druggeljug *>("TestTypes", "Druggeljug");
-
- const QDateTime refDate = engine.coerceValue<QDate, QDateTime>(ref->myDate());
- const QDateTime refTime = engine.coerceValue<QTime, QDateTime>(ref->myTime());
-
- QCOMPARE(o->property("date").value<QDateTime>(), refDate);
- QCOMPARE(o->property("time").value<QDateTime>(), refTime);
-
- QCOMPARE(o->property("dateString").toString(), (engine.coerceValue<QDateTime, QString>(refDate)));
- QCOMPARE(o->property("timeString").toString(), (engine.coerceValue<QDateTime, QString>(refTime)));
+ QCOMPARE(o->objectName(), "a b"_L1);
+ QCOMPARE(o->property("r"), QVariant::fromValue(QRectF(12, 13, 14, 15)));
- QMetaObject::invokeMethod(o.data(), "shuffle");
+ const QVariantMap expected = QVariantMap {
+ { u"1"_s, QVariant::fromValue<std::nullptr_t>(nullptr) },
+ { u"19"_s, QVariant::fromValue(u"19"_s) },
+ { u"25"_s, QVariant() }
+ };
- QCOMPARE(ref->myDate(), (engine.coerceValue<QDateTime, QDate>(refDate)));
- QCOMPARE(ref->myTime(), (engine.coerceValue<QDateTime, QTime>(refTime)));
+ QCOMPARE(o->property("v").toMap(), expected);
+}
- const QDate date = ref->myDate();
- const QTime time = ref->myTime();
+void tst_QmlCppCodegen::voidConversion()
+{
+ QQmlEngine engine;
+ const QUrl url(u"qrc:/qt/qml/TestTypes/voidConversion.qml"_s);
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QCOMPARE(o->property("dateString").toString(), (engine.coerceValue<QDate, QString>(date)));
- QCOMPARE(o->property("timeString").toString(), (engine.coerceValue<QTime, QString>(time)));
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + u":8: Error: Cannot assign [undefined] to QPointF"_s));
- QMetaObject::invokeMethod(o.data(), "fool");
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QCOMPARE(ref->myDate(), (engine.coerceValue<QTime, QDate>(time)));
- QCOMPARE(ref->myTime(), (engine.coerceValue<QDate, QTime>(date)));
+ QCOMPARE(o->property("p"), QPointF(20, 10));
}
-static QRegularExpression bindingLoopMessage(const QUrl &url, char var)
+void tst_QmlCppCodegen::voidFunction()
{
- // The actual string depends on how many times QObject* was registered with what parameters.
- return QRegularExpression(
- "%1:4:1: QML [^:]+: Binding loop detected for property \"%2\""_L1
- .arg(url.toString()).arg(QLatin1Char(var)));
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/voidfunction.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QVERIFY(object->objectName().isEmpty());
+ object->metaObject()->invokeMethod(object.data(), "doesNotReturnValue");
+ QCOMPARE(object->objectName(), u"barbar"_s);
}
-void tst_QmlCppCodegen::valueTypeBehavior()
+void tst_QmlCppCodegen::writeBack()
{
QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/writeback.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- const QUrl copy(u"qrc:/qt/qml/TestTypes/valueTypeCopy.qml"_s);
+ Person *person = qobject_cast<Person *>(object.data());
+ QVERIFY(person);
+ QCOMPARE(person->area(), QRectF(4, 5, 16, 17));
+ QCOMPARE(person->property("inner").toInt(), 99);
- QQmlComponent c1(&engine, copy);
- QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
- QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(copy, 'e'));
- QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(copy, 'f'));
- QScopedPointer<QObject> o1(c1.create());
- QVERIFY(!o1.isNull());
- QCOMPARE(o1->property("e").toDouble(), 45.0);
- QCOMPARE(o1->property("f").toDouble(), 1.0);
+ Person *shadowable = person->property("shadowable").value<Person *>();
+ QVERIFY(shadowable);
+ QCOMPARE(shadowable->area(), QRectF(40, 50, 16, 17));
- const QUrl reference(u"qrc:/qt/qml/TestTypes/valueTypeReference.qml"_s);
- QQmlComponent c2(&engine, reference);
- QVERIFY2(c2.isReady(), qPrintable(c2.errorString()));
- QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(reference, 'e'));
- QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(reference, 'f'));
- QScopedPointer<QObject> o2(c2.create());
- QVERIFY(!o2.isNull());
- QVERIFY(qIsNaN(o2->property("e").toDouble()));
- QCOMPARE(o2->property("f").toDouble(), 5.0);
+ QCOMPARE(person->property("ints"), QVariant::fromValue(QList<int>({12, 22, 2, 1, 0, 0, 33})));
}
-void tst_QmlCppCodegen::invisibleSingleton()
+void tst_QmlCppCodegen::writeVariantMap()
{
QQmlEngine engine;
- const QUrl copy(u"qrc:/qt/qml/TestTypes/hidden/Main.qml"_s);
- QQmlComponent c(&engine, copy);
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/StringBuilderTestTypes/writeVariantMap.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ const QVariantMap v = object->property("data").toMap();
+ QCOMPARE(v.size(), 1);
+ const QVariant textPlain = v[u"text/plain"_s];
+ QCOMPARE(textPlain.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(textPlain.toString(), u"%Drag Me%"_s);
- QTest::ignoreMessage(
- QtWarningMsg,
- "qrc:/qt/qml/TestTypes/hidden/Main.qml:4:5: "
- "Unable to assign [undefined] to QColor");
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- QCOMPARE(o->property("c"), QVariant(QMetaType::fromName("QColor")));
}
QTEST_MAIN(tst_QmlCppCodegen)
diff --git a/tests/auto/qml/qmldiskcache/CMakeLists.txt b/tests/auto/qml/qmldiskcache/CMakeLists.txt
index b6fd92d653..e47d2a7f75 100644
--- a/tests/auto/qml/qmldiskcache/CMakeLists.txt
+++ b/tests/auto/qml/qmldiskcache/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmldiskcache Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmldiskcache LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qmldiskcache
SOURCES
tst_qmldiskcache.cpp
diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
index 19a6731ff7..810fdecafd 100644
--- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
+++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
@@ -34,12 +34,18 @@ private slots:
void recompileAfterDirectoryChange();
void fileSelectors();
void localAliases();
+ void aliasToAlias();
void cacheResources();
void stableOrderOfDependentCompositeTypes();
void singletonDependency();
void cppRegisteredSingletonDependency();
void cacheModuleScripts();
void reuseStaticMappings();
+ void invalidateSaveLoadCache();
+ void duplicateIdsInInlineComponents();
+
+ void inlineComponentDoesNotCauseConstantInvalidation_data();
+ void inlineComponentDoesNotCauseConstantInvalidation();
private:
QDir m_qmlCacheDirectory;
@@ -98,7 +104,7 @@ struct TestCompiler
{
closeMapping();
testFilePath = baseDirectory + QStringLiteral("/test.qml");
- cacheFilePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ cacheFilePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(
QUrl::fromLocalFile(testFilePath));
mappedFile.setFileName(cacheFilePath);
}
@@ -170,7 +176,7 @@ struct TestCompiler
return false;
}
- const QString targetCacheFilePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ const QString targetCacheFilePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(
QUrl::fromLocalFile(targetTestFilePath));
QFile source(cacheFilePath);
@@ -197,16 +203,14 @@ struct TestCompiler
{
const QString path = fileName.isEmpty() ? testFilePath : tempDir.path() + "/" + fileName;
- QQmlRefPointer<QV4::ExecutableCompilationUnit> unit
- = QV4::ExecutableCompilationUnit::create();
+ auto unit = QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>();
return unit->loadFromDisk(QUrl::fromLocalFile(path),
QFileInfo(path).lastModified(), &lastErrorString);
}
quintptr unitData()
{
- QQmlRefPointer<QV4::ExecutableCompilationUnit> unit
- = QV4::ExecutableCompilationUnit::create();
+ auto unit = QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>();
return unit->loadFromDisk(QUrl::fromLocalFile(testFilePath),
QFileInfo(testFilePath).lastModified(), &lastErrorString)
? quintptr(unit->unitData())
@@ -289,12 +293,12 @@ void tst_qmldiskcache::loadLocalAsFallback()
f.write(reinterpret_cast<const char *>(&unit), sizeof(unit));
}
- QQmlRefPointer<QV4::ExecutableCompilationUnit> unit = QV4::ExecutableCompilationUnit::create();
+ auto unit = QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>();
bool loaded = unit->loadFromDisk(QUrl::fromLocalFile(testCompiler.testFilePath),
QFileInfo(testCompiler.testFilePath).lastModified(),
&testCompiler.lastErrorString);
QVERIFY2(loaded, qPrintable(testCompiler.lastErrorString));
- QCOMPARE(unit->objectCount(), 1);
+ QCOMPARE(unit->qmlData->nObjects, 1u);
}
void tst_qmldiskcache::regenerateAfterChange()
@@ -606,7 +610,7 @@ void tst_qmldiskcache::fileSelectors()
QVERIFY(!obj.isNull());
QCOMPARE(obj->property("value").toInt(), 42);
- QFile cacheFile(QV4::ExecutableCompilationUnit::localCacheFilePath(
+ QFile cacheFile(QV4::CompiledData::CompilationUnit::localCacheFilePath(
QUrl::fromLocalFile(testFilePath)));
QVERIFY2(cacheFile.exists(), qPrintable(cacheFile.fileName()));
}
@@ -622,7 +626,7 @@ void tst_qmldiskcache::fileSelectors()
QVERIFY(!obj.isNull());
QCOMPARE(obj->property("value").toInt(), 100);
- QFile cacheFile(QV4::ExecutableCompilationUnit::localCacheFilePath(
+ QFile cacheFile(QV4::CompiledData::CompilationUnit::localCacheFilePath(
QUrl::fromLocalFile(selectedTestFilePath)));
QVERIFY2(cacheFile.exists(), qPrintable(cacheFile.fileName()));
}
@@ -671,6 +675,55 @@ void tst_qmldiskcache::localAliases()
}
}
+void tst_qmldiskcache::aliasToAlias()
+{
+ QQmlEngine engine;
+
+ TestCompiler testCompiler(&engine);
+ QVERIFY(testCompiler.tempDir.isValid());
+
+ const QByteArray contents = QByteArrayLiteral(R"(
+ import QML
+ QtObject {
+ id: foo
+ readonly property alias myAlias: bar.prop
+
+ property QtObject o: QtObject {
+ id: bar
+
+ property QtObject o: QtObject {
+ id: baz
+ readonly property int value: 100
+ }
+
+ readonly property alias prop: baz.value
+ }
+ }
+ )");
+
+ {
+ testCompiler.clearCache();
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+ QVERIFY2(testCompiler.verify(), qPrintable(testCompiler.lastErrorString));
+ }
+
+ {
+ CleanlyLoadingComponent component(&engine, testCompiler.testFilePath);
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QCOMPARE(obj->property("myAlias").toInt(), 100);
+ }
+
+ engine.clearComponentCache();
+
+ {
+ CleanlyLoadingComponent component(&engine, testCompiler.testFilePath);
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QCOMPARE(obj->property("myAlias").toInt(), 100);
+ }
+}
+
static QSet<QString> entrySet(const QDir &dir)
{
const auto &list = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
@@ -782,7 +835,7 @@ void tst_qmldiskcache::stableOrderOfDependentCompositeTypes()
QVERIFY2(firstDependentTypeClassName.contains("QMLTYPE"), firstDependentTypeClassName.constData());
QVERIFY2(secondDependentTypeClassName.contains("QMLTYPE"), secondDependentTypeClassName.constData());
- const QString testFileCachePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(
QUrl::fromLocalFile(testFilePath));
QVERIFY(QFile::exists(testFileCachePath));
QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified();
@@ -861,7 +914,7 @@ void tst_qmldiskcache::singletonDependency()
QCOMPARE(obj->property("value").toInt(), 42);
}
- const QString testFileCachePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(
QUrl::fromLocalFile(testFilePath));
QVERIFY(QFile::exists(testFileCachePath));
QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified();
@@ -919,7 +972,7 @@ void tst_qmldiskcache::cppRegisteredSingletonDependency()
QCOMPARE(value.toInt(), 42);
}
- const QString testFileCachePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(
QUrl::fromLocalFile(testFilePath));
QVERIFY(QFile::exists(testFileCachePath));
QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified();
@@ -961,7 +1014,8 @@ void tst_qmldiskcache::cacheModuleScripts()
auto componentPrivate = QQmlComponentPrivate::get(&component);
QVERIFY(componentPrivate);
- auto compilationUnit = componentPrivate->compilationUnit->dependentScripts.first()->compilationUnit();
+ auto compilationUnit = componentPrivate->compilationUnit->dependentScriptsPtr()
+ ->first()->compilationUnit();
QVERIFY(compilationUnit);
auto unitData = compilationUnit->unitData();
QVERIFY(unitData);
@@ -1007,6 +1061,326 @@ void tst_qmldiskcache::reuseStaticMappings()
QCOMPARE(testCompiler.unitData(), data1);
}
+class AParent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int x MEMBER x)
+public:
+ AParent(QObject *parent = nullptr) : QObject(parent) {}
+ int x = 25;
+};
+
+class BParent : public QObject
+{
+ Q_OBJECT
+
+ // Insert y before x, to change the property index of x
+ Q_PROPERTY(int y MEMBER y)
+
+ Q_PROPERTY(int x MEMBER x)
+public:
+ BParent(QObject *parent = nullptr) : QObject(parent) {}
+ int y = 13;
+ int x = 25;
+};
+
+static QString writeTempFile(
+ const QTemporaryDir &tempDir, const QString &fileName, const char *contents) {
+ QFile f(tempDir.path() + '/' + fileName);
+ const bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate);
+ Q_ASSERT(ok);
+ f.write(contents);
+ return f.fileName();
+};
+
+void tst_qmldiskcache::invalidateSaveLoadCache()
+{
+ qmlRegisterType<AParent>("Base", 1, 0, "Parent");
+ std::unique_ptr<QQmlEngine> e = std::make_unique<QQmlEngine>();
+
+ // If you store a CU to a .qmlc file at run time, the .qmlc file will contain
+ // alias entries with the encodedMetaPropertyIndex pre-resolved. That's in
+ // contrast to .qmlc files generated ahead of time. Exploit that to cause
+ // a need to recompile the file.
+
+ QTemporaryDir tempDir;
+ writeTempFile(
+ tempDir, QLatin1String("B.qml"),
+ R"(
+ import QML
+ QtObject {
+ component C: QtObject {}
+ }
+ )");
+
+ const QString fileName = writeTempFile(
+ tempDir, QLatin1String("a.qml"),
+ R"(
+ import Base
+ Parent {
+ id: self
+ property alias z: self.x
+ component C: Parent {}
+ property C c: C {}
+ property B.C d: B.C {}
+ }
+ )");
+ const QUrl url = QUrl::fromLocalFile(fileName);
+ waitForFileSystem();
+
+ {
+ QQmlComponent a(e.get(), url);
+ QVERIFY2(a.isReady(), qPrintable(a.errorString()));
+ QScopedPointer<QObject> ao(a.create());
+ QVERIFY(!ao.isNull());
+ AParent *ap = qobject_cast<AParent *>(ao.data());
+ QCOMPARE(ap->property("z").toInt(), ap->x);
+ }
+
+ QString errorString;
+ auto oldUnit = QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>();
+ QVERIFY2(oldUnit->loadFromDisk(url, QFileInfo(fileName).lastModified(), &errorString), qPrintable(errorString));
+
+ // Produce a checksum mismatch.
+ e->clearComponentCache();
+ qmlClearTypeRegistrations();
+ qmlRegisterType<BParent>("Base", 1, 0, "Parent");
+ e = std::make_unique<QQmlEngine>();
+
+ {
+ QQmlComponent b(e.get(), url);
+ QVERIFY2(b.isReady(), qPrintable(b.errorString()));
+ QScopedPointer<QObject> bo(b.create());
+ QVERIFY(!bo.isNull());
+ BParent *bp = qobject_cast<BParent *>(bo.data());
+ QCOMPARE(bp->property("z").toInt(), bp->x);
+ }
+
+ // Make it recompile again. If we ever get rid of the metaobject indices in compilation units,
+ // the above test will not test the save/load cache anymore. Therefore, in order to make really
+ // sure that we get a new CU that invalidates the save/load cache, modify the file in place.
+
+ e->clearComponentCache();
+ {
+ QFile file(fileName);
+ QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Append));
+ file.write(" ");
+ }
+ waitForFileSystem();
+
+ {
+ QQmlComponent b(e.get(), url);
+ QVERIFY2(b.isReady(), qPrintable(b.errorString()));
+ QScopedPointer<QObject> bo(b.create());
+ QVERIFY(!bo.isNull());
+ BParent *bp = qobject_cast<BParent *>(bo.data());
+ QCOMPARE(bp->property("z").toInt(), bp->x);
+ }
+
+ // Verify that the mapped unit data is actually different now.
+ // The cache should have been invalidated after all.
+ // So, now we should be able to load a freshly written CU.
+
+ auto unit = QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>();
+ QVERIFY2(unit->loadFromDisk(url, QFileInfo(fileName).lastModified(), &errorString), qPrintable(errorString));
+
+ QVERIFY(unit->unitData() != oldUnit->unitData());
+}
+
+void tst_qmldiskcache::duplicateIdsInInlineComponents()
+{
+ // Exercise the case of loading strange generalized group properties from .qmlc.
+
+ QQmlEngine engine;
+
+ TestCompiler testCompiler(&engine);
+ QVERIFY(testCompiler.tempDir.isValid());
+
+ const QByteArray contents = QByteArrayLiteral(R"(
+ import QtQml
+ QtObject {
+ component First : QtObject {
+ property QtObject aa: QtObject {
+ id: a
+ }
+ property Binding bb: Binding {
+ a.objectName: "test1"
+ }
+ }
+
+ component Second : QtObject {
+ property QtObject aa: QtObject {
+ id: a
+ }
+ property Binding bb: Binding {
+ a.objectName: "test2"
+ }
+
+ property Component cc: QtObject {
+ property QtObject aa: QtObject {
+ id: a
+ }
+ property Binding bb: Binding {
+ a.objectName: "test3"
+ }
+ }
+ }
+
+ property First first: First {}
+ property Second second: Second {}
+ property QtObject third: second.cc.createObject();
+
+ objectName: first.aa.objectName + second.aa.objectName + third.aa.objectName;
+ }
+ )");
+
+ {
+ testCompiler.clearCache();
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+ QVERIFY2(testCompiler.verify(), qPrintable(testCompiler.lastErrorString));
+ }
+
+ {
+ CleanlyLoadingComponent component(&engine, testCompiler.testFilePath);
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QCOMPARE(obj->objectName(), "test1test2test3");
+ }
+
+ engine.clearComponentCache();
+
+ {
+ CleanlyLoadingComponent component(&engine, testCompiler.testFilePath);
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QCOMPARE(obj->objectName(), "test1test2test3");
+ }
+}
+
+void tst_qmldiskcache::inlineComponentDoesNotCauseConstantInvalidation_data()
+{
+ QTest::addColumn<QByteArray>("code");
+
+ QTest::addRow("simple") << QByteArray(R"(
+ import QtQml
+ QtObject {
+ component Test: QtObject {
+ property int i: 28
+ }
+ property Test test: Test {
+ objectName: "foobar"
+ }
+ property int k: test.i
+ }
+ )");
+
+ QTest::addRow("with function") << QByteArray(R"(
+ import QtQml
+ QtObject {
+ component Test : QtObject {
+ id: self
+ property int i: 2
+ property alias j: self.i
+ }
+ property Test test: Test {
+ function updateValue() {}
+ objectName: 'foobar'
+ j: 28
+ }
+ property int k: test.j
+ }
+ )");
+
+ QTest::addRow("in nested") << QByteArray(R"(
+ import QtQuick
+ Item {
+ Item {
+ component Line: Item {
+ property alias endY: pathLine.y
+ Item {
+ Item {
+ id: pathLine
+ }
+ }
+ }
+ }
+ Line {
+ id: primaryLine
+ endY: 28
+ }
+ property int k: primaryLine.endY
+ }
+ )");
+
+ QTest::addRow("with revision") << QByteArray(R"(
+ import QtQuick
+ ListView {
+ Item {
+ id: scrollBar
+ }
+ delegate: Image {
+ mipmap: true
+ }
+ Item {
+ id: refreshNodesIndicator
+ }
+ property int k: delegate.createObject().mipmap ? 28 : 4
+ }
+ )");
+}
+
+void tst_qmldiskcache::inlineComponentDoesNotCauseConstantInvalidation()
+{
+ QFETCH(QByteArray, code);
+
+ QQmlEngine engine;
+
+ TestCompiler testCompiler(&engine);
+ QVERIFY(testCompiler.tempDir.isValid());
+
+ auto check = [&](){
+ QQmlComponent c(&engine, QUrl::fromLocalFile(testCompiler.testFilePath));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("k"), QVariant::fromValue<int>(28));
+ };
+
+ testCompiler.reset();
+ QVERIFY(testCompiler.writeTestFile(code));
+
+ QVERIFY(testCompiler.loadTestFile());
+
+ const quintptr data1 = testCompiler.unitData();
+ QVERIFY(data1 != 0);
+ QCOMPARE(testCompiler.unitData(), data1);
+ check();
+
+ engine.clearComponentCache();
+
+ // inline component does not invalidate cache
+ QVERIFY(testCompiler.loadTestFile());
+ QCOMPARE(testCompiler.unitData(), data1);
+ check();
+
+ testCompiler.reset();
+ QVERIFY(testCompiler.writeTestFile(R"(
+ import QtQml
+ QtObject {
+ component Test : QtObject {
+ property double d: 2
+ }
+ property Test test: Test {
+ objectName: 'foobar'
+ }
+ })"));
+ QVERIFY(testCompiler.loadTestFile());
+ const quintptr data2 = testCompiler.unitData();
+ QVERIFY(data2);
+ QVERIFY(data1 != data2);
+}
+
QTEST_MAIN(tst_qmldiskcache)
#include "tst_qmldiskcache.moc"
diff --git a/tests/auto/qml/qmlformat/CMakeLists.txt b/tests/auto/qml/qmlformat/CMakeLists.txt
index 2c908a9190..76923d66de 100644
--- a/tests/auto/qml/qmlformat/CMakeLists.txt
+++ b/tests/auto/qml/qmlformat/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmlformat Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlformat LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -24,8 +30,11 @@ qt_internal_add_test(tst_qmlformat
Qt::TestPrivate
Qt::QuickTestUtilsPrivate
TESTDATA ${test_data}
+ TIMEOUT 3000
)
+add_dependencies(tst_qmlformat Qt::qmlformat)
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qmlformat/data/Annotations.formatted.qml b/tests/auto/qml/qmlformat/data/Annotations.formatted.qml
index 92cbeb55f7..019b7f0141 100644
--- a/tests/auto/qml/qmlformat/data/Annotations.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/Annotations.formatted.qml
@@ -10,17 +10,14 @@ import QtCharts 2.0
@Pippo {
atg1: 3
}
-@Annotation2 {
-}
+@Annotation2 {}
Item {
- @Annotate {
- }
+ @Annotate {}
anchors.fill: parent
@AnnotateMore {
property int x: 5
}
- @AnnotateALot {
- }
+ @AnnotateALot {}
property variant othersSlice: 0
//![1]
@@ -79,19 +76,17 @@ Item {
@BindingAnn {
bType: 2
}
- val2: Item {
- }
+ val2: Item {}
@BindingAnn {
bType: 3
}
val3: [
- Item {
- }
+ Item {}
]
@BindingAnn {
bType: 4
}
- Animation on val {
+ Animation on val {
duration: 34
}
}
diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml
index 8b181f607e..b1662e8898 100644
--- a/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml
+++ b/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml
@@ -43,7 +43,7 @@ Item {
property bool some_bool: false
// This comment is related to the property animation
- PropertyAnimation on x {
+ PropertyAnimation on x {
id: foo2
x: 3
y: x + 3
@@ -54,6 +54,7 @@ Item {
// Another orphan
// More orphans
+
property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
property bool something_computed: function (x) {
const PI = 3, DAYS_PER_YEAR = 365.25;
@@ -124,6 +125,7 @@ Item {
}
// Another orphan inside something_computed
+
return "foobar";
}()
@@ -133,11 +135,9 @@ Item {
// This is an orphan
// This is a cool text
- Text {
- },
+ Text {},
// This is a cool rectangle
- Rectangle {
- }
+ Rectangle {}
]
// some_read_only_bool
diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.qml
index cb8865d94e..c4aef78924 100644
--- a/tests/auto/qml/qmlformat/data/Example1.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/Example1.formatted.qml
@@ -43,7 +43,7 @@ Item {
property bool some_bool: false
// This comment is related to the property animation
- PropertyAnimation on x {
+ PropertyAnimation on x {
id: foo2
x: 3
y: x + 3
@@ -54,6 +54,7 @@ Item {
// Another orphan
// More orphans
+
property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
property bool something_computed: function (x) {
const PI = 3, DAYS_PER_YEAR = 365.25;
@@ -124,6 +125,7 @@ Item {
}
// Another orphan inside something_computed
+
return "foobar";
}()
@@ -133,11 +135,9 @@ Item {
// This is an orphan
// This is a cool text
- Text {
- },
+ Text {},
// This is a cool rectangle
- Rectangle {
- }
+ Rectangle {}
]
// some_read_only_bool
diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml
index ef964f6f60..7cea50213a 100644
--- a/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml
+++ b/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml
@@ -43,7 +43,7 @@ Item {
property bool some_bool: false
// This comment is related to the property animation
- PropertyAnimation on x {
+ PropertyAnimation on x {
id: foo2
x: 3
y: x + 3
@@ -54,6 +54,7 @@ Item {
// Another orphan
// More orphans
+
property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
property bool something_computed: function (x) {
const PI = 3, DAYS_PER_YEAR = 365.25;
@@ -124,6 +125,7 @@ Item {
}
// Another orphan inside something_computed
+
return "foobar";
}()
@@ -133,11 +135,9 @@ Item {
// This is an orphan
// This is a cool text
- Text {
- },
+ Text {},
// This is a cool rectangle
- Rectangle {
- }
+ Rectangle {}
]
// some_read_only_bool
diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted2.qml b/tests/auto/qml/qmlformat/data/Example1.formatted2.qml
index aa662a3d5f..7049686900 100644
--- a/tests/auto/qml/qmlformat/data/Example1.formatted2.qml
+++ b/tests/auto/qml/qmlformat/data/Example1.formatted2.qml
@@ -39,6 +39,7 @@ Item {
// Another orphan
// More orphans
+
property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
property bool some_bool: false
default property bool some_default_bool: 500 % 5 !== 0 // some_default_bool
@@ -114,6 +115,7 @@ Item {
}
// Another orphan inside something_computed
+
return "foobar";
}()
@@ -140,14 +142,12 @@ Item {
// This is an orphan
// This is a cool text
- Text {
- },
+ Text {},
// This is a cool rectangle
- Rectangle {
- }
+ Rectangle {}
]
// This comment is related to the property animation
- PropertyAnimation on x {
+ PropertyAnimation on x {
id: foo2
x: 3
y: x + 3
diff --git a/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml b/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml
index 7dfe435ac0..95b4fcf4a3 100644
--- a/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml
@@ -1,4 +1,3 @@
// This comment should be directly above Item after formatting
-Item {
-}
+Item {}
diff --git a/tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml b/tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml
new file mode 100644
index 0000000000..8ae4dd7c88
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml
@@ -0,0 +1,4 @@
+Item {
+ // should keep its comma
+ property var some_array_literal: [30, 20, 0.3,]
+}
diff --git a/tests/auto/qml/qmlformat/data/arrayEndComma.qml b/tests/auto/qml/qmlformat/data/arrayEndComma.qml
new file mode 100644
index 0000000000..1aec09515c
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/arrayEndComma.qml
@@ -0,0 +1,8 @@
+Item {
+ // should keep its comma
+ property var some_array_literal: [
+ 30,
+ 20,
+ 0.3,
+ ]
+}
diff --git a/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.formatted.qml b/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.formatted.qml
new file mode 100644
index 0000000000..ac4cf97881
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.formatted.qml
@@ -0,0 +1,10 @@
+import QtQuick
+
+Item {
+ Component.onCompleted: {
+ let f = ([]) => {};
+ let g = ([a]) => {};
+ let h = ([a, b]) => {};
+ let i = ([a, ...b]) => {};
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.qml b/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.qml
new file mode 100644
index 0000000000..2a47b2f152
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.qml
@@ -0,0 +1,8 @@
+import QtQuick
+
+Item { Component.onCompleted: { let f = ([]) => {};
+ let g = ([a]) => {};
+ let h = ([a, b]) => {};
+ let i = ([a, ...b]) => {};
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/blanklinesAfterComment.formatted.qml b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.formatted.qml
new file mode 100644
index 0000000000..071e3bc69f
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.formatted.qml
@@ -0,0 +1,12 @@
+/* comment with spaces */
+
+/*
+ another comment
+ */
+//
+
+// another comment /*test */
+
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qml/qmlformat/data/blanklinesAfterComment.qml b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.qml
new file mode 100644
index 0000000000..c99415aeed
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.qml
@@ -0,0 +1,15 @@
+/* comment with spaces */
+
+/*
+ another comment
+ */
+//
+
+
+// another comment /*test */
+
+
+
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qml/qmlformat/data/class.formatted.js b/tests/auto/qml/qmlformat/data/class.formatted.js
new file mode 100644
index 0000000000..eeb1faf64e
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/class.formatted.js
@@ -0,0 +1,5 @@
+class Person {
+ constructor(name) {
+ this._name = name;
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/class.js b/tests/auto/qml/qmlformat/data/class.js
new file mode 100644
index 0000000000..116061d515
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/class.js
@@ -0,0 +1 @@
+class Person{constructor(name){this._name = name;}}
diff --git a/tests/auto/qml/qmlformat/data/commentInEnum.formatted.qml b/tests/auto/qml/qmlformat/data/commentInEnum.formatted.qml
new file mode 100644
index 0000000000..583c315c4b
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/commentInEnum.formatted.qml
@@ -0,0 +1,11 @@
+import QtQml
+
+QtObject {
+ // This to enum
+ enum Foo {
+ A = 3, // This is A
+ B, // This is B
+ C = 4, // This is C
+ D // This is D
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/commentInEnum.qml b/tests/auto/qml/qmlformat/data/commentInEnum.qml
new file mode 100644
index 0000000000..3a1b15d278
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/commentInEnum.qml
@@ -0,0 +1,12 @@
+import QtQml
+
+QtObject {
+ // This to enum
+ enum Foo {
+ A = 3, // This is A
+ B, // This is B
+ C = 4, // This is C
+ D // This is D
+ }
+
+}
diff --git a/tests/auto/qml/qmlformat/data/commentInQmlObject.formatted.qml b/tests/auto/qml/qmlformat/data/commentInQmlObject.formatted.qml
new file mode 100644
index 0000000000..749dc65b7c
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/commentInQmlObject.formatted.qml
@@ -0,0 +1,4 @@
+import QtQml
+
+// hello world
+QtObject {}
diff --git a/tests/auto/qml/qmlformat/data/commentInQmlObject.qml b/tests/auto/qml/qmlformat/data/commentInQmlObject.qml
new file mode 100644
index 0000000000..9aca637e4f
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/commentInQmlObject.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ // hello world
+}
diff --git a/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.formatted.qml b/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.formatted.qml
new file mode 100644
index 0000000000..0bfcc58179
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.formatted.qml
@@ -0,0 +1,24 @@
+import QtQml
+
+QtObject {
+
+ function evil({
+ hello = "world",
+ x = 42
+ }, [n = 42, m = 43, o = 44], {
+ destructuring,
+ is = {
+ a,
+ lot,
+ of
+ },
+ fun = 42
+ } = {
+ destructuring: 123,
+ is: {
+ x: 123
+ },
+ fun: 456
+ }) {
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.qml b/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.qml
new file mode 100644
index 0000000000..f41661ed67
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.qml
@@ -0,0 +1,9 @@
+import QtQml
+
+QtObject {
+
+ function evil({ hello = "world", x = 42 },
+ [n = 42, m = 43, o = 44],
+ { destructuring, is = {a, lot, of}, fun = 42 } = {destructuring : 123, is : {x : 123}, fun : 456}) {
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/directives.formatted.js b/tests/auto/qml/qmlformat/data/directives.formatted.js
new file mode 100644
index 0000000000..3d0a4db544
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/directives.formatted.js
@@ -0,0 +1,8 @@
+.pragma library
+.import "fun.js" as Fun
+.import Qt.test 1.0 as JsQtTest
+.import Qt.Quick as Test
+
+Fun.begin();
+Test.do_stuff();
+JsQtTest.do_stuff();
diff --git a/tests/auto/qml/qmlformat/data/directives.js b/tests/auto/qml/qmlformat/data/directives.js
new file mode 100644
index 0000000000..b8e1b785ac
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/directives.js
@@ -0,0 +1,9 @@
+
+.pragma library
+
+.import "fun.js" as Fun
+.import Qt.test 1.0 as JsQtTest
+
+
+.import Qt.Quick as Test
+Fun.begin();Test.do_stuff();JsQtTest.do_stuff();
diff --git a/tests/auto/qml/qmlformat/data/directivesWithComments.formatted.js b/tests/auto/qml/qmlformat/data/directivesWithComments.formatted.js
new file mode 100644
index 0000000000..c130f72453
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/directivesWithComments.formatted.js
@@ -0,0 +1,6 @@
+.pragma library // use as library
+/*
+ Fun is necessary
+ */
+.import "fun.js" as Fun
+.import Qt.test 1.0 as JsQtTest // yet another comment not to be lost
diff --git a/tests/auto/qml/qmlformat/data/directivesWithComments.js b/tests/auto/qml/qmlformat/data/directivesWithComments.js
new file mode 100644
index 0000000000..7206bb27ed
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/directivesWithComments.js
@@ -0,0 +1,8 @@
+
+.pragma library // use as library
+
+/*
+ Fun is necessary
+ */
+.import "fun.js" as Fun
+.import Qt.test 1.0 as JsQtTest // yet another comment not to be lost
diff --git a/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml b/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml
index 0c7a2829c9..8eaac71178 100644
--- a/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml
@@ -1,13 +1,15 @@
Item {
- property var test: [{
+ property var test: [
+ {
// Testing
"foo": "bar"
- }]
+ }
+ ]
onTestChanged: {
fooBar(test, {
- // Testing
- "foo": "bar"
- });
+ // Testing
+ "foo": "bar"
+ });
}
}
diff --git a/tests/auto/qml/qmlformat/data/dontRemoveComments.qml b/tests/auto/qml/qmlformat/data/dontRemoveComments.qml
index 1797834879..2d2b4b6705 100644
--- a/tests/auto/qml/qmlformat/data/dontRemoveComments.qml
+++ b/tests/auto/qml/qmlformat/data/dontRemoveComments.qml
@@ -1,8 +1,10 @@
Item {
- property var test: [{
-// Testing
+ property var test: [
+ {
+ // Testing
"foo": "bar"
- }]
+ }
+ ]
onTestChanged: {
fooBar(test, {
diff --git a/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml b/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml
index edbb12c6e6..de6a23f9c7 100644
--- a/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml
@@ -4,11 +4,13 @@ Item {
function f() {
var count = 0;
+
class Person {
constructor(name){
this._name = name;
}
}
+
class Employee extends Person {
constructor(name, age){
super(name);
diff --git a/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.formatted.qml b/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.formatted.qml
new file mode 100644
index 0000000000..f41942e054
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.formatted.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+QtObject {
+
+ function patron(a, ...b) {
+ }
+
+ function patron1(a, ...[b, ...args]) {
+ }
+
+ function patron2(...{}) {
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.qml b/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.qml
new file mode 100644
index 0000000000..28364f29c9
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.qml
@@ -0,0 +1,11 @@
+import QtQml
+
+QtObject {
+
+ function patron(a, ...b) {
+ }
+
+ function patron1(a, ...[b, ...args]) {}
+
+ function patron2(...{}) {}
+} \ No newline at end of file
diff --git a/tests/auto/qml/qmlformat/data/enumWithValues.formatted.qml b/tests/auto/qml/qmlformat/data/enumWithValues.formatted.qml
new file mode 100644
index 0000000000..bbf978936f
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/enumWithValues.formatted.qml
@@ -0,0 +1,12 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Rectangle {
+ enum AxisAlignment {
+ Bottom = 0,
+ Left = 1,
+ Right = 2
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/enumWithValues.qml b/tests/auto/qml/qmlformat/data/enumWithValues.qml
new file mode 100644
index 0000000000..2dbe7fbac5
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/enumWithValues.qml
@@ -0,0 +1,12 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Rectangle{
+enum AxisAlignment{
+Bottom = 0,
+Left = 1,
+Right = 2
+}
+}
diff --git a/tests/auto/qml/qmlformat/data/escapeChars.formatted.qml b/tests/auto/qml/qmlformat/data/escapeChars.formatted.qml
new file mode 100644
index 0000000000..3f6807834f
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/escapeChars.formatted.qml
@@ -0,0 +1,16 @@
+import QtQuick
+
+Item {
+ x: {
+ const s = "\"";
+ let a = {
+ "\"": "\\"
+ };
+
+ let patron = {
+ "\\\"\n\n": "\?\?\\\"",
+ "": "",
+ "\'\"\n": 1
+ };
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/escapeChars.qml b/tests/auto/qml/qmlformat/data/escapeChars.qml
new file mode 100644
index 0000000000..c82ff3119e
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/escapeChars.qml
@@ -0,0 +1,16 @@
+import QtQuick
+
+Item {
+ x: {
+ const s = "\""
+ let a = {
+ "\"": "\\"
+ };
+
+ let patron = {
+ "\\\"\n\n" : "\?\?\\\"","": "", "\'\"\n":1
+ };
+
+
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/esm.formatted.mjs b/tests/auto/qml/qmlformat/data/esm.formatted.mjs
new file mode 100644
index 0000000000..f0b3fd7753
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/esm.formatted.mjs
@@ -0,0 +1,44 @@
+//Imports
+import defaultExport from "module-name";
+import * as name from "module-name";
+import { export1 } from "module-name";
+import { export1 as alias1 } from "module-name";
+import { default as alias } from "module-name";
+import { export1, export2 } from "module-name";
+import { export1, export2 as alias2 } from "module-name";
+import defaultExport, { export1, a } from "module-name";
+import defaultExport, * as name from "module-name";
+import "module-name";
+
+// Exporting declarations
+export let name1, name2; // also var
+export const name1 = 1, name2 = 2; // also var, let
+export function functionName() {}
+export class ClassName {
+ constructor(h){
+ this.h = h;
+ }
+}
+export function* generatorFunctionName() {}
+export const {
+ name1,
+ name2: bar
+} = o;
+export const [name1, name2] = array;
+
+// Export list
+export { name1, nameN };
+export { variable1 as name1, variable2 as name2, nameN };
+export { name1 as default };
+
+// Default exports
+export default function* generatorFunctionName() {
+ return 1;
+}
+
+// Aggregating modules
+export * from "module-name";
+export { name1, nameN } from "module-name";
+export { import1 as name1, import2 as name2, nameN } from "module-name";
+export { default } from "module-name";
+export { default as name1 } from "module-name";
diff --git a/tests/auto/qml/qmlformat/data/esm.mjs b/tests/auto/qml/qmlformat/data/esm.mjs
new file mode 100644
index 0000000000..83e22fdedd
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/esm.mjs
@@ -0,0 +1,33 @@
+//Imports
+import defaultExport from "module-name";
+import * as name from "module-name"
+import {export1} from "module-name";
+import { export1 as alias1 } from "module-name";
+import { default as alias } from "module-name"
+import { export1, export2 } from "module-name";
+import {export1,export2 as alias2} from "module-name";
+import defaultExport,{export1,a} from "module-name"
+import defaultExport, * as name from "module-name";
+import "module-name";
+
+
+// Exporting declarations
+export let name1,name2; // also var
+export const name1=1,name2=2 // also var, let
+export function functionName() {}
+export class ClassName{constructor(h){this.h=h;}}
+export function* generatorFunctionName() {}
+export const {name1, name2: bar}=o;export const [name1,name2]=array
+
+// Export list
+export {name1,nameN};export {variable1 as name1,variable2 as name2,nameN }
+export {name1 as default};
+
+// Default exports
+export default function* generatorFunctionName() {return 1;}
+
+// Aggregating modules
+export * from "module-name";
+export { name1,nameN} from "module-name"
+export { import1 as name1, import2 as name2,nameN } from "module-name";export { default, } from "module-name";
+export { default as name1 } from "module-name";
diff --git a/tests/auto/qml/qmlformat/data/filesOption/valid1.formatted.qml b/tests/auto/qml/qmlformat/data/filesOption/valid1.formatted.qml
new file mode 100644
index 0000000000..a995f0479f
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/filesOption/valid1.formatted.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ property int a
+ function aa() {
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/filesOption/valid1.qml b/tests/auto/qml/qmlformat/data/filesOption/valid1.qml
new file mode 100644
index 0000000000..8aef366bd9
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/filesOption/valid1.qml
@@ -0,0 +1,9 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+property int a
+function aa(){}
+} \ No newline at end of file
diff --git a/tests/auto/qml/qmlformat/data/filesOption/valid2.formatted.qml b/tests/auto/qml/qmlformat/data/filesOption/valid2.formatted.qml
new file mode 100644
index 0000000000..a995f0479f
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/filesOption/valid2.formatted.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ property int a
+ function aa() {
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/filesOption/valid2.qml b/tests/auto/qml/qmlformat/data/filesOption/valid2.qml
new file mode 100644
index 0000000000..f2cb636c00
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/filesOption/valid2.qml
@@ -0,0 +1,9 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ property int a
+ function aa() {}
+}
diff --git a/tests/auto/qml/qmlformat/data/forOf.formatted.qml b/tests/auto/qml/qmlformat/data/forOf.formatted.qml
index fa9ff9c631..0cc4f9fecd 100644
--- a/tests/auto/qml/qmlformat/data/forOf.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/forOf.formatted.qml
@@ -3,6 +3,7 @@ import QtQml 2.0
QtObject {
Component.onCompleted: {
var list = [[1, 2], [3, 4], [5, 6]];
+
for (const [x, y] of list)
console.log("X: " + x + "; Y: " + y);
for (let [x, y] of list)
diff --git a/tests/auto/qml/qmlformat/data/functionsSpacing.formatted.qml b/tests/auto/qml/qmlformat/data/functionsSpacing.formatted.qml
index d452ba2b8c..91f520b5fc 100644
--- a/tests/auto/qml/qmlformat/data/functionsSpacing.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/functionsSpacing.formatted.qml
@@ -6,8 +6,7 @@ Item {
}
function test2() {
}
- Button {
- }
+ Button {}
function test4() {
}
diff --git a/tests/auto/qml/qmlformat/data/importStatements.formatted.qml b/tests/auto/qml/qmlformat/data/importStatements.formatted.qml
new file mode 100644
index 0000000000..6613becaca
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/importStatements.formatted.qml
@@ -0,0 +1,8 @@
+import QtQml
+
+import QtQuick
+import QtQuick.Controls
+
+import org.test.module
+
+QtObject {}
diff --git a/tests/auto/qml/qmlformat/data/importStatements.qml b/tests/auto/qml/qmlformat/data/importStatements.qml
new file mode 100644
index 0000000000..efe1872e93
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/importStatements.qml
@@ -0,0 +1,12 @@
+import QtQml
+
+
+import QtQuick
+import QtQuick.Controls
+
+import org.test.module
+
+
+
+QtObject {
+}
diff --git a/tests/auto/qml/qmlformat/data/javascriptBlock.formatted.qml b/tests/auto/qml/qmlformat/data/javascriptBlock.formatted.qml
new file mode 100644
index 0000000000..09ab9454e1
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/javascriptBlock.formatted.qml
@@ -0,0 +1,6 @@
+Item {
+ block1: {
+ console.log("Hello, world!");
+ }
+ emptyBlock: {}
+}
diff --git a/tests/auto/qml/qmlformat/data/javascriptBlock.qml b/tests/auto/qml/qmlformat/data/javascriptBlock.qml
new file mode 100644
index 0000000000..1665c81f42
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/javascriptBlock.qml
@@ -0,0 +1,5 @@
+Item {
+ block1: {console.log("Hello, world!");}
+ emptyBlock: {
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.formatted.js b/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.formatted.js
new file mode 100644
index 0000000000..62a5e36f5e
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.formatted.js
@@ -0,0 +1,6 @@
+var b = function () {
+ var a = 1;
+ for (var ii = 1; ii < 10; ++ii) {
+ a = a * ii;
+ }
+};
diff --git a/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.js b/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.js
new file mode 100644
index 0000000000..0155cff7f9
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.js
@@ -0,0 +1 @@
+var b=function(){var a=1;for(var ii=1;ii<10;++ii){a=a*ii;}}
diff --git a/tests/auto/qml/qmlformat/data/lambdaWithIfElse.formatted.js b/tests/auto/qml/qmlformat/data/lambdaWithIfElse.formatted.js
new file mode 100644
index 0000000000..3bc7f683c4
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/lambdaWithIfElse.formatted.js
@@ -0,0 +1,7 @@
+var f = function () {
+ if (true) {
+ console.log("true");
+ } else {
+ console.log("false");
+ }
+};
diff --git a/tests/auto/qml/qmlformat/data/lambdaWithIfElse.js b/tests/auto/qml/qmlformat/data/lambdaWithIfElse.js
new file mode 100644
index 0000000000..aaf731e5f0
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/lambdaWithIfElse.js
@@ -0,0 +1 @@
+var f = function(){if(true){ console.log("true");} else {console.log("false");}}
diff --git a/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.formatted.js b/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.formatted.js
new file mode 100644
index 0000000000..99db6fb372
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.formatted.js
@@ -0,0 +1,9 @@
+var l = function () {
+ var nl = function () {
+ if (true) {
+ console.log("true");
+ } else {
+ console.log("false");
+ }
+ };
+};
diff --git a/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.js b/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.js
new file mode 100644
index 0000000000..23ae087b04
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.js
@@ -0,0 +1 @@
+var l = function(){var nl = function(){if(true){console.log("true");}else{console.log("false");}};};
diff --git a/tests/auto/qml/qmlformat/data/messyIfStatement.formatted.js b/tests/auto/qml/qmlformat/data/messyIfStatement.formatted.js
new file mode 100644
index 0000000000..cd7d75314c
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/messyIfStatement.formatted.js
@@ -0,0 +1,4 @@
+if (((typeof ezJsu !== 'undefined') && ezJsu === true) || ((typeof _ez_sa !== 'undefined') && _ez_sa === true)) {
+ a.defaultStoreUrl = '//g.ezoic.net/ezoic/imp.gif';
+ a.defaultStoreA = '//g.ezoic.net/ezoic/i.gif';// Single Line Comments here
+}
diff --git a/tests/auto/qml/qmlformat/data/messyIfStatement.js b/tests/auto/qml/qmlformat/data/messyIfStatement.js
new file mode 100644
index 0000000000..cdd4c7bd9d
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/messyIfStatement.js
@@ -0,0 +1,2 @@
+if (((typeof ezJsu!=='undefined')&&ezJsu===true)||((typeof _ez_sa !=='undefined')&&_ez_sa === true)) {a.defaultStoreUrl='//g.ezoic.net/ezoic/imp.gif';a.defaultStoreA ='//g.ezoic.net/ezoic/i.gif';// Single Line Comments here
+}
diff --git a/tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs b/tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs
new file mode 100644
index 0000000000..37f8ccb698
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs
@@ -0,0 +1,20 @@
+//Imports
+import defaultExport from "module-name";
+import "module-name";
+export class ClassName {
+ constructor(h){
+ this.h = h;
+ }
+}
+export const {
+ n1,
+ n3,
+ n4,
+ name2: bar
+} = o;
+export const [name1, name2] = array;
+function stuff() {
+ var l = () => {
+ 1 + 1;
+ };
+}
diff --git a/tests/auto/qml/qmlformat/data/mini_esm.mjs b/tests/auto/qml/qmlformat/data/mini_esm.mjs
new file mode 100644
index 0000000000..9d6c2406dc
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/mini_esm.mjs
@@ -0,0 +1,3 @@
+//Imports
+import defaultExport from "module-name";import "module-name";export class ClassName{constructor(h){this.h=h;}}
+export const {n1,n3,n4,name2:bar}=o;export const [name1,name2]=array;function stuff(){var l=()=>{1+1};};
diff --git a/tests/auto/qml/qmlformat/data/multilineComment.formatted.qml b/tests/auto/qml/qmlformat/data/multilineComment.formatted.qml
index 45d04c5887..46e3e963ea 100644
--- a/tests/auto/qml/qmlformat/data/multilineComment.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/multilineComment.formatted.qml
@@ -1,11 +1,9 @@
Item {
- Item {
- }
+ Item {}
/* This is a multiline comment.
it should stay attached to Commented instead of getting orphaned.
*/
// This should also stick to Commented
- Commented {
- }
+ Commented {}
}
diff --git a/tests/auto/qml/qmlformat/data/nestedFunctions.formatted.qml b/tests/auto/qml/qmlformat/data/nestedFunctions.formatted.qml
index 5536ecf513..fc1915f647 100644
--- a/tests/auto/qml/qmlformat/data/nestedFunctions.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/nestedFunctions.formatted.qml
@@ -1,11 +1,13 @@
Item {
function a() {
function nested() {}
+
foo();
}
function b() {
function nested() {}
+
bar();
}
}
diff --git a/tests/auto/qml/qmlformat/data/nestedIf.formatted.qml b/tests/auto/qml/qmlformat/data/nestedIf.formatted.qml
index 4ff5a40a23..ebb125f36d 100644
--- a/tests/auto/qml/qmlformat/data/nestedIf.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/nestedIf.formatted.qml
@@ -26,6 +26,7 @@ Item {
x();
}
}
+
if (x && y)
if (x < y)
return 0;
diff --git a/tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml b/tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml
new file mode 100644
index 0000000000..94e97076b1
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml
@@ -0,0 +1,137 @@
+import QtQml
+
+QtObject {
+
+ function set1() {
+ const array = [1, 2, 3, 4];
+ const [a, b] = [1, 2];
+ const [aa, , bb] = array;
+ const [aaa = 23, bbb] = array;
+ const [a1, b1, ...rest1] = array;
+ const [a2, , b2, ...rest2] = array;
+ const [a3, b3, ...{
+ pop,
+ push
+ }] = array;
+ const [a4, b4, ...[c, d]] = array;
+
+ const obj = {
+ _a: 1,
+ _b: 2
+ };
+ const {
+ a5,
+ b5
+ } = obj;
+ const {
+ a6: a_,
+ b6: b1_
+ } = obj;
+ const {
+ a7: a11 = 4,
+ b11 = 34,
+ c1: b111,
+ d1
+ } = obj;
+ let key = a;
+ const {
+ [key]: a___
+ } = obj;
+ }
+
+ function set2() {
+ // declare first
+ let a, b, a1, b1, c, d, rest, pop, push;
+ const array = [1, 2, 3, 4];
+ [a, b] = array;
+ [a, , b] = array;
+ [a = aDefault, b] = array;
+ [a, b, ...rest] = array;
+ [a, , b, ...rest] = array;
+ [a, b, ...{
+ pop,
+ push
+ }] = array;
+ [a, b, ...[c, d]] = array;
+
+ const obj = {
+ _a: 1,
+ _b: 2
+ };
+ ({
+ a,
+ b
+ } = obj); // brackets are required
+ ({
+ a: a1,
+ b: b1
+ } = obj);
+
+ const complicatedObject = {
+ a: 1,
+ b: {
+ c: 2,
+ d: {
+ e: 3,
+ f: [4, 5, 6]
+ }
+ },
+ g: [7, 8, 9]
+ };
+
+ const {
+ patron,
+ b: {
+ mafik,
+ d: {
+ e,
+ f: [, secondF, ...restF]
+ }
+ },
+ g: [firstG, ...restG]
+ } = complicatedObject;
+ }
+
+ Component.onCompleted: {
+ const myFunction = myLambda => {
+ const myObject = {
+ a: 1,
+ b: {
+ c: 2,
+ d: [3, 4, 5]
+ },
+ e: {
+ f: 6,
+ g: {
+ h: 7,
+ i: [8, 9, 10]
+ }
+ }
+ };
+
+ myLambda(myObject);
+ };
+
+ myFunction(({
+ a,
+ b: {
+ c,
+ d: [firstD]
+ },
+ e: {
+ f,
+ g: {
+ h,
+ i: [, secondI]
+ }
+ }
+ }) => {
+ console.log(a); // 1
+ console.log(c); // 2
+ console.log(firstD); // 3
+ console.log(f); // 6
+ console.log(h); // 7
+ console.log(secondI); // 9
+ });
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/objectDestructuring.qml b/tests/auto/qml/qmlformat/data/objectDestructuring.qml
new file mode 100644
index 0000000000..0487153125
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/objectDestructuring.qml
@@ -0,0 +1,77 @@
+import QtQml
+
+QtObject {
+
+ function set1() {
+ const array = [1,2,3,4];
+ const [a, b] = [1,2];
+ const [aa, , bb] = array;
+ const [aaa = 23, bbb] = array;
+ const [a1, b1, ...rest1] = array;
+ const [a2, , b2, ...rest2] = array;
+ const [a3, b3, ...{ pop, push }] = array;
+ const [a4, b4, ...[c, d]] = array;
+
+ const obj = {_a:1,_b:2};
+ const { a5, b5 } = obj;
+ const { a6: a_, b6: b1_ } = obj;
+ const { a7: a11 = 4, b11 = 34, c1: b111, d1 } = obj;
+ let key = a;
+ const { [key]: a___ } = obj;
+ }
+
+ function set2() {
+ // declare first
+ let a, b, a1, b1, c, d, rest, pop, push;
+ const array = [1,2,3,4];
+ [a, b] = array;
+ [a, , b] = array;
+ [a = aDefault, b] = array;
+ [a, b, ...rest] = array;
+ [a, , b, ...rest] = array;
+ [a, b, ...{ pop, push }] = array;
+ [a, b, ...[c, d]] = array;
+
+ const obj = {_a:1,_b:2};
+ ({ a, b } = obj); // brackets are required
+ ({ a: a1, b: b1 } = obj);
+
+ const complicatedObject = {
+ a: 1,
+ b: {
+ c: 2,
+ d: {
+ e: 3,
+ f: [4, 5, 6]
+ }
+ },
+ g: [7, 8, 9]
+ };
+
+ const { patron, b: { mafik, d: { e, f: [ , secondF, ...restF ] } }, g: [ firstG, ...restG ] } = complicatedObject;
+ }
+
+ Component.onCompleted: {
+ const myFunction = (myLambda) => {
+ const myObject = {
+ a: 1,
+ b: {c: 2, d: [3, 4, 5] }, e: {
+ f: 6,
+ g: { h: 7, i: [8, 9, 10]
+ }
+ }
+ };
+
+ myLambda(myObject);
+ };
+
+ myFunction(({ a, b: { c, d: [ firstD ] }, e: { f, g: { h, i: [ , secondI ] } } }) => {
+ console.log(a); // 1
+ console.log(c); // 2
+ console.log(firstD); // 3
+ console.log(f); // 6
+ console.log(h); // 7
+ console.log(secondI); // 9
+ });
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/objectsSpacing.formatted.qml b/tests/auto/qml/qmlformat/data/objectsSpacing.formatted.qml
index bd0406e595..df26a9b599 100644
--- a/tests/auto/qml/qmlformat/data/objectsSpacing.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/objectsSpacing.formatted.qml
@@ -1,6 +1,9 @@
Item {
+ Button {}
+
Button {
+ id: foo
}
height: 360
diff --git a/tests/auto/qml/qmlformat/data/objectsSpacing.qml b/tests/auto/qml/qmlformat/data/objectsSpacing.qml
index 6adc89778c..0239b05145 100644
--- a/tests/auto/qml/qmlformat/data/objectsSpacing.qml
+++ b/tests/auto/qml/qmlformat/data/objectsSpacing.qml
@@ -3,6 +3,10 @@ Item {
Button {
}
+ Button {
+ id: foo
+ }
+
height: 360
width: 360
diff --git a/tests/auto/qml/qmlformat/data/pragma.formatted.js b/tests/auto/qml/qmlformat/data/pragma.formatted.js
new file mode 100644
index 0000000000..3f57e537ac
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/pragma.formatted.js
@@ -0,0 +1,4 @@
+"use strict";
+{
+ function f() {}
+}
diff --git a/tests/auto/qml/qmlformat/data/pragma.formatted.qml b/tests/auto/qml/qmlformat/data/pragma.formatted.qml
new file mode 100644
index 0000000000..143db39888
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/pragma.formatted.qml
@@ -0,0 +1,8 @@
+pragma Singleton
+pragma ComponentBehavior: Bound
+pragma FunctionSignatureBehavior: Enforced
+pragma ValueTypeBehavior: Copy, Addressable
+
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qml/qmlformat/data/pragma.js b/tests/auto/qml/qmlformat/data/pragma.js
new file mode 100644
index 0000000000..b81d52d853
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/pragma.js
@@ -0,0 +1 @@
+"use strict";{function f(){}}
diff --git a/tests/auto/qml/qmlformat/data/pragma.qml b/tests/auto/qml/qmlformat/data/pragma.qml
new file mode 100644
index 0000000000..7469277395
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/pragma.qml
@@ -0,0 +1,8 @@
+pragma Singleton
+ pragma ComponentBehavior: Bound
+ pragma FunctionSignatureBehavior: Enforced
+pragma ValueTypeBehavior: Copy, Addressable
+
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qml/qmlformat/data/propertyNames.formatted.qml b/tests/auto/qml/qmlformat/data/propertyNames.formatted.qml
index 94b5877957..9214014889 100644
--- a/tests/auto/qml/qmlformat/data/propertyNames.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/propertyNames.formatted.qml
@@ -3,11 +3,11 @@ Item {
var copiedItem = "copied value";
var computedItem = "computedName";
var obj = {
- "identifierName": "identifier value",
+ identifierName: "identifier value",
"string name": "string value",
- "Infinity": "numeric value",
+ Infinity: "numeric value",
[computedItem]: "computed value",
- "copiedItem": copiedItem
+ copiedItem
};
}
}
diff --git a/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml b/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml
index b9bcc34e8c..767bfe7e61 100644
--- a/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml
+++ b/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml
@@ -1 +1 @@
-/* This file is licensed under the not a license license 1. You may not comply 2. Goodbye */ // Importing this is very important import QtQuick 5.15 // Muddling the waters! import QtQuick.Models 3.14 as muddle // Importing that is important too import Z import That import This // THIS IS VERY IMPORTANT! import Y import X.Z import X.Y import A.LLOHA import A.B.B.A // This comment is related to Item Item { // This to id // Also id. (line 2) // This is the third id // fourth id comment id: foo // This to enum enum Foo { A = 3, // This is A B, // This is B C = 4, // This is C D // This is D } // Orphan comment // Another orphan // More orphans property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3] property bool some_bool: false default property bool some_default_bool: 500 % 5 !== 0 // some_default_bool // some_read_only_bool readonly property bool some_read_only_bool: Math.sin(3) && (aFunc()[30] + 5) | 2 != 0 property bool something_computed: function (x) { const PI = 3, DAYS_PER_YEAR = 365.25; var x = 3 + 2; x["bla"] = 50; // This is an orphan inside something_computed // Are these getting duplicated? // This one to var few! var few = new WhatEver(); x += Math.sin(3); x--; --x; x++; ++x; for (var x = 0; x < 100; x++) { x++; console.log("Foo"); } for (var x in [3, 2, 1]) { y++; console.log("Bar"); } while (true) { console.log("Wee"); } with (foo) { bar; x += 5; } // This is related to with! x3: do { console.log("Hello"); } while (3 == 0) try { dangerous(); } catch (e) { console.log(e); } finally { console.log("What else?"); } switch (x) { case 0: x = 1; break; case 1: x = 5; break; case 4: x = 100; break; } if (x == 50) { console.log("true"); } else if (x == 50) { console.log("other thing"); } else { console.log("false"); } if (x == 50) { console.log("true"); } else if (x == 50) { console.log("other thing"); x--; } else { console.log("false"); } // Another orphan inside something_computed return "foobar"; }() signal say(string name, bool caps) // This one to aFunc() function aFunc() { var x = 3; return x; } x: 3 // Very cool myFavouriteThings: [ // This is an orphan // This is a cool text Text { }, // This is a cool rectangle Rectangle { } ] // This comment is related to the property animation PropertyAnimation on x { id: foo2 x: 3 y: x + 3 } Component.onCompleted: console.log("Foo!") Text { required property string batman signal boo(int count, int times, real duration) text: "Bla" } } \ No newline at end of file
+/* This file is licensed under the not a license license 1. You may not comply 2. Goodbye */ // Importing this is very important import QtQuick 5.15 // Muddling the waters! import QtQuick.Models 3.14 as muddle // Importing that is important too import Z import That import This // THIS IS VERY IMPORTANT! import Y import X.Z import X.Y import A.LLOHA import A.B.B.A // This comment is related to Item Item { // This to id // Also id. (line 2) // This is the third id // fourth id comment id: foo // This to enum enum Foo { A = 3, // This is A B, // This is B C = 4, // This is C D // This is D } // Orphan comment // Another orphan // More orphans property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3] property bool some_bool: false default property bool some_default_bool: 500 % 5 !== 0 // some_default_bool // some_read_only_bool readonly property bool some_read_only_bool: Math.sin(3) && (aFunc()[30] + 5) | 2 != 0 property bool something_computed: function (x) { const PI = 3, DAYS_PER_YEAR = 365.25; var x = 3 + 2; x["bla"] = 50; // This is an orphan inside something_computed // Are these getting duplicated? // This one to var few! var few = new WhatEver(); x += Math.sin(3); x--; --x; x++; ++x; for (var x = 0; x < 100; x++) { x++; console.log("Foo"); } for (var x in [3, 2, 1]) { y++; console.log("Bar"); } while (true) { console.log("Wee"); } with (foo) { bar; x += 5; } // This is related to with! x3: do { console.log("Hello"); } while (3 == 0) try { dangerous(); } catch (e) { console.log(e); } finally { console.log("What else?"); } switch (x) { case 0: x = 1; break; case 1: x = 5; break; case 4: x = 100; break; } if (x == 50) { console.log("true"); } else if (x == 50) { console.log("other thing"); } else { console.log("false"); } if (x == 50) { console.log("true"); } else if (x == 50) { console.log("other thing"); x--; } else { console.log("false"); } // Another orphan inside something_computed return "foobar"; }() signal say(string name, bool caps) // This one to aFunc() function aFunc() { var x = 3; return x; } x: 3 // Very cool myFavouriteThings: [ // This is an orphan // This is a cool text Text { }, // This is a cool rectangle Rectangle { } ] // This comment is related to the property animation PropertyAnimation on x { id: foo2 x: 3 y: x + 3 } Component.onCompleted: console.log("Foo!") Text { required property string batman signal boo(int count, int times, real duration) text: "Bla" } } \ No newline at end of file
diff --git a/tests/auto/qml/qmlformat/data/simpleJSStatement.formatted.js b/tests/auto/qml/qmlformat/data/simpleJSStatement.formatted.js
new file mode 100644
index 0000000000..fbdec1038c
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/simpleJSStatement.formatted.js
@@ -0,0 +1 @@
+let v = 1;
diff --git a/tests/auto/qml/qmlformat/data/simpleJSStatement.js b/tests/auto/qml/qmlformat/data/simpleJSStatement.js
new file mode 100644
index 0000000000..d954a87fc0
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/simpleJSStatement.js
@@ -0,0 +1 @@
+let v=1;
diff --git a/tests/auto/qml/qmlformat/data/simpleLoop.formatted.js b/tests/auto/qml/qmlformat/data/simpleLoop.formatted.js
new file mode 100644
index 0000000000..435fc145bf
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/simpleLoop.formatted.js
@@ -0,0 +1,4 @@
+var a = 1;
+for (var ii = 1; ii < 10; ++ii) {
+ a = a * ii;
+}
diff --git a/tests/auto/qml/qmlformat/data/simpleLoop.js b/tests/auto/qml/qmlformat/data/simpleLoop.js
new file mode 100644
index 0000000000..08b172991f
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/simpleLoop.js
@@ -0,0 +1 @@
+var a=1;for(var ii=1;ii<10;++ii){a=a*ii;}
diff --git a/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.formatted.js b/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.formatted.js
new file mode 100644
index 0000000000..d5b34291e6
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.formatted.js
@@ -0,0 +1,4 @@
+function f() {
+ let a = 0;
+ return a;
+}
diff --git a/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.js b/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.js
new file mode 100644
index 0000000000..c49be5e2bd
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.js
@@ -0,0 +1 @@
+function f(){let a=0;return a; }
diff --git a/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml b/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml
index 40cf5068da..923f0642d7 100644
--- a/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml
@@ -2,15 +2,12 @@ QtObject {
id: foo
states: [
- State {
- }
+ State {}
]
transitions: [
- Transition {
- }
+ Transition {}
]
// This needs to be *before* states and transitions after formatting
- Item {
- }
+ Item {}
}
diff --git a/tests/auto/qml/qmlformat/data/threeFunctions.formattedFuncSpacing.js b/tests/auto/qml/qmlformat/data/threeFunctions.formattedFuncSpacing.js
new file mode 100644
index 0000000000..592db7a02b
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/threeFunctions.formattedFuncSpacing.js
@@ -0,0 +1,11 @@
+function one() {
+ var a=1;
+}
+
+function two(a, b) {
+ console.log(a,b);
+}
+
+function three(c) {
+ var a=c;
+}
diff --git a/tests/auto/qml/qmlformat/data/threeFunctions.formattedTabs.js b/tests/auto/qml/qmlformat/data/threeFunctions.formattedTabs.js
new file mode 100644
index 0000000000..6575a9fbd8
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/threeFunctions.formattedTabs.js
@@ -0,0 +1,9 @@
+function one() {
+ var a = 1;
+}
+function two(a, b) {
+ console.log(a, b);
+}
+function three(c) {
+ var a = c;
+}
diff --git a/tests/auto/qml/qmlformat/data/threeFunctions.formattedW2.js b/tests/auto/qml/qmlformat/data/threeFunctions.formattedW2.js
new file mode 100644
index 0000000000..afcf8acf02
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/threeFunctions.formattedW2.js
@@ -0,0 +1,9 @@
+function one() {
+ var a = 1;
+}
+function two(a, b) {
+ console.log(a, b);
+}
+function three(c) {
+ var a = c;
+}
diff --git a/tests/auto/qml/qmlformat/data/threeFunctionsOneLine.js b/tests/auto/qml/qmlformat/data/threeFunctionsOneLine.js
new file mode 100644
index 0000000000..648591f221
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/threeFunctionsOneLine.js
@@ -0,0 +1 @@
+function one() {var a=1;}function two(a, b) {console.log(a,b);}function three(c){var a=c;}
diff --git a/tests/auto/qml/qmlformat/data/twoFunctions.formatted.js b/tests/auto/qml/qmlformat/data/twoFunctions.formatted.js
new file mode 100644
index 0000000000..b7414de053
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/twoFunctions.formatted.js
@@ -0,0 +1,12 @@
+function one() {
+ var a = 1;
+ if (a === true) {
+ a = 5;
+ }
+}
+
+function two(a, b) {
+ for (; b < 5; ++b) {
+ a = a * b;
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/twoFunctions.js b/tests/auto/qml/qmlformat/data/twoFunctions.js
new file mode 100644
index 0000000000..b410ebd167
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/twoFunctions.js
@@ -0,0 +1,3 @@
+function one(){var a=1;if (a===true){a=5;}}
+
+function two(a,b){for(;b<5;++b){a=a*b;}}
diff --git a/tests/auto/qml/qmlformat/tst_qmlformat.cpp b/tests/auto/qml/qmlformat/tst_qmlformat.cpp
index c14dd794fc..11d4c9d2c7 100644
--- a/tests/auto/qml/qmlformat/tst_qmlformat.cpp
+++ b/tests/auto/qml/qmlformat/tst_qmlformat.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QDir>
@@ -16,6 +16,25 @@
using namespace QQmlJS::Dom;
+// TODO refactor extension helpers
+const QString QML_EXT = ".qml";
+const QString JS_EXT = ".js";
+const QString MJS_EXT = ".mjs";
+
+static QStringView fileExt(QStringView filename)
+{
+ if (filename.endsWith(QML_EXT)) {
+ return QML_EXT;
+ }
+ if (filename.endsWith(JS_EXT)) {
+ return JS_EXT;
+ }
+ if (filename.endsWith(MJS_EXT)) {
+ return MJS_EXT;
+ }
+ Q_UNREACHABLE();
+};
+
class TestQmlformat: public QQmlDataTest
{
Q_OBJECT
@@ -27,6 +46,7 @@ public:
private Q_SLOTS:
void initTestCase() override;
+ //actually testFormat tests CLI of qmlformat
void testFormat();
void testFormat_data();
@@ -40,10 +60,19 @@ private Q_SLOTS:
void testBackupFileLimit();
+ void testFilesOption_data();
+ void testFilesOption();
+
+ void plainJS_data();
+ void plainJS();
+
+ void ecmascriptModule();
+
private:
QString readTestFile(const QString &path);
+ //TODO(QTBUG-117849) refactor this helper function
QString runQmlformat(const QString &fileToFormat, QStringList args, bool shouldSucceed = true,
- RunOption rOption = RunOption::OnCopy);
+ RunOption rOption = RunOption::OnCopy, QStringView ext = QML_EXT);
QString formatInMemory(const QString &fileToFormat, bool *didSucceed = nullptr,
LineWriterOptions options = LineWriterOptions(),
WriteOutChecks extraChecks = WriteOutCheck::ReparseCompare,
@@ -52,9 +81,11 @@ private:
QString m_qmlformatPath;
QStringList m_excludedDirs;
QStringList m_invalidFiles;
+ QStringList m_ignoreFiles;
QStringList findFiles(const QDir &);
bool isInvalidFile(const QFileInfo &fileName) const;
+ bool isIgnoredFile(const QFileInfo &fileName) const;
};
// Don't fail on warnings because we read a lot of QML files that might intentionally be malformed.
@@ -85,6 +116,7 @@ void TestQmlformat::initTestCase()
m_excludedDirs << "doc/src/snippets/qtquick1/qtbinding";
m_excludedDirs << "doc/src/snippets/qtquick1/imports";
m_excludedDirs << "tests/manual/v4";
+ m_excludedDirs << "tests/manual/qmllsformatter";
m_excludedDirs << "tests/auto/qml/ecmascripttests";
m_excludedDirs << "tests/auto/qml/qmllint";
@@ -126,6 +158,15 @@ void TestQmlformat::initTestCase()
m_invalidFiles << "tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_Or.qml";
m_invalidFiles << "tests/auto/qml/qqmllanguage/data/typeAnnotations.2.qml";
m_invalidFiles << "tests/auto/qml/qqmlparser/data/disallowedtypeannotations/qmlnestedfunction.qml";
+ m_invalidFiles << "tests/auto/qmlls/utils/data/emptyFile.qml";
+ m_invalidFiles << "tests/auto/qmlls/utils/data/completions/missingRHS.qml";
+ m_invalidFiles << "tests/auto/qmlls/utils/data/completions/missingRHS.parserfail.qml";
+ m_invalidFiles << "tests/auto/qmlls/utils/data/completions/attachedPropertyMissingRHS.qml";
+ m_invalidFiles << "tests/auto/qmlls/utils/data/completions/groupedPropertyMissingRHS.qml";
+ m_invalidFiles << "tests/auto/qmlls/utils/data/completions/afterDots.qml";
+ m_invalidFiles << "tests/auto/qmlls/modules/data/completions/bindingAfterDot.qml";
+ m_invalidFiles << "tests/auto/qmlls/modules/data/completions/defaultBindingAfterDot.qml";
+ m_invalidFiles << "tests/auto/qmlls/utils/data/qualifiedModule.qml";
// Files that get changed:
// rewrite of import "bla/bla/.." to import "bla"
@@ -145,6 +186,10 @@ void TestQmlformat::initTestCase()
m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon1.qml";
m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon_error1.qml";
m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon2.qml";
+
+ // These files are too big
+ m_ignoreFiles << "tests/benchmarks/qml/qmldom/data/longQmlFile.qml";
+ m_ignoreFiles << "tests/benchmarks/qml/qmldom/data/deeplyNested.qml";
}
QStringList TestQmlformat::findFiles(const QDir &d)
@@ -157,15 +202,17 @@ QStringList TestQmlformat::findFiles(const QDir &d)
QStringList rv;
- QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
- QDir::Files);
- foreach (const QString &file, files) {
- rv << d.absoluteFilePath(file);
+ const QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
+ QDir::Files);
+ for (const QString &file: files) {
+ QString absoluteFilePath = d.absoluteFilePath(file);
+ if (!isIgnoredFile(QFileInfo(absoluteFilePath)))
+ rv << absoluteFilePath;
}
- QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
- QDir::NoSymLinks);
- foreach (const QString &dir, dirs) {
+ const QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
+ QDir::NoSymLinks);
+ for (const QString &dir: dirs) {
QDir sub = d;
sub.cd(dir);
rv << findFiles(sub);
@@ -183,6 +230,15 @@ bool TestQmlformat::isInvalidFile(const QFileInfo &fileName) const
return false;
}
+bool TestQmlformat::isIgnoredFile(const QFileInfo &fileName) const
+{
+ for (const QString &file : m_ignoreFiles) {
+ if (fileName.absoluteFilePath().endsWith(file))
+ return true;
+ }
+ return false;
+}
+
QString TestQmlformat::readTestFile(const QString &path)
{
QFile file(testFile(path));
@@ -304,6 +360,60 @@ void TestQmlformat::testFormat_data()
QTest::newRow("ecmaScriptClassInQml")
<< "ecmaScriptClassInQml.qml"
<< "ecmaScriptClassInQml.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("arrowFunctionWithBinding")
+ << "arrowFunctionWithBinding.qml"
+ << "arrowFunctionWithBinding.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("blanklinesAfterComment")
+ << "blanklinesAfterComment.qml"
+ << "blanklinesAfterComment.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("pragmaValueList")
+ << "pragma.qml"
+ << "pragma.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("objectDestructuring")
+ << "objectDestructuring.qml"
+ << "objectDestructuring.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("destructuringFunctionParameter")
+ << "destructuringFunctionParameter.qml"
+ << "destructuringFunctionParameter.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("ellipsisFunctionArgument")
+ << "ellipsisFunctionArgument.qml"
+ << "ellipsisFunctionArgument.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("importStatements")
+ << "importStatements.qml"
+ << "importStatements.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("arrayEndComma")
+ << "arrayEndComma.qml"
+ << "arrayEndComma.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("escapeChars")
+ << "escapeChars.qml"
+ << "escapeChars.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("javascriptBlock")
+ << "javascriptBlock.qml"
+ << "javascriptBlock.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("enumWithValues")
+ << "enumWithValues.qml"
+ << "enumWithValues.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ //plainJS
+ QTest::newRow("nestedLambdaWithIfElse")
+ << "lambdaWithIfElseInsideLambda.js"
+ << "lambdaWithIfElseInsideLambda.formatted.js" << QStringList{} << RunOption::OnCopy;
+
+ QTest::newRow("indentEquals2")
+ << "threeFunctionsOneLine.js"
+ << "threeFunctions.formattedW2.js" << QStringList{"-w=2"} << RunOption::OnCopy;
+
+ QTest::newRow("tabIndents")
+ << "threeFunctionsOneLine.js"
+ << "threeFunctions.formattedTabs.js" << QStringList{"-t"} << RunOption::OnCopy;
+
+ QTest::newRow("normalizedFunctionSpacing")
+ << "threeFunctionsOneLine.js"
+ << "threeFunctions.formattedFuncSpacing.js"
+ << QStringList{ "-n", "--functions-spacing" } << RunOption::OnCopy;
+
+ QTest::newRow("esm_tabIndents")
+ << "mini_esm.mjs"
+ << "mini_esm.formattedTabs.mjs" << QStringList{ "-t" } << RunOption::OnCopy;
}
void TestQmlformat::testFormat()
@@ -313,7 +423,82 @@ void TestQmlformat::testFormat()
QFETCH(QStringList, args);
QFETCH(RunOption, runOption);
- QCOMPARE(runQmlformat(testFile(file), args, true, runOption), readTestFile(fileFormatted));
+ auto formatted = runQmlformat(testFile(file), args, true, runOption, fileExt(file));
+ QEXPECT_FAIL("normalizedFunctionSpacing",
+ "Normalize && function spacing are not yet supported for JS", Abort);
+ auto exp = readTestFile(fileFormatted);
+ QCOMPARE(formatted, exp);
+}
+
+void TestQmlformat::plainJS_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QString>("fileFormatted");
+
+ QTest::newRow("simpleStatement") << "simpleJSStatement.js"
+ << "simpleJSStatement.formatted.js";
+ QTest::newRow("simpleFunction") << "simpleOnelinerJSFunc.js"
+ << "simpleOnelinerJSFunc.formatted.js";
+ QTest::newRow("simpleLoop") << "simpleLoop.js"
+ << "simpleLoop.formatted.js";
+ QTest::newRow("messyIfStatement") << "messyIfStatement.js"
+ << "messyIfStatement.formatted.js";
+ QTest::newRow("lambdaFunctionWithLoop") << "lambdaFunctionWithLoop.js"
+ << "lambdaFunctionWithLoop.formatted.js";
+ QTest::newRow("lambdaWithIfElse") << "lambdaWithIfElse.js"
+ << "lambdaWithIfElse.formatted.js";
+ QTest::newRow("nestedLambdaWithIfElse") << "lambdaWithIfElseInsideLambda.js"
+ << "lambdaWithIfElseInsideLambda.formatted.js";
+ QTest::newRow("twoFunctions") << "twoFunctions.js"
+ << "twoFunctions.formatted.js";
+ QTest::newRow("pragma") << "pragma.js"
+ << "pragma.formatted.js";
+ QTest::newRow("classConstructor") << "class.js"
+ << "class.formatted.js";
+ QTest::newRow("legacyDirectives") << "directives.js"
+ << "directives.formatted.js";
+ QTest::newRow("legacyDirectivesWithComments") << "directivesWithComments.js"
+ << "directivesWithComments.formatted.js";
+}
+
+void TestQmlformat::plainJS()
+{
+ QFETCH(QString, file);
+ QFETCH(QString, fileFormatted);
+
+ bool wasSuccessful;
+ LineWriterOptions opts;
+#ifdef Q_OS_WIN
+ opts.lineEndings = QQmlJS::Dom::LineWriterOptions::LineEndings::Windows;
+#endif
+ QString output = formatInMemory(testFile(file), &wasSuccessful, opts, WriteOutCheck::None);
+
+ QVERIFY(wasSuccessful && !output.isEmpty());
+
+ // TODO(QTBUG-119404)
+ QEXPECT_FAIL("classConstructor", "see QTBUG-119404", Abort);
+ // TODO(QTBUG-119770)
+ QEXPECT_FAIL("legacyDirectivesWithComments", "see QTBUG-119770", Abort);
+ auto exp = readTestFile(fileFormatted);
+ QCOMPARE(output, exp);
+}
+
+void TestQmlformat::ecmascriptModule()
+{
+ QString file("esm.mjs");
+ QString formattedFile("esm.formatted.mjs");
+
+ bool wasSuccessful;
+ LineWriterOptions opts;
+#ifdef Q_OS_WIN
+ opts.lineEndings = QQmlJS::Dom::LineWriterOptions::LineEndings::Windows;
+#endif
+ QString output = formatInMemory(testFile(file), &wasSuccessful, opts, WriteOutCheck::None);
+
+ QVERIFY(wasSuccessful && !output.isEmpty());
+
+ auto exp = readTestFile(formattedFile);
+ QCOMPARE(output, readTestFile(formattedFile));
}
#if !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled
@@ -326,9 +511,23 @@ void TestQmlformat::testExample_data()
QString examples = QLatin1String(SRCDIR) + "/../../../../examples/";
QString tests = QLatin1String(SRCDIR) + "/../../../../tests/";
+ QStringList exampleFiles;
+ QStringList testFiles;
QStringList files;
- files << findFiles(QDir(examples));
- files << findFiles(QDir(tests));
+ exampleFiles << findFiles(QDir(examples));
+ testFiles << findFiles(QDir(tests));
+
+ // Actually this test is an e2e test and not the unit test.
+ // At the moment of writing, CI lacks providing instruments for the automated tests
+ // which might be time-consuming, as for example this one.
+ // Therefore as part of QTBUG-122990 this test was copied to the /manual/e2e/qml/qmlformat
+ // however very small fraction of the test data is still preserved here for the sake of
+ // testing automatically at least a small part of the examples
+ const int nBatch = 10;
+ files << exampleFiles.mid(0, nBatch) << exampleFiles.mid(exampleFiles.size() / 2, nBatch)
+ << exampleFiles.mid(exampleFiles.size() - nBatch, nBatch);
+ files << testFiles.mid(0, nBatch) << testFiles.mid(exampleFiles.size() / 2, nBatch)
+ << testFiles.mid(exampleFiles.size() - nBatch, nBatch);
for (const QString &file : files)
QTest::newRow(qPrintable(file)) << file;
@@ -417,12 +616,79 @@ void TestQmlformat::testBackupFileLimit()
};
}
+void TestQmlformat::testFilesOption_data()
+{
+ QTest::addColumn<QString>("containerFile");
+ QTest::addColumn<QStringList>("individualFiles");
+
+ QTest::newRow("initial") << "fileListToFormat"
+ << QStringList{"valid1.qml", "invalidEntry:cannot be parsed", "valid2.qml"};
+}
+
+void TestQmlformat::testFilesOption()
+{
+ QFETCH(QString, containerFile);
+ QFETCH(QStringList, individualFiles);
+
+ // Create a temporary directory
+ QTemporaryDir tempDir;
+ tempDir.setAutoRemove(false);
+ QStringList actualFormattedFilesPath;
+
+ // Iterate through files in the source directory and copy them to the temporary directory
+ const auto sourceDir = dataDirectory() + QDir::separator() + "filesOption";
+
+ // Create a file that contains the list of files to be formatted
+ const QString tempFilePath = tempDir.path() + QDir::separator() + containerFile;
+ QFile container(tempFilePath);
+ if (container.open(QIODevice::Text | QIODevice::WriteOnly)) {
+ QTextStream out(&container);
+
+ for (const auto &file : individualFiles) {
+ QString destinationFilePath = tempDir.path() + QDir::separator() + file;
+ if (QFile::copy(sourceDir + QDir::separator() + file, destinationFilePath))
+ actualFormattedFilesPath << destinationFilePath;
+ out << destinationFilePath << "\n";
+ }
+
+ container.close();
+ } else {
+ QFAIL("Cannot create temp test file\n");
+ return;
+ }
+
+ {
+ QProcess process;
+ process.start(m_qmlformatPath, QStringList{"-F", tempFilePath});
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ }
+
+ const auto readFile = [](const QString &filePath){
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning() << "Error on opening the file " << filePath;
+ return QByteArray{};
+ }
+
+ return file.readAll();
+ };
+
+ for (const auto &filePath : actualFormattedFilesPath) {
+ auto expectedFormattedFile = QFileInfo(filePath).fileName();
+ const auto expectedFormattedFilePath = sourceDir + QDir::separator() +
+ expectedFormattedFile.replace(".qml", ".formatted.qml");
+
+ QCOMPARE(readFile(filePath), readFile(expectedFormattedFilePath));
+ }
+}
+
QString TestQmlformat::runQmlformat(const QString &fileToFormat, QStringList args,
- bool shouldSucceed, RunOption rOptions)
+ bool shouldSucceed, RunOption rOptions, QStringView ext)
{
// Copy test file to temporary location
QTemporaryDir tempDir;
- const QString tempFile = tempDir.path() + QDir::separator() + "to_format.qml";
+ const QString tempFile = (tempDir.path() + QDir::separator() + "to_format") % ext;
if (rOptions == RunOption::OnCopy) {
QFile::copy(fileToFormat, tempFile);
@@ -446,7 +712,8 @@ QString TestQmlformat::runQmlformat(const QString &fileToFormat, QStringList arg
QFile temp(tempFile);
- temp.open(QIODevice::ReadOnly);
+ if (!temp.open(QIODevice::ReadOnly))
+ qFatal("Could not open %s", qPrintable(tempFile));
QString formatted = QString::fromUtf8(temp.readAll());
return formatted;
@@ -456,19 +723,17 @@ QString TestQmlformat::formatInMemory(const QString &fileToFormat, bool *didSucc
LineWriterOptions options, WriteOutChecks extraChecks,
WriteOutChecks largeChecks)
{
- DomItem env = DomEnvironment::create(
+ auto env = DomEnvironment::create(
QStringList(), // as we load no dependencies we do not need any paths
QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
| QQmlJS::Dom::DomEnvironment::Option::NoDependencies);
DomItem tFile;
- env.loadFile(
- fileToFormat, QString(),
- [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; },
- LoadOption::DefaultLoad);
- env.loadPendingDependencies();
+ env->loadFile(FileToLoad::fromFileSystem(env, fileToFormat),
+ [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; });
+ env->loadPendingDependencies();
MutableDomItem myFile = tFile.field(Fields::currentItem);
- DomItem writtenOut;
+ bool writtenOut;
QString resultStr;
if (myFile.field(Fields::isValid).value().toBool()) {
WriteOutChecks checks = extraChecks;
@@ -486,7 +751,7 @@ QString TestQmlformat::formatInMemory(const QString &fileToFormat, bool *didSucc
res.flush();
}
if (didSucceed)
- *didSucceed = bool(writtenOut);
+ *didSucceed = writtenOut;
return resultStr;
}
diff --git a/tests/auto/qml/qmlimportscanner/CMakeLists.txt b/tests/auto/qml/qmlimportscanner/CMakeLists.txt
index 042e8fd3d5..a1a22d7309 100644
--- a/tests/auto/qml/qmlimportscanner/CMakeLists.txt
+++ b/tests/auto/qml/qmlimportscanner/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmlimportscanner Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlimportscanner LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json b/tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json
index a688511ed0..8860b629d1 100644
--- a/tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json
+++ b/tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json
@@ -10,29 +10,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -40,9 +36,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -50,8 +46,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json b/tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json
index 084e4354b3..085d0bf6d4 100644
--- a/tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json
+++ b/tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json
@@ -5,24 +5,20 @@
"type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -30,9 +26,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -40,8 +36,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json b/tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json
index c50fe5ab51..c0cad1e3a1 100644
--- a/tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json
+++ b/tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json
@@ -10,29 +10,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -40,9 +36,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -50,8 +46,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/Drawer.qml.json b/tests/auto/qml/qmlimportscanner/data/Drawer.qml.json
index 447c664785..3abcd58b1c 100644
--- a/tests/auto/qml/qmlimportscanner/data/Drawer.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/Drawer.qml.json
@@ -1,23 +1,19 @@
[
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -25,9 +21,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -35,8 +31,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/Imports.json b/tests/auto/qml/qmlimportscanner/data/Imports.json
index 5e23e7b1ad..ee6903b1da 100644
--- a/tests/auto/qml/qmlimportscanner/data/Imports.json
+++ b/tests/auto/qml/qmlimportscanner/data/Imports.json
@@ -10,29 +10,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -40,9 +36,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -50,8 +46,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json b/tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json
index 06df9295fe..0e733b551f 100644
--- a/tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json
@@ -1,39 +1,29 @@
[
{
"classname": "QtQuick2Plugin",
- "name": "QtQuick",
"linkTarget": "Qt6::qtquick2plugin",
+ "name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
- },
- {
- "name": "Things",
- "plugin": "doesNotExistPlugin",
- "relativePath": "Things",
"type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -41,9 +31,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -51,8 +41,14 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
+ },
+ {
+ "name": "Things",
+ "plugin": "doesNotExistPlugin",
+ "relativePath": "Things",
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json b/tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json
index 213798d04d..d0d427f595 100644
--- a/tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json
+++ b/tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json
@@ -5,29 +5,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -35,9 +31,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -45,8 +41,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/Simple.qml.json b/tests/auto/qml/qmlimportscanner/data/Simple.qml.json
index 213798d04d..d0d427f595 100644
--- a/tests/auto/qml/qmlimportscanner/data/Simple.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/Simple.qml.json
@@ -5,29 +5,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -35,9 +31,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -45,8 +41,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/Singleton.json b/tests/auto/qml/qmlimportscanner/data/Singleton.json
index cb24e57f60..1813d01efe 100644
--- a/tests/auto/qml/qmlimportscanner/data/Singleton.json
+++ b/tests/auto/qml/qmlimportscanner/data/Singleton.json
@@ -10,29 +10,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -40,9 +36,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -50,8 +46,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/Things.json b/tests/auto/qml/qmlimportscanner/data/Things.json
index ee5caecfda..a6081c89d8 100644
--- a/tests/auto/qml/qmlimportscanner/data/Things.json
+++ b/tests/auto/qml/qmlimportscanner/data/Things.json
@@ -11,29 +11,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -41,9 +37,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -51,8 +47,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json b/tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json
index 2d2b602fb1..7094d1c8e3 100644
--- a/tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json
@@ -1,27 +1,19 @@
[
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
- "name": "QtQml",
- "plugin": "qmlmetaplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
- },
- {
"classname": "QtQmlPlugin",
"linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
+ "name": "QtQml",
"plugin": "qmlplugin",
"pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "prefer": ":/qt-project.org/imports/QtQml/",
+ "relativePath": "QtQml",
+ "type": "module"
},
{
- "name": "Methods.js",
- "type": "javascript"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -29,9 +21,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -39,8 +31,12 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
+ },
+ {
+ "name": "Methods.js",
+ "type": "javascript"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/localImport.qml.json b/tests/auto/qml/qmlimportscanner/data/localImport.qml.json
index ee5caecfda..a6081c89d8 100644
--- a/tests/auto/qml/qmlimportscanner/data/localImport.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/localImport.qml.json
@@ -11,29 +11,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -41,9 +37,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -51,8 +47,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json b/tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json
index 213798d04d..d0d427f595 100644
--- a/tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json
@@ -5,29 +5,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -35,9 +31,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -45,8 +41,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json b/tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json
index ee5caecfda..a6081c89d8 100644
--- a/tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json
@@ -11,29 +11,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -41,9 +37,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -51,8 +47,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json b/tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json
index 447c664785..3abcd58b1c 100644
--- a/tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json
@@ -1,23 +1,19 @@
[
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -25,9 +21,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -35,8 +31,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/rootPath.json b/tests/auto/qml/qmlimportscanner/data/rootPath.json
index 942c8d6000..41ce0f9a45 100644
--- a/tests/auto/qml/qmlimportscanner/data/rootPath.json
+++ b/tests/auto/qml/qmlimportscanner/data/rootPath.json
@@ -5,29 +5,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -35,9 +31,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -45,9 +41,9 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
},
{
"name": "QTBUG-45916.js",
@@ -68,12 +64,12 @@
"type": "module"
},
{
- "name": "Imports",
- "relativePath": "Imports",
+ "name": "Module",
"type": "module"
},
{
- "name": "Module",
+ "name": "Imports",
+ "relativePath": "Imports",
"type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/tst_qmlimportscanner.cpp b/tests/auto/qml/qmlimportscanner/tst_qmlimportscanner.cpp
index 02cebc349c..49b3418401 100644
--- a/tests/auto/qml/qmlimportscanner/tst_qmlimportscanner.cpp
+++ b/tests/auto/qml/qmlimportscanner/tst_qmlimportscanner.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QProcess>
@@ -149,7 +149,7 @@ void TestQmlimportscanner::runQmlimportscanner(const QString &mode, const QStrin
QVERIFY(generated.isArray());
QFile imports(resultFile);
- imports.open(QIODevice::ReadOnly);
+ QVERIFY(imports.open(QIODevice::ReadOnly));
QJsonDocument expected = QJsonDocument::fromJson(imports.readAll(), &error);
QCOMPARE(error.error, QJsonParseError::NoError);
QVERIFY(expected.isArray());
diff --git a/tests/auto/qml/qmllint/CMakeLists.txt b/tests/auto/qml/qmllint/CMakeLists.txt
index 422e7a08b3..5a3e2d9c0d 100644
--- a/tests/auto/qml/qmllint/CMakeLists.txt
+++ b/tests/auto/qml/qmllint/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmllint Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmllint LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -42,9 +48,15 @@ qt_internal_extend_target(tst_qmllint CONDITION NOT ANDROID AND NOT IOS
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
)
+if (TARGET qmllint)
+ add_dependencies(tst_qmllint Qt::qmllint)
+endif()
+
if (TARGET qmljsrootgen)
qt_internal_extend_target(tst_qmllint
DEFINES
QT_QMLJSROOTGEN_PRESENT
)
+
+ add_dependencies(tst_qmllint Qt::qmljsrootgen)
endif()
diff --git a/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/A.qml b/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/A.qml
new file mode 100644
index 0000000000..4141884af9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/A.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property string myProperty
+}
diff --git a/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/qmldir b/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/qmldir
new file mode 100644
index 0000000000..b6e958d657
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/qmldir
@@ -0,0 +1,2 @@
+module ModuleInImportPath
+A 1.0 A.qml
diff --git a/tests/auto/qml/qmllint/data/IsNotAnEntryOfEnum.qml b/tests/auto/qml/qmllint/data/IsNotAnEntryOfEnum.qml
new file mode 100644
index 0000000000..8b20fe9ae9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/IsNotAnEntryOfEnum.qml
@@ -0,0 +1,14 @@
+import QtQuick
+
+Item {
+ id: item
+ visible: true
+
+ enum Mode {
+ Hours,
+ Minutes
+ }
+
+ property int mode: item.Mode.Hours
+ property string s: item.mode === IsNotAnEntryOfEnum.Mode.Hour ? "green" : "tomato"
+}
diff --git a/tests/auto/qml/qmllint/data/LocaleTest/localeTest.qmltypes b/tests/auto/qml/qmllint/data/LocaleTest/localeTest.qmltypes
new file mode 100644
index 0000000000..b5baa22357
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/LocaleTest/localeTest.qmltypes
@@ -0,0 +1,31 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by qmltyperegistrar.
+
+Module {
+ Component {
+ file: "AppManager.h"
+ name: "AppManager"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["LocaleTest/AppManager 1.0"]
+ isCreatable: false
+ isSingleton: true
+ exportMetaObjectRevisions: [256]
+ Property {
+ name: "primaryLocale"
+ type: "QLocale"
+ read: "getPrimaryLocale"
+ notify: "primaryLocaleChanged"
+ index: 0
+ isReadonly: true
+ }
+ Signal {
+ name: "primaryLocaleChanged"
+ Parameter { type: "QLocale" }
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/LocaleTest/qmldir b/tests/auto/qml/qmllint/data/LocaleTest/qmldir
new file mode 100644
index 0000000000..2dc0799d5b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/LocaleTest/qmldir
@@ -0,0 +1,3 @@
+module LocaleTest
+typeinfo localeTest.qmltypes
+depends QtQml
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/Outer.qml b/tests/auto/qml/qmllint/data/MultiDirectory/Outer.qml
new file mode 100644
index 0000000000..5dda9a4d12
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/Outer.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property int o: 12
+}
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/multi.qrc b/tests/auto/qml/qmllint/data/MultiDirectory/multi.qrc
new file mode 100644
index 0000000000..b6df21ec4c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/multi.qrc
@@ -0,0 +1,10 @@
+<RCC>
+ <qresource prefix="/qt/qml/MultiDirectory">
+ <file>qmldir</file>
+ <file>Outer.qml</file>
+ <file>qml/qmldir</file>
+ <file>qml/Inner.qml</file>
+ <file>qml/pages/qmldir</file>
+ <file>qml/pages/Page.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qml/Inner.qml b/tests/auto/qml/qmllint/data/MultiDirectory/qml/Inner.qml
new file mode 100644
index 0000000000..01b7c331d9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qml/Inner.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+Outer {
+ o: 25
+}
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/Page.qml b/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/Page.qml
new file mode 100644
index 0000000000..7efc889fb1
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/Page.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+Inner {
+ o: 32
+}
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/qmldir b/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/qmldir
new file mode 100644
index 0000000000..56ef19d41b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/qmldir
@@ -0,0 +1 @@
+prefer :/qt/qml/MultiDirectory/
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qml/qmldir b/tests/auto/qml/qmllint/data/MultiDirectory/qml/qmldir
new file mode 100644
index 0000000000..56ef19d41b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qml/qmldir
@@ -0,0 +1 @@
+prefer :/qt/qml/MultiDirectory/
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qmldir b/tests/auto/qml/qmllint/data/MultiDirectory/qmldir
new file mode 100644
index 0000000000..699132dc4f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qmldir
@@ -0,0 +1,5 @@
+module MultiDirectory
+prefer :/qt/qml/MultiDirectory
+Outer 1.0 Outer.qml
+Inner 1.0 qml/Inner.qml
+Page 1.0 qml/pages/Page.qml
diff --git a/tests/auto/qml/qmllint/data/MyStyle/MyStyle.qmltypes b/tests/auto/qml/qmllint/data/MyStyle/MyStyle.qmltypes
new file mode 100644
index 0000000000..92c1b0953e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MyStyle/MyStyle.qmltypes
@@ -0,0 +1,112 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by qmltyperegistrar.
+
+Module {
+ Component {
+ file: "mystyle.h"
+ name: "MyStyle"
+ accessSemantics: "reference"
+ prototype: "QQuickAttachedPropertyPropagator"
+ exports: ["MyStyle/MyStyle 1.0", "MyStyle/MyStyle 254.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [256, 65024]
+ attachedType: "MyStyle"
+ Enum {
+ name: "Theme"
+ values: ["Light", "Dark"]
+ }
+ Property {
+ name: "theme"
+ type: "Theme"
+ read: "theme"
+ write: "setTheme"
+ reset: "resetTheme"
+ notify: "themeChanged"
+ index: 0
+ isFinal: true
+ }
+ Property {
+ name: "windowColor"
+ type: "QColor"
+ read: "windowColor"
+ notify: "themeChanged"
+ index: 1
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "windowTextColor"
+ type: "QColor"
+ read: "windowTextColor"
+ notify: "themeChanged"
+ index: 2
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "buttonColor"
+ type: "QColor"
+ read: "buttonColor"
+ notify: "themeChanged"
+ index: 3
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "buttonTextColor"
+ type: "QColor"
+ read: "buttonTextColor"
+ notify: "themeChanged"
+ index: 4
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "toolBarColor"
+ type: "QColor"
+ read: "toolBarColor"
+ notify: "themeChanged"
+ index: 5
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "popupColor"
+ type: "QColor"
+ read: "popupColor"
+ notify: "themeChanged"
+ index: 6
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "popupBorderColor"
+ type: "QColor"
+ read: "popupBorderColor"
+ notify: "themeChanged"
+ index: 7
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "backgroundDimColor"
+ type: "QColor"
+ read: "backgroundDimColor"
+ notify: "themeChanged"
+ index: 8
+ isReadonly: true
+ isFinal: true
+ }
+ Signal { name: "themeChanged" }
+ }
+ Component {
+ file: "qquickattachedpropertypropagator.h"
+ name: "QQuickAttachedPropertyPropagator"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/MyStyle/ToolBar.qml b/tests/auto/qml/qmllint/data/MyStyle/ToolBar.qml
new file mode 100644
index 0000000000..5920797d9b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MyStyle/ToolBar.qml
@@ -0,0 +1,12 @@
+import QtQuick
+import QtQuick.Templates as T
+import MyStyle
+
+T.ToolBar {
+ id: control
+
+ property color c: MyStyle.toolBarColor
+ background: Rectangle {
+ color: MyStyle.toolBarColor
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/MyStyle/qmldir b/tests/auto/qml/qmllint/data/MyStyle/qmldir
new file mode 100644
index 0000000000..8cc4246f7c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MyStyle/qmldir
@@ -0,0 +1,4 @@
+module MyStyle
+typeinfo MyStyle.qmltypes
+ToolBar 254.0 ToolBar.qml
+import QtQuick.Controls.Material
diff --git a/tests/auto/qml/qmllint/data/NeedImportPath.qml b/tests/auto/qml/qmllint/data/NeedImportPath.qml
new file mode 100644
index 0000000000..0a63b58f7c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/NeedImportPath.qml
@@ -0,0 +1,5 @@
+import ModuleInImportPath
+
+A {
+ myProperty: "Hello World"
+}
diff --git a/tests/auto/qml/qmllint/data/Qtbug111015/qmldir b/tests/auto/qml/qmllint/data/Qtbug111015/qmldir
new file mode 100644
index 0000000000..3bf1d48e13
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Qtbug111015/qmldir
@@ -0,0 +1,3 @@
+module Qtbug111015
+typeinfo qtbug111015.qmltypes
+import QtQml
diff --git a/tests/auto/qml/qmllint/data/Qtbug111015/qtbug111015.qmltypes b/tests/auto/qml/qmllint/data/Qtbug111015/qtbug111015.qmltypes
new file mode 100644
index 0000000000..7de521a379
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Qtbug111015/qtbug111015.qmltypes
@@ -0,0 +1,20 @@
+import QtQuick.tooling 1.2
+
+Module {
+ Component {
+ file: "typewithjsonobjectlist.h"
+ name: "TypeWithJsonObjectList"
+ exports: ["QmlLintTestLib/TypeWithJsonObjectList 1.0"]
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property { name: "jsonObjectList"; type: "QJsonObject"; isList: true; read: "getJsonObjectList"; index: 0; isReadonly: true }
+ }
+ Component {
+ file: "typewithjsonarray.h"
+ name: "TypeWithJsonArray"
+ exports: ["QmlLintTestLib/TypeWithJsonArray 1.0"]
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property { name: "jsonArray"; type: "QJsonArray"; read: "getJsonArray"; index: 0; isReadonly: true }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/SharedFunctions.js b/tests/auto/qml/qmllint/data/SharedFunctions.js
new file mode 100644
index 0000000000..3398d2d6d7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/SharedFunctions.js
@@ -0,0 +1,5 @@
+.pragma library
+
+function setColorAlpha(color, alpha) {
+ return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha)
+}
diff --git a/tests/auto/qml/qmllint/data/StringToDateTime/qmldir b/tests/auto/qml/qmllint/data/StringToDateTime/qmldir
new file mode 100644
index 0000000000..761f613496
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/StringToDateTime/qmldir
@@ -0,0 +1,3 @@
+module StringToDateTime
+typeinfo stringToDateTime.qmltypes
+import QtQml
diff --git a/tests/auto/qml/qmllint/data/StringToDateTime/stringToDateTime.qmltypes b/tests/auto/qml/qmllint/data/StringToDateTime/stringToDateTime.qmltypes
new file mode 100644
index 0000000000..e0f13fa2ec
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/StringToDateTime/stringToDateTime.qmltypes
@@ -0,0 +1,14 @@
+import QtQuick.tooling 1.2
+Module {
+ Component {
+ file: "stringToQDateTime.h"
+ name: "StringToDateTimeComponent"
+ exports: ["QmlLintTestLib/StringToDateTime 1.0"]
+ exportMetaObjectRevisions: [256]
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property { name: "aDate"; type: "QDate"; read: "getADate"; write: "setADate" }
+ Property { name: "aTime"; type: "QTime"; read: "getATime"; write: "setATime" }
+ Property { name: "aDateTime"; type: "QDateTime"; read: "getADateTime"; write: "setADateTime" }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/TestTypes/testtypes.qmltypes b/tests/auto/qml/qmllint/data/TestTypes/testtypes.qmltypes
index 04ca30c184..77ad6a3cef 100644
--- a/tests/auto/qml/qmllint/data/TestTypes/testtypes.qmltypes
+++ b/tests/auto/qml/qmllint/data/TestTypes/testtypes.qmltypes
@@ -178,4 +178,24 @@ Module {
exportMetaObjectRevisions: [256]
Method { name: "createObject"; isJavaScriptFunction: true }
}
+ Component {
+ file: "variantMapLookup.h"
+ name: "VariantMapLookupFoo"
+ prototype: "QObject"
+ exports: ["TestTypes/VariantMapLookupFoo 1.0"]
+ exportMetaObjectRevisions: [256]
+ Property {
+ name: "data"
+ type: "QVariantMap"
+ read: "data"
+ index: 0
+ }
+ }
+ Component {
+ file: "foo.h"
+ name: "Foo"
+ prototype: "QObject"
+ exports: ["TestTypes/Foo 1.0"]
+ Method { name: "print" }
+ }
}
diff --git a/tests/auto/qml/qmllint/data/Things/plugins.qmltypes b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes
index 9d36d91a90..3b0da602ac 100644
--- a/tests/auto/qml/qmllint/data/Things/plugins.qmltypes
+++ b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes
@@ -12,6 +12,7 @@ Module {
exports: ["Things/SomethingEntirelyStrange 1.0"]
Enum {
name: "AnEnum"
+ isScoped: true
values: {
"AAA": 0,
"BBB": 1,
@@ -20,7 +21,7 @@ Module {
}
Enum {
name: "TheEnum"
- scoped: false
+ isScoped: false
values: {
"V1": 0,
"V2": 1
@@ -96,4 +97,21 @@ Module {
Property { name: "foo"; type: "string" }
hasCustomParser: true
}
+ Component {
+ file: "mediaplayer-qml.h"
+ name: "MediaPlayerStateMachine"
+ accessSemantics: "value"
+ exports: ["Mediaplayer/MediaPlayerStateMachine 1.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [256]
+ }
+ Component {
+ file: "constinvokable.h"
+ name: "ConstInvokable"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["Things/ConstInvokable 1.0"]
+ exportMetaObjectRevisions: [256]
+ Method { name: "getObject"; type: "QObject"; isPointer: true; isTypeConstant: true }
+ }
}
diff --git a/tests/auto/qml/qmllint/data/UnqualifiedInStoreSloppy.qml b/tests/auto/qml/qmllint/data/UnqualifiedInStoreSloppy.qml
new file mode 100644
index 0000000000..197b74fa60
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/UnqualifiedInStoreSloppy.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ Rectangle {
+ property real divisor: 0
+
+ Timer {
+ onTriggered: divisor = 1
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/UnqualifiedInStoreStrict.qml b/tests/auto/qml/qmllint/data/UnqualifiedInStoreStrict.qml
new file mode 100644
index 0000000000..198e2146f5
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/UnqualifiedInStoreStrict.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ Rectangle {
+ property real divisor: 0
+
+ Timer {
+ onTriggered: function() {"use strict"; divisor = 1 }
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/addressableValue.qml b/tests/auto/qml/qmllint/data/addressableValue.qml
new file mode 100644
index 0000000000..9b93728ed8
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/addressableValue.qml
@@ -0,0 +1,8 @@
+pragma ValueTypeBehavior: Addressable
+
+import QtQml
+import scripts
+
+QtObject {
+ property var v: "red" as vvv
+}
diff --git a/tests/auto/qml/qmllint/data/attachedImportUse.qml b/tests/auto/qml/qmllint/data/attachedImportUse.qml
new file mode 100644
index 0000000000..56b4e2bf7c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/attachedImportUse.qml
@@ -0,0 +1,7 @@
+import QtQml
+import TestTypes
+
+QtObject {
+ id: control
+ objectName: control.BirthdayParty.objectName
+}
diff --git a/tests/auto/qml/qmllint/data/badAliasNotAnExpression.qml b/tests/auto/qml/qmllint/data/badAliasNotAnExpression.qml
new file mode 100644
index 0000000000..cdc2b28c07
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badAliasNotAnExpression.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+Item {
+
+ property alias innerObj: {
+ id: inner
+ }
+
+}
diff --git a/tests/auto/qml/qmllint/data/bad_builtins/builtins.qmltypes b/tests/auto/qml/qmllint/data/bad_builtins/builtins.qmltypes
new file mode 100644
index 0000000000..96f98dd14e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/bad_builtins/builtins.qmltypes
@@ -0,0 +1,513 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by:
+// 'qmlplugindump -builtins'
+
+Module {
+ dependencies: []
+ Component {
+ name: "Qt"
+ Enum {
+ name: "GlobalColor"
+ values: {
+ "color0": 0,
+ "color1": 1,
+ "black": 2,
+ "white": 3,
+ "darkGray": 4,
+ "gray": 5,
+ "lightGray": 6,
+ "red": 7,
+ "green": 8,
+ "blue": 9,
+ "cyan": 10,
+ "magenta": 11,
+ "yellow": 12,
+ "darkRed": 13,
+ "darkGreen": 14,
+ "darkBlue": 15,
+ "darkCyan": 16,
+ "darkMagenta": 17,
+ "darkYellow": 18,
+ "transparent": 19
+ }
+ }
+ Enum {
+ name: "KeyboardModifiers"
+ values: {
+ "NoModifier": 0,
+ "ShiftModifier": 33554432,
+ "ControlModifier": 67108864,
+ "AltModifier": 134217728,
+ "MetaModifier": 268435456,
+ "KeypadModifier": 536870912,
+ "GroupSwitchModifier": 1073741824,
+ "KeyboardModifierMask": -33554432
+ }
+ }
+ Enum {
+ name: "MouseButtons"
+ values: {
+ "NoButton": 0,
+ "LeftButton": 1,
+ "RightButton": 2,
+ "MidButton": 4, // For backwards compatibility
+ "MiddleButton": 4,
+ "BackButton": 8,
+ "XButton1": 8,
+ "ExtraButton1": 8,
+ "ForwardButton": 16,
+ "XButton2": 16,
+ "ExtraButton2": 16,
+ "TaskButton": 32,
+ "ExtraButton3": 32,
+ "ExtraButton4": 64,
+ "ExtraButton5": 128,
+ "ExtraButton6": 256,
+ "ExtraButton7": 512,
+ "ExtraButton8": 1024,
+ "ExtraButton9": 2048,
+ "ExtraButton10": 4096,
+ "ExtraButton11": 8192,
+ "ExtraButton12": 16384,
+ "ExtraButton13": 32768,
+ "ExtraButton14": 65536,
+ "ExtraButton15": 131072,
+ "ExtraButton16": 262144,
+ "ExtraButton17": 524288,
+ "ExtraButton18": 1048576,
+ "ExtraButton19": 2097152,
+ "ExtraButton20": 4194304,
+ "ExtraButton21": 8388608,
+ "ExtraButton22": 16777216,
+ "ExtraButton23": 33554432,
+ "ExtraButton24": 67108864,
+ "AllButtons": 134217727,
+ "MaxMouseButton": 67108864,
+ "MouseButtonMask": -1
+ }
+ }
+ Enum {
+ name: "Orientation"
+ values: {
+ "Horizontal": 1,
+ "Vertical": 2
+ }
+ }
+ Enum {
+ name: "Orientations"
+ values: {
+ "Horizontal": 1,
+ "Vertical": 2
+ }
+ }
+ Enum {
+ name: "FocusPolicy"
+ values: {
+ "NoFocus": 0,
+ "TabFocus": 1,
+ "ClickFocus": 2,
+ "StrongFocus": 11,
+ "WheelFocus": 15
+ }
+ }
+ Enum {
+ name: "TabFocusBehavior"
+ values: {
+ "NoTabFocus": 0,
+ "TabFocusTextControls": 1,
+ "TabFocusListControls": 2,
+ "TabFocusAllControls": 255
+ }
+ }
+ Enum {
+ name: "SortOrder"
+ values: {
+ "AscendingOrder": 0,
+ "DescendingOrder": 1
+ }
+ }
+ Enum {
+ name: "SplitBehavior"
+ values: {
+ "KeepEmptyParts": 0,
+ "SkipEmptyParts": 1
+ }
+ }
+ Enum {
+ name: "Alignment"
+ values: {
+ "AlignLeft": 1,
+ "AlignLeading": 1,
+ "AlignRight": 2,
+ "AlignTrailing": 2,
+ "AlignHCenter": 4,
+ "AlignJustify": 8,
+ "AlignAbsolute": 16,
+ "AlignHorizontal_Mask": 31,
+ "AlignTop": 32,
+ "AlignBottom": 64,
+ "AlignVCenter": 128,
+ "AlignBaseline": 256,
+ "AlignVertical_Mask": 480,
+ "AlignCenter": 132
+ }
+ }
+ Enum {
+ name: "TextFlag"
+ values: {
+ "TextSingleLine": 256,
+ "TextDontClip": 512,
+ "TextExpandTabs": 1024,
+ "TextShowMnemonic": 2048,
+ "TextWordWrap": 4096,
+ "TextWrapAnywhere": 8192,
+ "TextDontPrint": 16384,
+ "TextIncludeTrailingSpaces": 134217728,
+ "TextHideMnemonic": 32768,
+ "TextJustificationForced": 65536,
+ "TextForceLeftToRight": 131072,
+ "TextForceRightToLeft": 262144,
+ "TextLongestVariant": 524288,
+ "TextBypassShaping": 1048576
+ }
+ }
+ Enum {
+ name: "TextElideMode"
+ values: {
+ "ElideLeft": 0,
+ "ElideRight": 1,
+ "ElideMiddle": 2,
+ "ElideNone": 3
+ }
+ }
+ Enum {
+ name: "WindowType"
+ values: {
+ "Widget": 0,
+ "Window": 1,
+ "Dialog": 3,
+ "Sheet": 5,
+ "Drawer": 7,
+ "Popup": 9,
+ "Tool": 11,
+ "ToolTip": 13,
+ "SplashScreen": 15,
+ "Desktop": 17,
+ "SubWindow": 18,
+ "ForeignWindow": 33,
+ "CoverWindow": 65,
+ "WindowType_Mask": 255,
+ "MSWindowsFixedSizeDialogHint": 256,
+ "MSWindowsOwnDC": 512,
+ "BypassWindowManagerHint": 1024,
+ "X11BypassWindowManagerHint": 1024,
+ "FramelessWindowHint": 2048,
+ "WindowTitleHint": 4096,
+ "WindowSystemMenuHint": 8192,
+ "WindowMinimizeButtonHint": 16384,
+ "WindowMaximizeButtonHint": 32768,
+ "WindowMinMaxButtonsHint": 49152,
+ "WindowContextHelpButtonHint": 65536,
+ "WindowShadeButtonHint": 131072,
+ "WindowStaysOnTopHint": 262144,
+ "WindowTransparentForInput": 524288,
+ "WindowOverridesSystemGestures": 1048576,
+ "WindowDoesNotAcceptFocus": 2097152,
+ "MaximizeUsingFullscreenGeometryHint": 4194304,
+ "CustomizeWindowHint": 33554432,
+ "WindowStaysOnBottomHint": 67108864,
+ "WindowCloseButtonHint": 134217728,
+ "MacWindowToolBarButtonHint": 268435456,
+ "BypassGraphicsProxyWidget": 536870912,
+ "NoDropShadowWindowHint": 1073741824,
+ "WindowFullscreenButtonHint": -2147483648
+ }
+ }
+ Enum {
+ name: "WindowFlags"
+ values: {
+ "Widget": 0,
+ "Window": 1,
+ "Dialog": 3,
+ "Sheet": 5,
+ "Drawer": 7,
+ "Popup": 9,
+ "Tool": 11,
+ "ToolTip": 13,
+ "SplashScreen": 15,
+ "Desktop": 17,
+ "SubWindow": 18,
+ "ForeignWindow": 33,
+ "CoverWindow": 65,
+ "WindowType_Mask": 255,
+ "MSWindowsFixedSizeDialogHint": 256,
+ "MSWindowsOwnDC": 512,
+ "BypassWindowManagerHint": 1024,
+ "X11BypassWindowManagerHint": 1024,
+ "FramelessWindowHint": 2048,
+ "WindowTitleHint": 4096,
+ "WindowSystemMenuHint": 8192,
+ "WindowMinimizeButtonHint": 16384,
+ "WindowMaximizeButtonHint": 32768,
+ "WindowMinMaxButtonsHint": 49152,
+ "WindowContextHelpButtonHint": 65536,
+ "WindowShadeButtonHint": 131072,
+ "WindowStaysOnTopHint": 262144,
+ "WindowTransparentForInput": 524288,
+ "WindowOverridesSystemGestures": 1048576,
+ "WindowDoesNotAcceptFocus": 2097152,
+ "MaximizeUsingFullscreenGeometryHint": 4194304,
+ "CustomizeWindowHint": 33554432,
+ "WindowStaysOnBottomHint": 67108864,
+ "WindowCloseButtonHint": 134217728,
+ "MacWindowToolBarButtonHint": 268435456,
+ "BypassGraphicsProxyWidget": 536870912,
+ "NoDropShadowWindowHint": 1073741824,
+ "WindowFullscreenButtonHint": -2147483648
+ }
+ }
+ Enum {
+ name: "WindowState"
+ values: {
+ "WindowNoState": 0,
+ "WindowMinimized": 1,
+ "WindowMaximized": 2,
+ "WindowFullScreen": 4,
+ "WindowActive": 8
+ }
+ }
+ Enum {
+ name: "WindowStates"
+ values: {
+ "WindowNoState": 0,
+ "WindowMinimized": 1,
+ "WindowMaximized": 2,
+ "WindowFullScreen": 4,
+ "WindowActive": 8
+ }
+ }
+ Enum {
+ name: "ApplicationState"
+ values: {
+ "ApplicationSuspended": 0,
+ "ApplicationHidden": 1,
+ "ApplicationInactive": 2,
+ "ApplicationActive": 4
+ }
+ }
+ Enum {
+ name: "ScreenOrientation"
+ values: {
+ "PrimaryOrientation": 0,
+ "PortraitOrientation": 1,
+ "LandscapeOrientation": 2,
+ "InvertedPortraitOrientation": 4,
+ "InvertedLandscapeOrientation": 8
+ }
+ }
+ Enum {
+ name: "ScreenOrientations"
+ values: {
+ "PrimaryOrientation": 0,
+ "PortraitOrientation": 1,
+ "LandscapeOrientation": 2,
+ "InvertedPortraitOrientation": 4,
+ "InvertedLandscapeOrientation": 8
+ }
+ }
+ Enum {
+ name: "WidgetAttribute"
+ values: {
+ "WA_Disabled": 0,
+ "WA_UnderMouse": 1,
+ "WA_MouseTracking": 2,
+ "WA_ContentsPropagated": 3,
+ "WA_OpaquePaintEvent": 4,
+ "WA_NoBackground": 4,
+ "WA_StaticContents": 5,
+ "WA_LaidOut": 7,
+ "WA_PaintOnScreen": 8,
+ "WA_NoSystemBackground": 9,
+ "WA_UpdatesDisabled": 10,
+ "WA_Mapped": 11,
+ "WA_MacNoClickThrough": 12,
+ "WA_InputMethodEnabled": 14,
+ "WA_WState_Visible": 15,
+ "WA_WState_Hidden": 16,
+ "WA_ForceDisabled": 32,
+ "WA_KeyCompression": 33,
+ "WA_PendingMoveEvent": 34,
+ "WA_PendingResizeEvent": 35,
+ "WA_SetPalette": 36,
+ "WA_SetFont": 37,
+ "WA_SetCursor": 38,
+ "WA_NoChildEventsFromChildren": 39,
+ "WA_WindowModified": 41,
+ "WA_Resized": 42,
+ "WA_Moved": 43,
+ "WA_PendingUpdate": 44,
+ "WA_InvalidSize": 45,
+ "WA_MacBrushedMetal": 46,
+ "WA_MacMetalStyle": 46,
+ "WA_CustomWhatsThis": 47,
+ "WA_LayoutOnEntireRect": 48,
+ "WA_OutsideWSRange": 49,
+ "WA_GrabbedShortcut": 50,
+ "WA_TransparentForMouseEvents": 51,
+ "WA_PaintUnclipped": 52,
+ "WA_SetWindowIcon": 53,
+ "WA_NoMouseReplay": 54,
+ "WA_DeleteOnClose": 55,
+ "WA_RightToLeft": 56,
+ "WA_SetLayoutDirection": 57,
+ "WA_NoChildEventsForParent": 58,
+ "WA_ForceUpdatesDisabled": 59,
+ "WA_WState_Created": 60,
+ "WA_WState_CompressKeys": 61,
+ "WA_WState_InPaintEvent": 62,
+ "WA_WState_Reparented": 63,
+ "WA_WState_ConfigPending": 64,
+ "WA_WState_Polished": 66,
+ "WA_WState_DND": 67,
+ "WA_WState_OwnSizePolicy": 68,
+ "WA_WState_ExplicitShowHide": 69,
+ "WA_ShowModal": 70,
+ "WA_MouseNoMask": 71,
+ "WA_GroupLeader": 72,
+ "WA_NoMousePropagation": 73,
+ "WA_Hover": 74,
+ "WA_InputMethodTransparent": 75,
+ "WA_QuitOnClose": 76,
+ "WA_KeyboardFocusChange": 77,
+ "WA_AcceptDrops": 78,
+ "WA_DropSiteRegistered": 79,
+ "WA_ForceAcceptDrops": 79,
+ "WA_WindowPropagation": 80,
+ "WA_NoX11EventCompression": 81,
+ "WA_TintedBackground": 82,
+ "WA_X11OpenGLOverlay": 83,
+ "WA_AlwaysShowToolTips": 84,
+ "WA_MacOpaqueSizeGrip": 85,
+ "WA_SetStyle": 86,
+ "WA_SetLocale": 87,
+ "WA_MacShowFocusRect": 88,
+ "WA_MacNormalSize": 89,
+ "WA_MacSmallSize": 90,
+ "WA_MacMiniSize": 91,
+ "WA_LayoutUsesWidgetRect": 92,
+ "WA_StyledBackground": 93,
+ "WA_MSWindowsUseDirect3D": 94,
+ "WA_CanHostQMdiSubWindowTitleBar": 95,
+ "WA_MacAlwaysShowToolWindow": 96,
+ "WA_StyleSheet": 97,
+ "WA_ShowWithoutActivating": 98,
+ "WA_X11BypassTransientForHint": 99,
+ "WA_NativeWindow": 100,
+ "WA_DontCreateNativeAncestors": 101,
+ "WA_MacVariableSize": 102,
+ "WA_DontShowOnScreen": 103,
+ "WA_X11NetWmWindowTypeDesktop": 104,
+ "WA_X11NetWmWindowTypeDock": 105,
+ "WA_X11NetWmWindowTypeToolBar": 106,
+ "WA_X11NetWmWindowTypeMenu": 107,
+ "WA_X11NetWmWindowTypeUtility": 108,
+ "WA_X11NetWmWindowTypeSplash": 109,
+ "WA_X11NetWmWindowTypeDialog": 110,
+ "WA_X11NetWmWindowTypeDropDownMenu": 111,
+ "WA_X11NetWmWindowTypePopupMenu": 112,
+ "WA_X11NetWmWindowTypeToolTip": 113,
+ "WA_X11NetWmWindowTypeNotification": 114,
+ "WA_X11NetWmWindowTypeCombo": 115,
+ "WA_X11NetWmWindowTypeDND": 116,
+ "WA_MacFrameworkScaled": 117,
+ "WA_SetWindowModality": 118,
+ "WA_WState_WindowOpacitySet": 119,
+ "WA_TranslucentBackground": 120,
+ "WA_AcceptTouchEvents": 121,
+ "WA_WState_AcceptedTouchBeginEvent": 122,
+ "WA_TouchPadAcceptSingleTouchEvents": 123,
+ "WA_X11DoNotAcceptFocus": 126,
+ "WA_MacNoShadow": 127,
+ "WA_AlwaysStackOnTop": 128,
+ "WA_TabletTracking": 129,
+ "WA_ContentsMarginsRespectsSafeArea": 130,
+ "WA_StyleSheetTarget": 131,
+ "WA_AttributeCount": 132
+ }
+ }
+ Enum {
+ name: "ApplicationAttribute"
+ values: {
+ "AA_ImmediateWidgetCreation": 0,
+ "AA_MSWindowsUseDirect3DByDefault": 1,
+ "AA_DontShowIconsInMenus": 2,
+ "AA_NativeWindows": 3,
+ "AA_DontCreateNativeWidgetSiblings": 4,
+ "AA_PluginApplication": 5,
+ "AA_MacPluginApplication": 5,
+ "AA_DontUseNativeMenuBar": 6,
+ "AA_MacDontSwapCtrlAndMeta": 7,
+ "AA_Use96Dpi": 8,
+ "AA_X11InitThreads": 10,
+ "AA_SynthesizeTouchForUnhandledMouseEvents": 11,
+ "AA_SynthesizeMouseForUnhandledTouchEvents": 12,
+ "AA_UseHighDpiPixmaps": 13,
+ "AA_ForceRasterWidgets": 14,
+ "AA_UseDesktopOpenGL": 15,
+ "AA_UseOpenGLES": 16,
+ "AA_UseSoftwareOpenGL": 17,
+ "AA_ShareOpenGLContexts": 18,
+ "AA_SetPalette": 19,
+ "AA_EnableHighDpiScaling": 20,
+ "AA_DisableHighDpiScaling": 21,
+ "AA_UseStyleSheetPropagationInWidgetStyles": 22,
+ "AA_DontUseNativeDialogs": 23,
+ "AA_SynthesizeMouseForUnhandledTabletEvents": 24,
+ "AA_CompressHighFrequencyEvents": 25,
+ "AA_DontCheckOpenGLContextThreadAffinity": 26,
+ "AA_DisableShaderDiskCache": 27,
+ "AA_DontShowShortcutsInContextMenus": 28,
+ "AA_CompressTabletEvents": 29,
+ "AA_DisableWindowContextHelpButton": 30,
+ "AA_DisableSessionManager": 31,
+ "AA_AttributeCount": 32
+ }
+ }
+ Enum {
+ name: "ImageConversionFlags"
+ values: {
+ "ColorMode_Mask": 3,
+ "AutoColor": 0,
+ "ColorOnly": 3,
+ "MonoOnly": 2,
+ "AlphaDither_Mask": 12,
+ "ThresholdAlphaDither": 0,
+ "OrderedAlphaDither": 4,
+ "DiffuseAlphaDither": 8,
+ "NoAlpha": 12,
+ "Dither_Mask": 48,
+ "DiffuseDither": 0,
+ "OrderedDither": 16,
+ "ThresholdDither": 32,
+ "DitherMode_Mask": 192,
+ "AutoDither": 0,
+ "PreferDither": 64,
+ "AvoidDither": 128,
+ "NoOpaqueDetection": 256,
+ "NoFormatConversion": 512
+ }
+ }
+ Enum {
+ name: "BGMode"
+ values: {
+ "TransparentMode": 0,
+ "OpaqueMode": 1
+ }
+ }
+ }
+ Component { name: "QEasingCurve"; prototype: "QQmlEasingValueType" }
+}
diff --git a/tests/auto/qml/qmllint/data/coercetovoid.qml b/tests/auto/qml/qmllint/data/coercetovoid.qml
new file mode 100644
index 0000000000..f1b593ea3a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/coercetovoid.qml
@@ -0,0 +1,8 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ function touchThisAndReturnSomething(x: int) {
+ return x + 1;
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/customParser.qml b/tests/auto/qml/qmllint/data/customParser.qml
index a83ae7e823..324ca20953 100644
--- a/tests/auto/qml/qmllint/data/customParser.qml
+++ b/tests/auto/qml/qmllint/data/customParser.qml
@@ -7,11 +7,11 @@ Rectangle {
states: [
State {
name: "red_color"
- PropertyChanges { target: root; color: "red" }
+ PropertyChanges { root.color: "red" }
},
State {
name: "blue_color"
- PropertyChanges { target: root; color: "blue" }
+ PropertyChanges { root.color: "blue" }
}
]
}
diff --git a/tests/auto/qml/qmllint/data/dontCheckJSTypes.qml b/tests/auto/qml/qmllint/data/dontCheckJSTypes.qml
new file mode 100644
index 0000000000..dc582936b9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/dontCheckJSTypes.qml
@@ -0,0 +1,11 @@
+import QtQuick
+
+import "SharedFunctions.js" as Functions
+
+Item {
+ Rectangle {
+ color: Functions.setColorAlpha(Qt.color("orange"), 0.15)
+ x: Functions.setColorAlpha.asdfg
+ y: Functions.asdfg
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/findMemberPrint.qml b/tests/auto/qml/qmllint/data/findMemberPrint.qml
new file mode 100644
index 0000000000..69146eb06b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/findMemberPrint.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+import TestTypes
+
+QtObject {
+ property var foooooooo: Foo {
+ id: foo
+ }
+
+ function f(): void {
+ foo.print()
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/generalizedGroupHint.qml b/tests/auto/qml/qmllint/data/generalizedGroupHint.qml
new file mode 100644
index 0000000000..5fec03f7f3
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/generalizedGroupHint.qml
@@ -0,0 +1,23 @@
+import QtQuick
+
+Window {
+ width: 640
+ height: 480
+ visible: true
+ title: 'Resolve my color type'
+
+ Item {
+ id: foo
+
+ states: [
+ State {
+ PropertyChanges {
+ target: foo
+ myColor: Qt.rgba(0.5, 0.5, 0.5, 0.16)
+ }
+ }
+ ]
+
+ property color myColor: 'black'
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/groupedAttachedLayout.qml b/tests/auto/qml/qmllint/data/groupedAttachedLayout.qml
new file mode 100644
index 0000000000..7cfe98d4f8
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/groupedAttachedLayout.qml
@@ -0,0 +1,20 @@
+import QtQuick
+import QtQuick.Layouts
+
+Window {
+ id: root
+
+ Rectangle {
+ id: redRect
+ }
+
+ Item {
+ states: [
+ State {
+ PropertyChanges {
+ redRect.Layout.fillWidth: true
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/main.qml b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/main.qml
new file mode 100644
index 0000000000..d018110b86
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/main.qml
@@ -0,0 +1,11 @@
+import QtQuick
+import QtQuick.Controls
+
+Window {
+ width: 640; height: 480
+ visible: true
+
+ Button {
+ text: "a"
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/qmldir b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/qmldir
new file mode 100644
index 0000000000..acb456ffd9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/qmldir
@@ -0,0 +1,3 @@
+module moduleWithQrc
+prefer :/qt/qml/moduleWithQrc/
+
diff --git a/tests/auto/qml/qmllint/data/hidden/moduleWithQrc_raw_qml_0.qrc b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc_raw_qml_0.qrc
new file mode 100644
index 0000000000..43d3ec805c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc_raw_qml_0.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/qt/qml/qmllint65/">
+ <file alias="main.qml">moduleWithQrc/main.qml</file>
+ </qresource>
+</RCC>
+
diff --git a/tests/auto/qml/qmllint/data/hidden/qmake_moduleWithQrc.qrc b/tests/auto/qml/qmllint/data/hidden/qmake_moduleWithQrc.qrc
new file mode 100644
index 0000000000..cb362e2d55
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/hidden/qmake_moduleWithQrc.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/qt/qml/qmllint65">
+ <file alias="qmldir">moduleWithQrc/qmldir</file>
+ </qresource>
+</RCC>
+
diff --git a/tests/auto/qml/qmllint/data/importNonexistentFile.qml b/tests/auto/qml/qmllint/data/importNonexistentFile.qml
new file mode 100644
index 0000000000..847023936a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/importNonexistentFile.qml
@@ -0,0 +1,3 @@
+import "¯\(ツ)/¯:/invalid/url"
+
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/importNullDevice.qml b/tests/auto/qml/qmllint/data/importNullDevice.qml
new file mode 100644
index 0000000000..5ff3090d75
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/importNullDevice.qml
@@ -0,0 +1,3 @@
+import "/dev/null"
+
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/initReadonly.qml b/tests/auto/qml/qmllint/data/initReadonly.qml
index 5a3cafff23..a9a2a0016b 100644
--- a/tests/auto/qml/qmllint/data/initReadonly.qml
+++ b/tests/auto/qml/qmllint/data/initReadonly.qml
@@ -2,4 +2,5 @@ import QtQml
QtObject {
readonly property int i: 14
+ readonly property int j: i + 20
}
diff --git a/tests/auto/qml/qmllint/data/inlineComponent.qml b/tests/auto/qml/qmllint/data/inlineComponent.qml
index ce6998a980..364d5319de 100644
--- a/tests/auto/qml/qmllint/data/inlineComponent.qml
+++ b/tests/auto/qml/qmllint/data/inlineComponent.qml
@@ -1,6 +1,7 @@
import QtQuick 2.0
Item {
+ component MyIC: IC {}
component IC : QtObject {}
QtObject {
component IC2: QtObject {}
diff --git a/tests/auto/qml/qmllint/data/invalidIdLookup.qml b/tests/auto/qml/qmllint/data/invalidIdLookup.qml
new file mode 100644
index 0000000000..b351e5cfea
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/invalidIdLookup.qml
@@ -0,0 +1,10 @@
+import Things
+import QtQml
+
+QtObject {
+ property MediaPlayerStateMachine m: MediaPlayerStateMachine {
+ id: stateMachine
+ }
+
+ objectName: stateMachine.objectName
+}
diff --git a/tests/auto/qml/qmllint/data/jsonArrayIsRecognized.qml b/tests/auto/qml/qmllint/data/jsonArrayIsRecognized.qml
new file mode 100644
index 0000000000..89c52e0e52
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/jsonArrayIsRecognized.qml
@@ -0,0 +1,8 @@
+import QtQuick
+import Qtbug111015 1.0
+
+Item {
+ TypeWithJsonArray {
+ jsonArray: []
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/jsonObjectIsRecognized.qml b/tests/auto/qml/qmllint/data/jsonObjectIsRecognized.qml
new file mode 100644
index 0000000000..0a96fa9f92
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/jsonObjectIsRecognized.qml
@@ -0,0 +1,8 @@
+import QtQuick
+import Qtbug111015 1.0
+
+Item {
+ TypeWithJsonObjectList {
+ jsonObjectList: []
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/locale.qml b/tests/auto/qml/qmllint/data/locale.qml
new file mode 100644
index 0000000000..4ff9e6392c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/locale.qml
@@ -0,0 +1,6 @@
+import QtQml
+import LocaleTest
+
+QtObject {
+ property int monday: AppManager.primaryLocale.firstDayOfWeek
+}
diff --git a/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport.qml b/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport.qml
new file mode 100644
index 0000000000..14c716c35d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport.qml
@@ -0,0 +1,9 @@
+import QtQuick as test
+
+test.Rectangle { // crashed qqmljsimportvisitor
+ id: mainRect
+ width: 100
+ height: 100
+ visible: true
+ rotation: 11
+}
diff --git a/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport2.qml b/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport2.qml
new file mode 100644
index 0000000000..4e03d8091d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport2.qml
@@ -0,0 +1,9 @@
+import QtQuick as test
+
+test.Item {
+ property test.color c
+
+ property var p: test.Grid {}
+
+ component IC: test.Rectangle {}
+}
diff --git a/tests/auto/qml/qmllint/data/multifix.fixed.qml b/tests/auto/qml/qmllint/data/multifix.fixed.qml
new file mode 100644
index 0000000000..d2188f2318
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/multifix.fixed.qml
@@ -0,0 +1,14 @@
+pragma ComponentBehavior: Bound
+import QtQml
+
+QtObject {
+ id: root
+
+ property Component cursorDelegate: QtObject {
+ objectName: root.objectName
+ }
+
+ property Component background: QtObject {
+ objectName: root.objectName
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/multifix.qml b/tests/auto/qml/qmllint/data/multifix.qml
new file mode 100644
index 0000000000..5f05ae7e62
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/multifix.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+QtObject {
+ id: root
+
+ property Component cursorDelegate: QtObject {
+ objectName: root.objectName
+ }
+
+ property Component background: QtObject {
+ objectName: root.objectName
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/notQmlRootMethods.qml b/tests/auto/qml/qmllint/data/notQmlRootMethods.qml
new file mode 100644
index 0000000000..6d067d572d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/notQmlRootMethods.qml
@@ -0,0 +1,8 @@
+import QtQml
+
+QtObject {
+ id: self
+
+ function a() { self.deleteLater(); }
+ function b() { self.destroyed(); }
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_anchorsUndefined.qml b/tests/auto/qml/qmllint/data/pluginQuick_anchorsUndefined.qml
index 2a51cceac3..b6c0f59c7f 100644
--- a/tests/auto/qml/qmllint/data/pluginQuick_anchorsUndefined.qml
+++ b/tests/auto/qml/qmllint/data/pluginQuick_anchorsUndefined.qml
@@ -5,5 +5,6 @@ Item {
anchors.horizontalCenter: undefined
anchors.verticalCenter: undefined
anchors.baseline: undefined
+ Component.onCompleted: anchors.bottom = undefined
}
}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesInvalidTarget.qml b/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesInvalidTarget.qml
new file mode 100644
index 0000000000..fa7d4ef1ac
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesInvalidTarget.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+Rectangle {
+ State {
+ name: "test"
+ PropertyChanges { target: root; color: "blue" }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesParsed.qml b/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesParsed.qml
new file mode 100644
index 0000000000..94873463f1
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesParsed.qml
@@ -0,0 +1,19 @@
+import QtQuick
+
+Window {
+ Item {
+ id: foo
+ property color myColor: 'black'
+
+ states: [
+ State {
+ PropertyChanges {
+ target: foo
+ myColor: Qt.rgba(0.5, 0.5, 0.5, 0.16)
+ notThere: "a"
+ }
+ }
+ ]
+
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/qEventPoint.qml b/tests/auto/qml/qmllint/data/qEventPoint.qml
new file mode 100644
index 0000000000..086e710b48
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qEventPoint.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+TapHandler {
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onSingleTapped: (eventPoint, button) => {
+ console.log("Single tap at", eventPoint, "with button", button)
+ }
+ onTapped: console.log("tapped")
+}
diff --git a/tests/auto/qml/qmllint/data/qmlRootMethods.qml b/tests/auto/qml/qmllint/data/qmlRootMethods.qml
new file mode 100644
index 0000000000..5541de3a32
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qmlRootMethods.qml
@@ -0,0 +1,12 @@
+import QtQml
+
+QtObject {
+ id: self
+
+ objectName: self.toString()
+
+ Component.onCompleted: {
+ self.destroy();
+ self.destroy(25);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml b/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml
index 4847fc9196..ad88f1c58c 100644
--- a/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml
+++ b/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml
@@ -2,5 +2,5 @@ import Things 1.0
Something {
property var a: SomethingEntirelyStrange {}
- property var b: SomethingEntirelyStrange.AAA
+ property var b: SomethingEntirelyStrange.AnEnum.AAA
}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml
new file mode 100644
index 0000000000..de142337b4
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml
@@ -0,0 +1,9 @@
+import QtQml
+import QtQuick
+
+QtObject {
+ id: root
+ component Comp : Item { }
+ property Comp c: Comp{ }
+ function comp() { return root.c }
+}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml
new file mode 100644
index 0000000000..0585ceceb2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+QtObject {
+ function enumeration() { return Text.AlignRight }
+}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml
new file mode 100644
index 0000000000..dc03311e73
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ function f() { }
+ function method() { return f }
+}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml
new file mode 100644
index 0000000000..bb79978d85
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml
@@ -0,0 +1,7 @@
+import QtQml
+
+QtObject {
+ id: root
+ property int i: 1
+ function prop() { return root.i }
+}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml
new file mode 100644
index 0000000000..78f02a8b67
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ function type() { return 1 + 1 }
+}
diff --git a/tests/auto/qml/qmllint/data/scriptInTemplate.qml b/tests/auto/qml/qmllint/data/scriptInTemplate.qml
new file mode 100644
index 0000000000..ba333dcd3e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scriptInTemplate.qml
@@ -0,0 +1,6 @@
+import QtQml
+import scripts
+
+QtObject {
+ objectName: `Result: ${Foo.getText()}`
+}
diff --git a/tests/auto/qml/qmllint/data/scripts/Foo.js b/tests/auto/qml/qmllint/data/scripts/Foo.js
new file mode 100644
index 0000000000..1d5106f733
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scripts/Foo.js
@@ -0,0 +1,6 @@
+.pragma library
+
+function getText() {
+ return "whohoooooo"
+}
+
diff --git a/tests/auto/qml/qmllint/data/scripts/qmldir b/tests/auto/qml/qmllint/data/scripts/qmldir
new file mode 100644
index 0000000000..b4bf844348
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scripts/qmldir
@@ -0,0 +1,4 @@
+module scripts
+typeinfo scripts.qmltypes
+Foo 1.0 Foo.js
+
diff --git a/tests/auto/qml/qmllint/data/scripts/scripts.qmltypes b/tests/auto/qml/qmllint/data/scripts/scripts.qmltypes
new file mode 100644
index 0000000000..ebbfc41eb2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scripts/scripts.qmltypes
@@ -0,0 +1,22 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by qmltyperegistrar.
+
+Module {
+ Component {
+ file: "value.h"
+ name: "ValueType"
+ accessSemantics: "value"
+ exports: ["scripts/vvv 1.0"]
+ exportMetaObjectRevisions: [256]
+ Method {
+ name: "ValueType"
+ isConstructor: true
+ Parameter { name: "v"; type: "QString" }
+ }
+ Method { name: "ValueType"; isCloned: true; isConstructor: true }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/scriptstring.qml b/tests/auto/qml/qmllint/data/scriptstring.qml
new file mode 100644
index 0000000000..733434e924
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scriptstring.qml
@@ -0,0 +1,73 @@
+import QtQuick
+
+Window {
+ id: root
+
+ Rectangle {
+ id: main
+
+ MouseArea {
+ id: mouse
+ property int clickCount: 0
+ onClicked: {
+ clickCount++
+
+ switch ( clickCount % 3 ) {
+ case 1 :
+ main.state = "middleState"
+ break
+ case 2 :
+ main.state = "rightState"
+ break
+ default :
+ main.state = "leftState"
+ }
+ }
+ }
+
+ Rectangle {
+ id: mover
+ anchors {
+ left: undefined
+ right: undefined
+ horizontalCenter: undefined
+ top: main.top
+ bottom: main.bottom
+ }
+ }
+
+ states: [
+ State {
+ name: "leftState"
+ AnchorChanges {
+ target: mover
+ anchors.left: main.left
+ anchors.right: undefined
+ anchors.horizontalCenter: undefined
+ }
+ },
+ State {
+ name: "middleState"
+ AnchorChanges {
+ target: mover
+ anchors {
+ left: undefined
+ right: undefined
+ horizontalCenter: main.horizontalCenter
+ }
+ }
+ },
+ State {
+ name: "rightState"
+ AnchorChanges {
+ target: mover
+ anchors {
+ left: undefined
+ right: main.right
+ horizontalCenter: undefined
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/settings/plugin/.qmllint.ini b/tests/auto/qml/qmllint/data/settings/plugin/.qmllint.ini
new file mode 100644
index 0000000000..a72e0e29e2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/plugin/.qmllint.ini
@@ -0,0 +1,2 @@
+[Warnings]
+TestWarning=disable
diff --git a/tests/auto/qml/qmllint/data/settings/plugin/elemenpass_pluginSettingTest.qml b/tests/auto/qml/qmllint/data/settings/plugin/elemenpass_pluginSettingTest.qml
new file mode 100644
index 0000000000..b9250a2d11
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/plugin/elemenpass_pluginSettingTest.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ Rectangle {
+ radius: 5
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/something.qml b/tests/auto/qml/qmllint/data/something.qml
new file mode 100644
index 0000000000..38998f606d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/something.qml
@@ -0,0 +1,2 @@
+import ModuleInImportPath
+A {}
diff --git a/tests/auto/qml/qmllint/data/storeNameMethod.qml b/tests/auto/qml/qmllint/data/storeNameMethod.qml
new file mode 100644
index 0000000000..fca02b288f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/storeNameMethod.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ Rectangle {
+
+ Timer {
+ function foo() {}
+ onTriggered: foo = 1
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/stringToDateTime.qml b/tests/auto/qml/qmllint/data/stringToDateTime.qml
new file mode 100644
index 0000000000..dc4bd6cda5
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/stringToDateTime.qml
@@ -0,0 +1,7 @@
+import StringToDateTime
+
+StringToDateTime {
+ aDate: "2023-03-29"
+ aTime: "15:10:41"
+ aDateTime: "2023-03-29 15:10:41"
+}
diff --git a/tests/auto/qml/qmllint/data/untitled/components/Foo.qml b/tests/auto/qml/qmllint/data/untitled/components/Foo.qml
new file mode 100644
index 0000000000..10e5741900
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/untitled/components/Foo.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Text {
+ text: "Here I am!"
+}
diff --git a/tests/auto/qml/qmllint/data/untitled/main.qml b/tests/auto/qml/qmllint/data/untitled/main.qml
new file mode 100644
index 0000000000..cf8980ab55
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/untitled/main.qml
@@ -0,0 +1,9 @@
+pragma Strict
+
+import QtQuick
+import 'qrc:/untitled/components' as C
+
+Window {
+ id: root
+ C.Foo {}
+}
diff --git a/tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc b/tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc
new file mode 100644
index 0000000000..0ad0d57fbb
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/untitled/">
+ <file alias="main.qml">main.qml</file>
+ <file alias="components/Foo.qml">components/Foo.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/qml/qmllint/data/useConstInvokable.qml b/tests/auto/qml/qmllint/data/useConstInvokable.qml
new file mode 100644
index 0000000000..4f89e89918
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/useConstInvokable.qml
@@ -0,0 +1,5 @@
+import Things
+
+ConstInvokable {
+ objectName: getObject().objectName
+}
diff --git a/tests/auto/qml/qmllint/data/validLiterals.qml b/tests/auto/qml/qmllint/data/validLiterals.qml
index 4f8c575cd3..55792eaae2 100644
--- a/tests/auto/qml/qmllint/data/validLiterals.qml
+++ b/tests/auto/qml/qmllint/data/validLiterals.qml
@@ -29,9 +29,9 @@ QtObject {
property date date1: "2021-08-13T14:16:21.435Z"
- property point point1: "1,2"
+ property point point1: ({ x: 1, y: 2 })
- property size size1: "50x50"
+ property size size1: ({ width: 50, height: 50 })
- property rect rect1: "10,20,30x30"
+ property rect rect1: ({ x: 10, y: 20, width: 30, height: 30 })
}
diff --git a/tests/auto/qml/qmllint/data/valueTypesFromString.qml b/tests/auto/qml/qmllint/data/valueTypesFromString.qml
new file mode 100644
index 0000000000..fc013f858f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/valueTypesFromString.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ property point p: "30,50"
+ property rect p3: "10, 20, 30x50"
+ property size p4: "30x50"
+}
diff --git a/tests/auto/qml/qmllint/data/variantMapLookup.qml b/tests/auto/qml/qmllint/data/variantMapLookup.qml
new file mode 100644
index 0000000000..7f50879932
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/variantMapLookup.qml
@@ -0,0 +1,13 @@
+pragma Strict
+import TestTypes
+import QtQuick
+
+Item {
+ VariantMapLookupFoo {
+ id: moo
+ }
+ Component.onCompleted: {
+ moo.data.value = 5
+ moo.data["value"] = 6
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/writeListProperty.qml b/tests/auto/qml/qmllint/data/writeListProperty.qml
new file mode 100644
index 0000000000..8015fdf51b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/writeListProperty.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ id: self
+ property Item a: Item { id: a }
+ Component.onCompleted: self.data = [ a ]
+}
diff --git a/tests/auto/qml/qmllint/lintplugin.cpp b/tests/auto/qml/qmllint/lintplugin.cpp
index 47279adcaa..58b174cb6b 100644
--- a/tests/auto/qml/qmllint/lintplugin.cpp
+++ b/tests/auto/qml/qmllint/lintplugin.cpp
@@ -1,11 +1,11 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "lintplugin.h"
using namespace Qt::StringLiterals;
-static constexpr LoggerWarningId plugin { "testPlugin.test" };
+static constexpr QQmlSA::LoggerWarningId plugin{ "testPlugin.test" };
class ElementTest : public QQmlSA::ElementPass
{
@@ -17,25 +17,25 @@ public:
bool shouldRun(const QQmlSA::Element &element) override
{
- return element->baseType() == m_rectangle;
+ return element.baseType() == m_rectangle;
}
void run(const QQmlSA::Element &element) override
{
- auto property = element->property(u"radius"_s);
- if (!property.isValid() || element->property(u"radius"_s).typeName() != u"double") {
- emitWarning(u"Failed to verify radius property", plugin, element->sourceLocation());
+ auto property = element.property(u"radius"_s);
+ if (!property.isValid() || element.property(u"radius"_s).typeName() != u"double") {
+ emitWarning(u"Failed to verify radius property", plugin, element.sourceLocation());
return;
}
- auto bindings = element->propertyBindings(u"radius"_s);
+ auto bindings = element.propertyBindings(u"radius"_s);
if (bindings.isEmpty() || bindings.constFirst().numberValue() != 5) {
emitWarning(u"Failed to verify radius property binding", plugin,
- element->sourceLocation());
+ element.sourceLocation());
return;
}
- emitWarning(u"ElementTest OK", plugin, element->sourceLocation());
+ emitWarning(u"ElementTest OK", plugin, element.sourceLocation());
}
private:
@@ -48,37 +48,37 @@ public:
PropertyTest(QQmlSA::PassManager *manager) : QQmlSA::PropertyPass(manager) { }
void onBinding(const QQmlSA::Element &element, const QString &propertyName,
- const QQmlJSMetaPropertyBinding &binding, const QQmlSA::Element &bindingScope,
+ const QQmlSA::Binding &binding, const QQmlSA::Element &bindingScope,
const QQmlSA::Element &value) override
{
emitWarning(u"Saw binding on %1 property %2 with value %3 (and type %4) in scope %5"_s
- .arg(element->baseTypeName(), propertyName,
+ .arg(element.baseTypeName(), propertyName,
value.isNull()
? u"NULL"_s
- : (value->internalName().isNull() ? value->baseTypeName()
- : value->baseTypeName()))
- .arg(binding.bindingType())
- .arg(bindingScope->baseTypeName()),
- plugin, bindingScope->sourceLocation());
+ : (value.name().isNull() ? value.baseTypeName()
+ : value.name()))
+ .arg(qToUnderlying(binding.bindingType()))
+ .arg(bindingScope.baseTypeName()),
+ plugin, bindingScope.sourceLocation());
}
void onRead(const QQmlSA::Element &element, const QString &propertyName,
- const QQmlSA::Element &readScope, QQmlJS::SourceLocation location) override
+ const QQmlSA::Element &readScope, QQmlSA::SourceLocation location) override
{
emitWarning(u"Saw read on %1 property %2 in scope %3"_s.arg(
- element->baseTypeName(), propertyName, readScope->baseTypeName()),
+ element.baseTypeName(), propertyName, readScope.baseTypeName()),
plugin, location);
}
void onWrite(const QQmlSA::Element &element, const QString &propertyName,
const QQmlSA::Element &value, const QQmlSA::Element &writeScope,
- QQmlJS::SourceLocation location) override
+ QQmlSA::SourceLocation location) override
{
emitWarning(u"Saw write on %1 property %2 with value %3 in scope %4"_s.arg(
- element->baseTypeName(), propertyName,
- (value->internalName().isNull() ? value->baseTypeName()
- : value->internalName()),
- writeScope->baseTypeName()),
+ element.baseTypeName(), propertyName,
+ (value.name().isNull() ? value.baseTypeName()
+ : value.name()),
+ writeScope.baseTypeName()),
plugin, location);
}
};
@@ -109,7 +109,7 @@ private:
void LintPlugin::registerPasses(QQmlSA::PassManager *manager, const QQmlSA::Element &rootElement)
{
- if (!rootElement->filePath().endsWith(u"_pluginTest.qml"))
+ if (!rootElement.filePath().endsWith(u"_pluginTest.qml"))
return;
manager->registerElementPass(std::make_unique<ElementTest>(manager));
diff --git a/tests/auto/qml/qmllint/lintplugin.h b/tests/auto/qml/qmllint/lintplugin.h
index 76733ca7a7..c121657456 100644
--- a/tests/auto/qml/qmllint/lintplugin.h
+++ b/tests/auto/qml/qmllint/lintplugin.h
@@ -1,12 +1,12 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef LINTPLUGIN_H
#define LINTPLUGIN_H
#include <QtPlugin>
#include <QtCore/qobject.h>
-#include <QtQmlCompiler/private/qqmlsa_p.h>
+#include <QtQmlCompiler/qqmlsa.h>
class LintPlugin : public QObject, public QQmlSA::LintPlugin
{
diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp
index a5e906ce9a..1730f38a51 100644
--- a/tests/auto/qml/qmllint/tst_qmllint.cpp
+++ b/tests/auto/qml/qmllint/tst_qmllint.cpp
@@ -1,6 +1,6 @@
// Copyright (C) 2016 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sergio Martins <sergio.martins@kdab.com>
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QProcess>
@@ -43,6 +43,11 @@ public:
Flags flags = {};
};
+ struct Environment : public QList<QPair<QString, QString>>
+ {
+ using QList<QPair<QString, QString>>::QList;
+ };
+
private Q_SLOTS:
void initTestCase() override;
@@ -73,12 +78,19 @@ private Q_SLOTS:
void autoqmltypes();
void resources();
+ void multiDirectory();
+
void requiredProperty();
void settingsFile();
void additionalImplicitImport();
+ void qrcUrlImport();
+
+ void incorrectImportFromHost_data();
+ void incorrectImportFromHost();
+
void attachedPropertyReuse();
void missingBuiltinsNoCrash();
@@ -90,11 +102,21 @@ private Q_SLOTS:
void lintModule();
void testLineEndings();
+ void valueTypesFromString();
+
+ void ignoreSettingsNotCommandLineOptions();
+ void backslashedQmldirPath();
+
+ void environment_data();
+ void environment();
+
+ void maxWarnings();
#if QT_CONFIG(library)
void testPlugin();
void quickPlugin();
#endif
+
private:
enum DefaultImportOption { NoDefaultImports, UseDefaultImports };
enum ContainOption { StringNotContained, StringContained };
@@ -105,17 +127,24 @@ private:
enum LintType { LintFile, LintModule };
+ static QStringList warningsShouldFailArgs() {
+ static QStringList args {"-W", "0"};
+ return args;
+ }
+
QString runQmllint(const QString &fileToLint, std::function<void(QProcess &)> handleResult,
const QStringList &extraArgs = QStringList(), bool ignoreSettings = true,
- bool addImportDirs = true, bool absolutePath = true);
+ bool addImportDirs = true, bool absolutePath = true,
+ const Environment &env = {});
QString runQmllint(const QString &fileToLint, bool shouldSucceed,
const QStringList &extraArgs = QStringList(), bool ignoreSettings = true,
- bool addImportDirs = true, bool absolutePath = true);
+ bool addImportDirs = true, bool absolutePath = true,
+ const Environment &env = {});
void callQmllint(const QString &fileToLint, bool shouldSucceed, QJsonArray *warnings = nullptr,
QStringList importDirs = {}, QStringList qmltypesFiles = {},
QStringList resources = {},
DefaultImportOption defaultImports = UseDefaultImports,
- QList<QQmlJSLogger::Category> *categories = nullptr, bool autoFixable = false,
+ QList<QQmlJS::LoggerCategory> *categories = nullptr, bool autoFixable = false,
LintType type = LintFile);
void searchWarnings(const QJsonArray &warnings, const QString &string,
@@ -137,7 +166,7 @@ private:
void runTest(const QString &testFile, const Result &result, QStringList importDirs = {},
QStringList qmltypesFiles = {}, QStringList resources = {},
DefaultImportOption defaultImports = UseDefaultImports,
- QList<QQmlJSLogger::Category> *categories = nullptr);
+ QList<QQmlJS::LoggerCategory> *categories = nullptr);
QString m_qmllintPath;
QString m_qmljsrootgenPath;
@@ -258,6 +287,12 @@ void TestQmllint::testUnqualified_data()
Message {
QStringLiteral("index is implicitly injected into this delegate. "
"Add a required property instead.") } } };
+ QTest::newRow("storeSloppy")
+ << QStringLiteral("UnqualifiedInStoreSloppy.qml")
+ << Result{ { Message{ QStringLiteral("Unqualified access"), 9, 26} } };
+ QTest::newRow("storeStrict")
+ << QStringLiteral("UnqualifiedInStoreStrict.qml")
+ << Result{ { Message{ QStringLiteral("Unqualified access"), 9, 52} } };
}
void TestQmllint::testUnknownCausesFail()
@@ -355,12 +390,12 @@ void TestQmllint::verifyJsRoot()
QString currentJsRootContent, generatedJsRootContent;
QFile currentJsRoot(currentJsRootPath);
- QVERIFY(currentJsRoot.open(QFile::ReadOnly));
+ QVERIFY(currentJsRoot.open(QFile::ReadOnly | QIODevice::Text));
currentJsRootContent = QString::fromUtf8(currentJsRoot.readAll());
currentJsRoot.close();
QFile generatedJsRoot(dir.path() + QDir::separator() + "jsroot.qmltypes");
- QVERIFY(generatedJsRoot.open(QFile::ReadOnly));
+ QVERIFY(generatedJsRoot.open(QFile::ReadOnly | QIODevice::Text));
generatedJsRootContent = QString::fromUtf8(generatedJsRoot.readAll());
generatedJsRoot.close();
@@ -383,7 +418,7 @@ void TestQmllint::autoqmltypes()
{
QProcess process;
process.setWorkingDirectory(testFile("autoqmltypes"));
- process.start(m_qmllintPath, { QStringLiteral("test.qml") });
+ process.start(m_qmllintPath, warningsShouldFailArgs() << QStringLiteral("test.qml") );
process.waitForFinished();
@@ -393,6 +428,21 @@ void TestQmllint::autoqmltypes()
QVERIFY(process.readAllStandardError()
.contains("is not a qmldir file. Assuming qmltypes"));
QVERIFY(process.readAllStandardOutput().isEmpty());
+
+ {
+ QProcess bare;
+ bare.setWorkingDirectory(testFile("autoqmltypes"));
+ bare.start(m_qmllintPath, warningsShouldFailArgs() << QStringLiteral("--bare") << QStringLiteral("test.qml") );
+ bare.waitForFinished();
+
+ const QByteArray errors = bare.readAllStandardError();
+ QVERIFY(!errors.contains("is not a qmldir file. Assuming qmltypes"));
+ QVERIFY(errors.contains("Failed to import TestTest."));
+ QVERIFY(bare.readAllStandardOutput().isEmpty());
+
+ QCOMPARE(bare.exitStatus(), QProcess::NormalExit);
+ QVERIFY(bare.exitCode() != 0);
+ }
}
void TestQmllint::resources()
@@ -422,6 +472,17 @@ void TestQmllint::resources()
}
}
+void TestQmllint::multiDirectory()
+{
+ callQmllint(
+ testFile("MultiDirectory/qml/Inner.qml"), true, nullptr,
+ {}, {}, { testFile("MultiDirectory/multi.qrc") });
+
+ callQmllint(
+ testFile("MultiDirectory/qml/pages/Page.qml"), true, nullptr,
+ {}, {}, { testFile("MultiDirectory/multi.qrc") });
+}
+
void TestQmllint::dirtyQmlCode_data()
{
QTest::addColumn<QString>("filename");
@@ -444,12 +505,12 @@ void TestQmllint::dirtyQmlCode_data()
QTest::newRow("MemberNotFound")
<< QStringLiteral("memberNotFound.qml")
<< Result { { Message {
- QStringLiteral("Property \"foo\" not found on type \"QtObject\""), 6,
+ QStringLiteral("Member \"foo\" not found on type \"QtObject\""), 6,
31 } } };
QTest::newRow("UnknownJavascriptMethd")
<< QStringLiteral("unknownJavascriptMethod.qml")
<< Result { { Message {
- QStringLiteral("Property \"foo2\" not found on type \"Methods\""), 5,
+ QStringLiteral("Member \"foo2\" not found on type \"Methods\""), 5,
25 } } };
QTest::newRow("badAlias")
<< QStringLiteral("badAlias.qml")
@@ -463,6 +524,12 @@ void TestQmllint::dirtyQmlCode_data()
QStringLiteral("Invalid alias expression. Only IDs and field member "
"expressions can be aliased"),
5, 26 } } };
+ QTest::newRow("badAliasNotAnExpression")
+ << QStringLiteral("badAliasNotAnExpression.qml")
+ << Result { { Message {
+ QStringLiteral("Invalid alias expression. Only IDs and field member "
+ "expressions can be aliased"),
+ 4, 30 } } };
QTest::newRow("aliasCycle1") << QStringLiteral("aliasCycle.qml")
<< Result { { Message {
QStringLiteral("Alias \"b\" is part of an alias cycle"),
@@ -485,17 +552,17 @@ void TestQmllint::dirtyQmlCode_data()
9, 34 } } };
QTest::newRow("badParent")
<< QStringLiteral("badParent.qml")
- << Result { { Message { QStringLiteral("Property \"rrr\" not found on type \"Item\""),
+ << Result { { Message { QStringLiteral("Member \"rrr\" not found on type \"Item\""),
5, 34 } } };
QTest::newRow("parentIsComponent")
<< QStringLiteral("parentIsComponent.qml")
<< Result { { Message {
- QStringLiteral("Property \"progress\" not found on type \"QQuickItem\""), 7,
+ QStringLiteral("Member \"progress\" not found on type \"QQuickItem\""), 7,
39 } } };
QTest::newRow("badTypeAssertion")
<< QStringLiteral("badTypeAssertion.qml")
<< Result { { Message {
- QStringLiteral("Property \"rrr\" not found on type \"QQuickItem\""), 5,
+ QStringLiteral("Member \"rrr\" not found on type \"QQuickItem\""), 5,
39 } } };
QTest::newRow("incompleteQmltypes")
<< QStringLiteral("incompleteQmltypes.qml")
@@ -504,7 +571,7 @@ void TestQmllint::dirtyQmlCode_data()
26 } } };
QTest::newRow("incompleteQmltypes2")
<< QStringLiteral("incompleteQmltypes2.qml")
- << Result { { Message { QStringLiteral("Property \"weDontKnowIt\" "
+ << Result { { Message { QStringLiteral("Member \"weDontKnowIt\" "
"not found on type \"CustomPalette\""),
5, 35 } } };
QTest::newRow("incompleteQmltypes3")
@@ -526,11 +593,11 @@ void TestQmllint::dirtyQmlCode_data()
QTest::newRow("javascriptMethodsInModule")
<< QStringLiteral("javascriptMethodsInModuleBad.qml")
<< Result { { Message {
- QStringLiteral("Property \"unknownFunc\" not found on type \"Foo\""), 5,
+ QStringLiteral("Member \"unknownFunc\" not found on type \"Foo\""), 5,
21 } } };
QTest::newRow("badEnumFromQtQml")
<< QStringLiteral("badEnumFromQtQml.qml")
- << Result { { Message { QStringLiteral("Property \"Linear123\" not "
+ << Result { { Message { QStringLiteral("Member \"Linear123\" not "
"found on type \"QQmlEasingEnums\""),
4, 30 } } };
QTest::newRow("anchors3")
@@ -548,13 +615,13 @@ void TestQmllint::dirtyQmlCode_data()
"unknown grouped property scope nanchors.") } } };
QTest::newRow("badAliasObject")
<< QStringLiteral("badAliasObject.qml")
- << Result { { Message { QStringLiteral("Property \"wrongwrongwrong\" not "
+ << Result { { Message { QStringLiteral("Member \"wrongwrongwrong\" not "
"found on type \"QtObject\""),
8, 40 } } };
QTest::newRow("badScript") << QStringLiteral("badScript.qml")
<< Result { { Message {
QStringLiteral(
- "Property \"stuff\" not found on type \"Empty\""),
+ "Member \"stuff\" not found on type \"Empty\""),
5, 21 } } };
QTest::newRow("badScriptOnAttachedProperty")
<< QStringLiteral("badScript.attached.qml")
@@ -565,7 +632,7 @@ void TestQmllint::dirtyQmlCode_data()
QTest::newRow("segFault (bad)")
<< QStringLiteral("SegFault.bad.qml")
<< Result { { Message { QStringLiteral(
- "Property \"foobar\" not found on type \"QQuickScreenAttached\"") } } };
+ "Member \"foobar\" not found on type \"QQuickScreenAttached\"") } } };
QTest::newRow("VariableUsedBeforeDeclaration")
<< QStringLiteral("useBeforeDeclaration.qml")
<< Result { { Message {
@@ -585,7 +652,7 @@ void TestQmllint::dirtyQmlCode_data()
"than the signal it handles.") } } };
QTest::newRow("OnAssignment") << QStringLiteral("onAssignment.qml")
<< Result { { Message { QStringLiteral(
- "Property \"loops\" not found on type \"bool\"") } } };
+ "Member \"loops\" not found on type \"bool\"") } } };
QTest::newRow("BadAttached") << QStringLiteral("badAttached.qml")
<< Result { { Message { QStringLiteral(
"unknown attached property scope WrongAttached.") } } };
@@ -702,13 +769,14 @@ void TestQmllint::dirtyQmlCode_data()
QTest::newRow("badAttachedProperty")
<< QStringLiteral("badAttachedProperty.qml")
<< Result { { Message {
- QStringLiteral("Property \"progress\" not found on type \"TestType\"") } } };
+ QStringLiteral("Member \"progress\" not found on type \"TestTypeAttached\"")
+ } } };
QTest::newRow("badAttachedPropertyNested")
<< QStringLiteral("badAttachedPropertyNested.qml")
<< Result { { Message { QStringLiteral(
- "Property \"progress\" not found on type \"QObject\""),
+ "Member \"progress\" not found on type \"QObject\""),
12, 41 } },
- { Message { QString("Property \"progress\" not found on type \"QObject\""),
+ { Message { QString("Member \"progress\" not found on type \"QObject\""),
6, 37 } } };
QTest::newRow("badAttachedPropertyTypeString")
<< QStringLiteral("badAttachedPropertyTypeString.qml")
@@ -780,6 +848,14 @@ singleTicks: ' \\' \\\\'
expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
16, 27 } },
{ Result::ExitsNormally, Result::AutoFixable } };
+ QTest::addRow("multifix")
+ << QStringLiteral("multifix.qml")
+ << Result { {
+ Message { QStringLiteral("Unqualified access"), 7, 19, QtWarningMsg},
+ Message { QStringLiteral("Unqualified access"), 11, 19, QtWarningMsg},
+ }, {}, {
+ Message { QStringLiteral("pragma ComponentBehavior: Bound\n"), 1, 1 }
+ }, { Result::AutoFixable }};
QTest::newRow("unresolvedType")
<< QStringLiteral("unresolvedType.qml")
<< Result { { Message { QStringLiteral(
@@ -812,7 +888,7 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
QTest::newRow("QtQuick.Window 2.0")
<< QStringLiteral("qtquickWindow20.qml")
<< Result { { Message { QStringLiteral(
- "Property \"window\" not found on type \"QQuickWindow\"") } } };
+ "Member \"window\" not found on type \"QQuickWindow\"") } } };
QTest::newRow("unresolvedAttachedType")
<< QStringLiteral("unresolvedAttachedType.qml")
<< Result { { Message { QStringLiteral(
@@ -879,22 +955,22 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
QTest::newRow("enumInvalid")
<< QStringLiteral("enumInvalid.qml")
<< Result { { Message {
- QStringLiteral("Property \"red\" not found on type \"QtObject\"") } } };
+ QStringLiteral("Member \"red\" not found on type \"QtObject\"") } } };
QTest::newRow("inaccessibleId")
<< QStringLiteral("inaccessibleId.qml")
<< Result { { Message {
- QStringLiteral("Property \"objectName\" not found on type \"int\"") } } };
+ QStringLiteral("Member \"objectName\" not found on type \"int\"") } } };
QTest::newRow("inaccessibleId2")
<< QStringLiteral("inaccessibleId2.qml")
<< Result { { Message {
- QStringLiteral("Property \"objectName\" not found on type \"int\"") } } };
+ QStringLiteral("Member \"objectName\" not found on type \"int\"") } } };
QTest::newRow("unknownTypeCustomParser")
<< QStringLiteral("unknownTypeCustomParser.qml")
<< Result { { Message { QStringLiteral("TypeDoesNotExist was not found.") } } };
QTest::newRow("nonNullStored")
<< QStringLiteral("nonNullStored.qml")
<< Result { { Message { QStringLiteral(
- "Property \"objectName\" not found on type \"Foozle\"") } },
+ "Member \"objectName\" not found on type \"Foozle\"") } },
{ Message { QStringLiteral("Unqualified access") } } };
QTest::newRow("cppPropertyChangeHandlers-wrong-parameters-size-bindable")
<< QStringLiteral("badCppPropertyChangeHandlers1.qml")
@@ -936,13 +1012,13 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
QTest::newRow("didYouMean(property)")
<< QStringLiteral("didYouMeanProperty.qml")
<< Result { { Message { QStringLiteral(
- "Property \"hoight\" not found on type \"Rectangle\"") },
+ "Member \"hoight\" not found on type \"Rectangle\"") },
{},
{ Message { QStringLiteral("height") } } } };
QTest::newRow("didYouMean(propertyCall)")
<< QStringLiteral("didYouMeanPropertyCall.qml")
<< Result {
- { Message { QStringLiteral("Property \"lgg\" not found on type \"Console\"") },
+ { Message { QStringLiteral("Member \"lgg\" not found on type \"Console\"") },
{},
{ Message { QStringLiteral("log") } } }
};
@@ -955,7 +1031,7 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
QTest::newRow("didYouMean(enum)")
<< QStringLiteral("didYouMeanEnum.qml")
<< Result { { Message { QStringLiteral(
- "Property \"Readx\" not found on type \"QQuickImage\"") },
+ "Member \"Readx\" not found on type \"QQuickImage\"") },
{},
{ Message { QStringLiteral("Ready") } } } };
QTest::newRow("nullBinding") << QStringLiteral("nullBinding.qml")
@@ -1020,9 +1096,8 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
QTest::newRow("NotScopedEnumCpp")
<< QStringLiteral("NotScopedEnumCpp.qml")
<< Result{ { Message{
- QStringLiteral(
- "Type is an unscoped enum. You cannot access \"V1\" from here."),
- 5, 57 } } };
+ QStringLiteral("You cannot access unscoped enum \"TheEnum\" from here."), 5,
+ 49 } } };
QTest::newRow("unresolvedArrayBinding")
<< QStringLiteral("unresolvedArrayBinding.qml")
@@ -1044,6 +1119,56 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
"in nested components."), 0, 0, QtInfoMsg } },
Result::AutoFixable
};
+ QTest::newRow("IsNotAnEntryOfEnum")
+ << QStringLiteral("IsNotAnEntryOfEnum.qml")
+ << Result{ {
+ Message {
+ QStringLiteral("Member \"Mode\" not found on type \"Item\""), 12,
+ 29, QtWarningMsg },
+ Message{
+ QStringLiteral("\"Hour\" is not an entry of enum \"Mode\"."), 13,
+ 62, QtInfoMsg }
+ },
+ {},
+ { Message{ QStringLiteral("Hours") } }
+ };
+
+ QTest::newRow("StoreNameMethod")
+ << QStringLiteral("storeNameMethod.qml")
+ << Result { { Message { QStringLiteral("Cannot assign to method foo") } } };
+
+ QTest::newRow("CoerceToVoid")
+ << QStringLiteral("coercetovoid.qml")
+ << Result { { Message {
+ QStringLiteral("Function without return type annotation returns double")
+ } } };
+
+ QTest::newRow("lowerCaseQualifiedImport")
+ << QStringLiteral("lowerCaseQualifiedImport.qml")
+ << Result{ {
+ Message{ u"Import qualifier 'test' must start with a capital letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.Rectangle' must start with an upper case letter."_s },
+ } };
+ QTest::newRow("lowerCaseQualifiedImport2")
+ << QStringLiteral("lowerCaseQualifiedImport2.qml")
+ << Result{ {
+ Message{ u"Import qualifier 'test' must start with a capital letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.Item' must start with an upper case letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.Rectangle' must start with an upper case letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.color' must start with an upper case letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.Grid' must start with an upper case letter."_s },
+ } };
+ QTest::newRow("notQmlRootMethods")
+ << QStringLiteral("notQmlRootMethods.qml")
+ << Result{ {
+ Message{ u"Member \"deleteLater\" not found on type \"QtObject\""_s },
+ Message{ u"Member \"destroyed\" not found on type \"QtObject\""_s },
+ } };
}
void TestQmllint::dirtyQmlCode()
@@ -1167,6 +1292,7 @@ void TestQmllint::cleanQmlCode_data()
QTest::newRow("QVariant") << QStringLiteral("qvariant.qml");
QTest::newRow("Accessible") << QStringLiteral("accessible.qml");
QTest::newRow("qjsroot") << QStringLiteral("qjsroot.qml");
+ QTest::newRow("qmlRootMethods") << QStringLiteral("qmlRootMethods.qml");
QTest::newRow("InlineComponent") << QStringLiteral("inlineComponent.qml");
QTest::newRow("InlineComponentWithComponents") << QStringLiteral("inlineComponentWithComponents.qml");
QTest::newRow("InlineComponentsChained") << QStringLiteral("inlineComponentsChained.qml");
@@ -1216,6 +1342,21 @@ void TestQmllint::cleanQmlCode_data()
QTest::newRow("propertyWithOn") << QStringLiteral("switcher.qml");
QTest::newRow("constructorProperty") << QStringLiteral("constructorProperty.qml");
QTest::newRow("onlyMajorVersion") << QStringLiteral("onlyMajorVersion.qml");
+ QTest::newRow("attachedImportUse") << QStringLiteral("attachedImportUse.qml");
+ QTest::newRow("VariantMapGetPropertyLookup") << QStringLiteral("variantMapLookup.qml");
+ QTest::newRow("StringToDateTime") << QStringLiteral("stringToDateTime.qml");
+ QTest::newRow("ScriptInTemplate") << QStringLiteral("scriptInTemplate.qml");
+ QTest::newRow("AddressableValue") << QStringLiteral("addressableValue.qml");
+ QTest::newRow("WriteListProperty") << QStringLiteral("writeListProperty.qml");
+ QTest::newRow("dontConfuseMemberPrintWithGlobalPrint") << QStringLiteral("findMemberPrint.qml");
+ QTest::newRow("groupedAttachedLayout") << QStringLiteral("groupedAttachedLayout.qml");
+ QTest::newRow("QQmlScriptString") << QStringLiteral("scriptstring.qml");
+ QTest::newRow("QEventPoint") << QStringLiteral("qEventPoint.qml");
+ QTest::newRow("locale") << QStringLiteral("locale.qml");
+ QTest::newRow("constInvokable") << QStringLiteral("useConstInvokable.qml");
+ QTest::newRow("dontCheckJSTypes") << QStringLiteral("dontCheckJSTypes.qml");
+ QTest::newRow("jsonObjectIsRecognized") << QStringLiteral("jsonObjectIsRecognized.qml");
+ QTest::newRow("jsonArrayIsRecognized") << QStringLiteral("jsonArrayIsRecognized.qml");
}
void TestQmllint::cleanQmlCode()
@@ -1239,10 +1380,10 @@ void TestQmllint::compilerWarnings_data()
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("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;
@@ -1261,6 +1402,51 @@ void TestQmllint::compilerWarnings_data()
<< Result { { { QStringLiteral(
"Functions without type annotations won't be compiled") } } }
<< true;
+ QTest::newRow("generalizedGroupHint")
+ << QStringLiteral("generalizedGroupHint.qml")
+ << Result { { { QStringLiteral(
+ "Cannot resolve property type for binding on myColor. "
+ "You may want use ID-based grouped properties here.") } } }
+ << true;
+ QTest::newRow("invalidIdLookup")
+ << QStringLiteral("invalidIdLookup.qml")
+ << Result { { {
+ QStringLiteral("Cannot retrieve a non-object type by ID: stateMachine")
+ } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-component")
+ << QStringLiteral("returnTypeAnnotation_component.qml")
+ << Result{ { { "Could not compile function comp: function without return type "
+ "annotation returns (component in" },
+ { "returnTypeAnnotation_component.qml)::c with type Comp. "
+ "This may prevent proper compilation to Cpp." } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-enum")
+ << QStringLiteral("returnTypeAnnotation_enum.qml")
+ << Result{ { { "Could not compile function enumeration: function without return type "
+ "annotation returns QQuickText::HAlignment::AlignRight. "
+ "This may prevent proper compilation to Cpp." } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-method")
+ << QStringLiteral("returnTypeAnnotation_method.qml")
+ << Result{ { { "Could not compile function method: function without return type "
+ "annotation returns (component in " }, // Don't check the build folder path
+ { "returnTypeAnnotation_method.qml)::f(...). This may "
+ "prevent proper compilation to Cpp." } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-property")
+ << QStringLiteral("returnTypeAnnotation_property.qml")
+ << Result{ { { "Could not compile function prop: function without return type "
+ "annotation returns (component in " }, // Don't check the build folder path
+ { "returnTypeAnnotation_property.qml)::i with type int. This may prevent "
+ "proper compilation to Cpp." } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-type")
+ << QStringLiteral("returnTypeAnnotation_type.qml")
+ << Result{ { { "Could not compile function type: function without return type "
+ "annotation returns double. This may prevent proper compilation to "
+ "Cpp." } } }
+ << true;
}
void TestQmllint::compilerWarnings()
@@ -1273,11 +1459,15 @@ void TestQmllint::compilerWarnings()
auto categories = QQmlJSLogger::defaultCategories();
- auto category = std::find(categories.begin(), categories.end(), qmlCompiler);
+ auto category = std::find_if(categories.begin(), categories.end(), [](const QQmlJS::LoggerCategory& category) {
+ return category.id() == qmlCompiler;
+ });
Q_ASSERT(category != categories.end());
- if (enableCompilerWarnings)
- category->setLevel(u"warning"_s);
+ if (enableCompilerWarnings) {
+ category->setLevel(QtWarningMsg);
+ category->setIgnored(false);
+ }
runTest(filename, result, {}, {}, {}, UseDefaultImports, &categories);
}
@@ -1285,7 +1475,7 @@ void TestQmllint::compilerWarnings()
QString TestQmllint::runQmllint(const QString &fileToLint,
std::function<void(QProcess &)> handleResult,
const QStringList &extraArgs, bool ignoreSettings,
- bool addImportDirs, bool absolutePath)
+ bool addImportDirs, bool absolutePath, const Environment &env)
{
auto qmlImportDir = QLibraryInfo::path(QLibraryInfo::QmlImportsPath);
QStringList args;
@@ -1311,6 +1501,11 @@ QString TestQmllint::runQmllint(const QString &fileToLint,
QString errors;
auto verify = [&](bool isSilent) {
QProcess process;
+ QProcessEnvironment processEnv = QProcessEnvironment::systemEnvironment();
+ for (const auto &entry : env)
+ processEnv.insert(entry.first, entry.second);
+
+ process.setProcessEnvironment(processEnv);
process.setWorkingDirectory(QFileInfo(absoluteFilePath).absolutePath());
process.start(m_qmllintPath, args);
handleResult(process);
@@ -1353,7 +1548,7 @@ QString TestQmllint::runQmllint(const QString &fileToLint,
QString TestQmllint::runQmllint(const QString &fileToLint, bool shouldSucceed,
const QStringList &extraArgs, bool ignoreSettings,
- bool addImportDirs, bool absolutePath)
+ bool addImportDirs, bool absolutePath, const Environment &env)
{
return runQmllint(
fileToLint,
@@ -1366,13 +1561,13 @@ QString TestQmllint::runQmllint(const QString &fileToLint, bool shouldSucceed,
else
QVERIFY(process.exitCode() != 0);
},
- extraArgs, ignoreSettings, addImportDirs, absolutePath);
+ extraArgs, ignoreSettings, addImportDirs, absolutePath, env);
}
void TestQmllint::callQmllint(const QString &fileToLint, bool shouldSucceed, QJsonArray *warnings,
QStringList importPaths, QStringList qmldirFiles,
QStringList resources, DefaultImportOption defaultImports,
- QList<QQmlJSLogger::Category> *categories, bool autoFixable,
+ QList<QQmlJS::LoggerCategory> *categories, bool autoFixable,
LintType type)
{
QJsonArray jsonOutput;
@@ -1382,18 +1577,22 @@ void TestQmllint::callQmllint(const QString &fileToLint, bool shouldSucceed, QJs
QQmlJSLinter::LintResult lintResult;
+ const QStringList resolvedImportPaths = defaultImports == UseDefaultImports
+ ? m_defaultImportPaths + importPaths
+ : importPaths;
if (type == LintFile) {
+ const QList<QQmlJS::LoggerCategory> resolvedCategories =
+ categories != nullptr ? *categories : QQmlJSLogger::defaultCategories();
lintResult = m_linter.lintFile(
- lintedFile, nullptr, true, &jsonOutput,
- defaultImports == UseDefaultImports ? m_defaultImportPaths + importPaths
- : importPaths,
- qmldirFiles, resources,
- categories != nullptr ? *categories : QQmlJSLogger::defaultCategories());
+ lintedFile, nullptr, true, &jsonOutput, resolvedImportPaths, qmldirFiles,
+ resources, resolvedCategories);
} else {
- lintResult = m_linter.lintModule(fileToLint, true, &jsonOutput);
+ lintResult =
+ m_linter.lintModule(fileToLint, true, &jsonOutput, resolvedImportPaths, resources);
}
bool success = lintResult == QQmlJSLinter::LintSuccess;
+ QEXPECT_FAIL("qtquickdialog", "Will fail until QTBUG-104091 is implemented", Abort);
QVERIFY2(success == shouldSucceed, QJsonDocument(jsonOutput).toJson());
if (warnings) {
@@ -1425,7 +1624,7 @@ void TestQmllint::callQmllint(const QString &fileToLint, bool shouldSucceed, QJs
if (QFileInfo(fixedPath).exists()) {
QFile fixedFile(fixedPath);
- fixedFile.open(QFile::ReadOnly);
+ QVERIFY(fixedFile.open(QFile::ReadOnly));
QString fixedFileContents = QString::fromUtf8(fixedFile.readAll());
#ifdef Q_OS_WIN
fixedCode = fixedCode.replace(u"\r\n"_s, u"\n"_s);
@@ -1447,7 +1646,7 @@ void TestQmllint::callQmllint(const QString &fileToLint, bool shouldSucceed, QJs
void TestQmllint::runTest(const QString &testFile, const Result &result, QStringList importDirs,
QStringList qmltypesFiles, QStringList resources,
DefaultImportOption defaultImports,
- QList<QQmlJSLogger::Category> *categories)
+ QList<QQmlJS::LoggerCategory> *categories)
{
QJsonArray warnings;
callQmllint(testFile, result.flags.testFlag(Result::Flag::ExitsNormally), &warnings, importDirs,
@@ -1604,17 +1803,17 @@ void TestQmllint::requiredProperty()
void TestQmllint::settingsFile()
{
- QVERIFY(runQmllint("settings/unqualifiedSilent/unqualified.qml", true, QStringList(), false)
+ QVERIFY(runQmllint("settings/unqualifiedSilent/unqualified.qml", true, warningsShouldFailArgs(), false)
.isEmpty());
- QVERIFY(runQmllint("settings/unusedImportWarning/unused.qml", false, QStringList(), false)
+ QVERIFY(runQmllint("settings/unusedImportWarning/unused.qml", false, warningsShouldFailArgs(), false)
.contains(QStringLiteral("Warning: %1:2:1: Unused import")
.arg(testFile("settings/unusedImportWarning/unused.qml"))));
- QVERIFY(runQmllint("settings/bare/bare.qml", false, {}, false, false)
+ QVERIFY(runQmllint("settings/bare/bare.qml", false, warningsShouldFailArgs(), false, false)
.contains(QStringLiteral("Failed to find the following builtins: "
- "builtins.qmltypes, jsroot.qmltypes")));
- QVERIFY(runQmllint("settings/qmltypes/qmltypes.qml", false, QStringList(), false)
+ "jsroot.qmltypes, builtins.qmltypes")));
+ QVERIFY(runQmllint("settings/qmltypes/qmltypes.qml", false, warningsShouldFailArgs(), false)
.contains(QStringLiteral("not a qmldir file. Assuming qmltypes.")));
- QVERIFY(runQmllint("settings/qmlimports/qmlimports.qml", true, QStringList(), false).isEmpty());
+ QVERIFY(runQmllint("settings/qmlimports/qmlimports.qml", true, warningsShouldFailArgs(), false).isEmpty());
}
void TestQmllint::additionalImplicitImport()
@@ -1623,17 +1822,56 @@ void TestQmllint::additionalImplicitImport()
const auto guard = qScopeGuard([this]() {m_linter.clearCache(); });
runTest("additionalImplicitImport.qml", Result::clean(), {}, {},
{ testFile("implicitImportResource.qrc") });
+}
+
+void TestQmllint::qrcUrlImport()
+{
+ const auto guard = qScopeGuard([this]() { m_linter.clearCache(); });
+ QJsonArray warnings;
+ callQmllint(testFile("untitled/main.qml"), true, &warnings, {}, {},
+ { testFile("untitled/qrcUrlImport.qrc") });
+ checkResult(warnings, Result::clean());
}
-void TestQmllint::attachedPropertyReuse()
+void TestQmllint::incorrectImportFromHost_data()
{
+ QTest::addColumn<QString>("filename");
+ QTest::addColumn<Result>("result");
+
+ QTest::newRow("NonexistentFile")
+ << QStringLiteral("importNonexistentFile.qml")
+ << Result{ { Message{
+ QStringLiteral("File or directory you are trying to import does not exist"),
+ 1, 1 } } };
+#ifndef Q_OS_WIN
+ // there is no /dev/null device on Win
+ QTest::newRow("NullDevice")
+ << QStringLiteral("importNullDevice.qml")
+ << Result{ { Message{ QStringLiteral("is neither a file nor a directory. Are sure the "
+ "import path is correct?"),
+ 1, 1 } } };
+#endif
+}
+
+void TestQmllint::incorrectImportFromHost()
+{
+ QFETCH(QString, filename);
+ QFETCH(Result, result);
+
+ runTest(filename, result);
+}
+void TestQmllint::attachedPropertyReuse()
+{
auto categories = QQmlJSLogger::defaultCategories();
- auto category = std::find(categories.begin(), categories.end(), qmlAttachedPropertyReuse);
+ auto category = std::find_if(categories.begin(), categories.end(), [](const QQmlJS::LoggerCategory& category) {
+ return category.id() == qmlAttachedPropertyReuse;
+ });
Q_ASSERT(category != categories.end());
- category->setLevel(u"warning"_s);
+ category->setLevel(QtWarningMsg);
+ category->setIgnored(false);
runTest("attachedPropNotReused.qml",
Result { { Message { QStringLiteral("Using attached type QQuickKeyNavigationAttached "
"already initialized in a parent "
@@ -1641,6 +1879,24 @@ void TestQmllint::attachedPropertyReuse()
{}, {}, {}, UseDefaultImports, &categories);
runTest("attachedPropEnum.qml", Result::clean(), {}, {}, {}, UseDefaultImports, &categories);
+ runTest("MyStyle/ToolBar.qml", Result {
+ {
+ Message {
+ "Using attached type MyStyle already initialized in a parent scope"_L1,
+ 10,
+ 16
+ }
+ },
+ {},
+ {
+ Message {
+ "Reference it by id instead"_L1,
+ 10,
+ 16
+ }
+ },
+ Result::AutoFixable
+ });
}
void TestQmllint::missingBuiltinsNoCrash()
@@ -1662,13 +1918,13 @@ void TestQmllint::missingBuiltinsNoCrash()
checkResult(warnings,
Result { { Message { QStringLiteral("Failed to find the following builtins: "
- "builtins.qmltypes, jsroot.qmltypes") } } });
+ "jsroot.qmltypes, builtins.qmltypes") } } });
}
void TestQmllint::absolutePath()
{
- QString absPathOutput = runQmllint("memberNotFound.qml", false, {}, true, true, true);
- QString relPathOutput = runQmllint("memberNotFound.qml", false, {}, true, true, false);
+ QString absPathOutput = runQmllint("memberNotFound.qml", false, warningsShouldFailArgs(), true, true, true);
+ QString relPathOutput = runQmllint("memberNotFound.qml", false, warningsShouldFailArgs(), true, true, false);
const QString absolutePath = QFileInfo(testFile("memberNotFound.qml")).absoluteFilePath();
QVERIFY(absPathOutput.contains(absolutePath));
@@ -1683,10 +1939,14 @@ void TestQmllint::importMultipartUri()
void TestQmllint::lintModule_data()
{
QTest::addColumn<QString>("module");
+ QTest::addColumn<QStringList>("importPaths");
+ QTest::addColumn<QStringList>("resources");
QTest::addColumn<Result>("result");
QTest::addRow("Things")
<< u"Things"_s
+ << QStringList()
+ << QStringList()
<< Result {
{ Message {
u"Type \"QPalette\" not found. Used in SomethingEntirelyStrange.palette"_s,
@@ -1696,16 +1956,30 @@ void TestQmllint::lintModule_data()
};
QTest::addRow("missingQmltypes")
<< u"Fake5Compat.GraphicalEffects.private"_s
+ << QStringList()
+ << QStringList()
<< Result { { Message { u"QML types file does not exist"_s } } };
+
+ QTest::addRow("moduleWithQrc")
+ << u"moduleWithQrc"_s
+ << QStringList({ testFile("hidden") })
+ << QStringList({
+ testFile("hidden/qmake_moduleWithQrc.qrc"),
+ testFile("hidden/moduleWithQrc_raw_qml_0.qrc")
+ })
+ << Result::clean();
}
void TestQmllint::lintModule()
{
QFETCH(QString, module);
+ QFETCH(QStringList, importPaths);
+ QFETCH(QStringList, resources);
QFETCH(Result, result);
QJsonArray warnings;
- callQmllint(module, false, &warnings, {}, {}, {}, {}, nullptr, false, LintModule);
+ callQmllint(module, result.flags & Result::ExitsNormally, &warnings, importPaths, {}, resources,
+ UseDefaultImports, nullptr, false, LintModule);
checkResult(warnings, result);
}
@@ -1739,6 +2013,25 @@ void TestQmllint::testLineEndings()
}
}
+void TestQmllint::valueTypesFromString()
+{
+ runTest("valueTypesFromString.qml",
+ Result{ {
+ Message{
+ u"Binding is not supported: Type QSizeF should be constructed using QML_STRUCTURED_VALUE's construction mechanism, instead of a string."_s },
+ Message{
+ u"Binding is not supported: Type QRectF should be constructed using QML_STRUCTURED_VALUE's construction mechanism, instead of a string."_s },
+ Message{
+ u"Binding is not supported: Type QPointF should be constructed using QML_STRUCTURED_VALUE's construction mechanism, instead of a string."_s },
+ },
+ { /*bad messages */ },
+ {
+ Message{ u"({ width: 30, height: 50 })"_s },
+ Message{ u"({ x: 10, y: 20, width: 30, height: 50 })"_s },
+ Message{ u"({ x: 30, y: 50 })"_s },
+ } });
+}
+
#if QT_CONFIG(library)
void TestQmllint::testPlugin()
{
@@ -1780,6 +2073,9 @@ void TestQmllint::testPlugin()
Result { { Message { u"QtQuick.Controls and NO QtQuick present"_s } } });
// Verify that none of the passes do anything when they're not supposed to
runTest("nothing_pluginTest.qml", Result::clean());
+
+ QVERIFY(runQmllint("settings/plugin/elemenpass_pluginSettingTest.qml", true, QStringList(), false)
+ .isEmpty());
}
// TODO: Eventually tests for (real) plugins need to be moved into a separate file
@@ -1835,7 +2131,7 @@ void TestQmllint::quickPlugin()
Message { u"SplitView attached property only works with Items"_s },
Message { u"ScrollIndicator must be attached to a Flickable"_s },
Message { u"ScrollBar must be attached to a Flickable or ScrollView"_s },
- Message { u"Accessible must be attached to an Item"_s },
+ Message { u"Accessible must be attached to an Item or an Action"_s },
Message { u"EnterKey attached property only works with Items"_s },
Message {
u"LayoutDirection attached property only works with Items and Windows"_s },
@@ -1885,8 +2181,108 @@ void TestQmllint::quickPlugin()
runTest("pluginQuick_attachedClean.qml", Result::clean());
runTest("pluginQuick_attachedIgnore.qml", Result::clean());
runTest("pluginQuick_noCrashOnUneresolved.qml", Result {}); // we don't care about the specific warnings
+
+ runTest("pluginQuick_propertyChangesParsed.qml",
+ Result { {
+ Message {
+ u"Property \"myColor\" is custom-parsed in PropertyChanges. "
+ "You should phrase this binding as \"foo.myColor: Qt.rgba(0.5, ...\""_s,
+ 12, 30
+ },
+ Message {
+ u"You should remove any bindings on the \"target\" property and avoid "
+ "custom-parsed bindings in PropertyChanges."_s,
+ 11, 29
+ },
+ Message {
+ u"Unknown property \"notThere\" in PropertyChanges."_s,
+ 13, 31
+ }
+ } });
+ runTest("pluginQuick_propertyChangesInvalidTarget.qml", Result {}); // we don't care about the specific warnings
+}
+
+void TestQmllint::environment_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<bool>("shouldSucceed");
+ QTest::addColumn<QStringList>("extraArgs");
+ QTest::addColumn<Environment>("env");
+ QTest::addColumn<QString>("expectedWarning");
+
+ const QString fileThatNeedsImportPath = testFile(u"NeedImportPath.qml"_s);
+ const QString importPath = testFile(u"ImportPath"_s);
+ const QString invalidImportPath = testFile(u"ImportPathThatDoesNotExist"_s);
+ const QString noWarningExpected;
+
+ QTest::addRow("missing-import-dir")
+ << fileThatNeedsImportPath << false << warningsShouldFailArgs()
+ << Environment{ { u"QML_IMPORT_PATH"_s, importPath } } << noWarningExpected;
+
+ QTest::addRow("import-dir-via-arg")
+ << fileThatNeedsImportPath << true << QStringList{ u"-I"_s, importPath }
+ << Environment{ { u"QML_IMPORT_PATH"_s, invalidImportPath } } << noWarningExpected;
+
+ QTest::addRow("import-dir-via-env")
+ << fileThatNeedsImportPath << true << QStringList{ u"-E"_s }
+ << Environment{ { u"QML_IMPORT_PATH"_s, importPath } }
+ << u"Using import directories passed from environment variable \"QML_IMPORT_PATH\": \"%1\"."_s
+ .arg(importPath);
+
+ QTest::addRow("import-dir-via-env2")
+ << fileThatNeedsImportPath << true << QStringList{ u"-E"_s }
+ << Environment{ { u"QML2_IMPORT_PATH"_s, importPath } }
+ << u"Using import directories passed from the deprecated environment variable \"QML2_IMPORT_PATH\": \"%1\"."_s
+ .arg(importPath);
}
+
+void TestQmllint::environment()
+{
+ QFETCH(QString, file);
+ QFETCH(bool, shouldSucceed);
+ QFETCH(QStringList, extraArgs);
+ QFETCH(Environment, env);
+ QFETCH(QString, expectedWarning);
+
+ const QString output = runQmllint(file, shouldSucceed, extraArgs, false, true, false, env);
+ if (!expectedWarning.isEmpty()) {
+ QVERIFY(output.contains(expectedWarning));
+ }
+}
+
+void TestQmllint::maxWarnings()
+{
+ // warnings are not fatal by default
+ runQmllint(testFile("badScript.qml"), true);
+ // or when max-warnings is set to -1
+ runQmllint(testFile("badScript.qml"), true, {"-W", "-1"});
+ // 1 warning => should fail
+ runQmllint(testFile("badScript.qml"), false, {"--max-warnings", "0"});
+ // only 1 warning => should exit normally
+ runQmllint(testFile("badScript.qml"), true, {"--max-warnings", "1"});
+}
+
#endif
-QTEST_MAIN(TestQmllint)
+void TestQmllint::ignoreSettingsNotCommandLineOptions()
+{
+ const QString importPath = testFile(u"ImportPath"_s);
+ // makes sure that ignore settings only ignores settings and not command line options like
+ // "-I".
+ const QString output = runQmllint(testFile(u"NeedImportPath.qml"_s), true,
+ QStringList{ u"-I"_s, importPath }, true);
+ // should not complain about not finding the module that is in importPath
+ QCOMPARE(output, QString());
+}
+
+void TestQmllint::backslashedQmldirPath()
+{
+ const QString qmldirPath
+ = testFile(u"ImportPath/ModuleInImportPath/qmldir"_s).replace('/', QDir::separator());
+ const QString output = runQmllint(
+ testFile(u"something.qml"_s), true, QStringList{ u"-i"_s, qmldirPath });
+ QVERIFY(output.isEmpty());
+}
+
+QTEST_GUILESS_MAIN(TestQmllint)
#include "tst_qmllint.moc"
diff --git a/tests/auto/qml/qmlplugindump/CMakeLists.txt b/tests/auto/qml/qmlplugindump/CMakeLists.txt
index 9153660ef0..053268bcfb 100644
--- a/tests/auto/qml/qmlplugindump/CMakeLists.txt
+++ b/tests/auto/qml/qmlplugindump/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmlplugindump Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlplugindump LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qmlplugindump
SOURCES
tst_qmlplugindump.cpp
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.cpp b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.cpp
index 171a185ad7..793191695d 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.cpp
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "dummy.h"
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.h b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.h
index 0fb354d6c4..b72814df82 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DUMMY_H
#define DUMMY_H
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.cpp b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.cpp
index eec547cd29..1409876ec6 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.cpp
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "dummy_plugin.h"
#include "dummy.h"
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.h b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.h
index 2c3f25ae61..45437e0500 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DUMMY_PLUGIN_H
#define DUMMY_PLUGIN_H
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.cpp b/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.cpp
index e84355eb11..4c8da8aeab 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.cpp
+++ b/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "plugin.h"
#include "types.h"
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.h b/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.h
index f16177351d..02c9d42022 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.h
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef PLUGIN_H
#define PLUGIN_H
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/types.h b/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/types.h
index 5fdc5fa1e4..7a1b73ac90 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/types.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/types.h
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPES_H
#define TYPES_H
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.cpp b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.cpp
index 04fcfc5edd..9ba1365d40 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.cpp
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "imports.h"
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.h b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.h
index 386cce9f4d..e88deda2f9 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef IMPORTS_H
#define IMPORTS_H
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.cpp b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.cpp
index b71719fb6f..c215917c7d 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.cpp
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "imports_plugin.h"
#include "imports.h"
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.h b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.h
index 17855d5a22..1353bbd24a 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef IMPORTS_PLUGIN_H
#define IMPORTS_PLUGIN_H
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.cpp b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.cpp
index 117b6db82f..6295ec2201 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.cpp
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "versions.h"
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.h b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.h
index 991823aaf3..b5afc16c2a 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef VERSIONS_H
#define VERSIONS_H
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.cpp b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.cpp
index 6a554c596d..9c1a2d4a4e 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.cpp
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "versions_plugin.h"
#include "versions.h"
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.h b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.h
index 9bc70ca473..aba5f1fac7 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef VERSIONS_PLUGIN_H
#define VERSIONS_PLUGIN_H
diff --git a/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp b/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
index 50af75380d..2e7b704413 100644
--- a/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
+++ b/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QLibraryInfo>
@@ -152,10 +152,10 @@ void tst_qmlplugindump::plugin()
QVERIFY2(dumper.waitForStarted(), qPrintable(dumper.errorString()));
QVERIFY2(dumper.waitForFinished(), qPrintable(dumper.errorString()));
- const QString &result = dumper.readAllStandardOutput();
+ const QByteArray result = dumper.readAllStandardOutput();
QFile expectedFile(expectedPath);
QVERIFY2(expectedFile.open(QIODevice::ReadOnly), qPrintable(expectedFile.errorString()));
- const QString expected = expectedFile.readAll();
+ const QByteArray expected = expectedFile.readAll();
QCOMPARE(result, expected);
}
diff --git a/tests/auto/qml/qmlsplitlib/CMakeLists.txt b/tests/auto/qml/qmlsplitlib/CMakeLists.txt
index 523ab5cbfd..7c77d5fbae 100644
--- a/tests/auto/qml/qmlsplitlib/CMakeLists.txt
+++ b/tests/auto/qml/qmlsplitlib/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlsplitlib LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
include(GenerateExportHeader)
qt_add_library(tst_qmlsplitlib_library
@@ -13,6 +19,17 @@ generate_export_header(tst_qmlsplitlib_library)
target_link_libraries(tst_qmlsplitlib_library Qt::Core Qt::QmlIntegration)
+qt_add_library(tst-qmlsplitlib-library-2
+ lib2.h
+ lib2.cpp
+)
+qt_autogen_tools_initial_setup(tst-qmlsplitlib-library-2)
+target_include_directories(tst-qmlsplitlib-library-2 PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # find autogenerated header
+generate_export_header(tst-qmlsplitlib-library-2)
+
+target_link_libraries(tst-qmlsplitlib-library-2 Qt::Core Qt::QmlIntegration)
+
+
qt_internal_add_test(tst_qmlsplitlib
SOURCES
tst_qmlsplitlib.cpp
@@ -23,12 +40,15 @@ qt_internal_add_test(tst_qmlsplitlib
qt_autogen_tools_initial_setup(tst_qmlsplitlib)
qt6_generate_foreign_qml_types(tst_qmlsplitlib_library tst_qmlsplitlib)
+qt6_generate_foreign_qml_types(tst-qmlsplitlib-library-2 tst_qmlsplitlib)
+
+qt_policy(SET QTP0001 NEW)
qt6_add_qml_module(tst_qmlsplitlib
URI "SplitLib"
- AUTO_RESOURCE_PREFIX
QML_FILES
main.qml
+ main2.qml
)
-target_link_libraries(tst_qmlsplitlib PRIVATE tst_qmlsplitlib_library)
+target_link_libraries(tst_qmlsplitlib PRIVATE tst_qmlsplitlib_library tst-qmlsplitlib-library-2)
diff --git a/tests/auto/qml/qmlsplitlib/lib.h b/tests/auto/qml/qmlsplitlib/lib.h
index 02fc88894d..b6c394a3b6 100644
--- a/tests/auto/qml/qmlsplitlib/lib.h
+++ b/tests/auto/qml/qmlsplitlib/lib.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef SPLITLIB_LIB_H
#define SPLITLIB_LIB_H
diff --git a/tests/auto/qml/qmlsplitlib/lib2.cpp b/tests/auto/qml/qmlsplitlib/lib2.cpp
new file mode 100644
index 0000000000..d4489f5c77
--- /dev/null
+++ b/tests/auto/qml/qmlsplitlib/lib2.cpp
@@ -0,0 +1,5 @@
+#include "lib2.h"
+
+bool SplitLib2::transmogrify() { return true; }
+
+#include "moc_lib2.cpp"
diff --git a/tests/auto/qml/qmlsplitlib/lib2.h b/tests/auto/qml/qmlsplitlib/lib2.h
new file mode 100644
index 0000000000..6d6aaddda5
--- /dev/null
+++ b/tests/auto/qml/qmlsplitlib/lib2.h
@@ -0,0 +1,30 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef SPLITLIB_LIB2_H
+#define SPLITLIB_LIB2_H
+#include "tst-qmlsplitlib-library-2_export.h"
+
+#include <QtQmlIntegration/qqmlintegration.h>
+#include <QtCore/qglobal.h>
+#include <QObject>
+
+class TST_QMLSPLITLIB_LIBRARY_2_EXPORT SplitLib2 : public QObject
+{
+public:
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_INVOKABLE bool transmogrify();
+};
+
+
+class TST_QMLSPLITLIB_LIBRARY_2_EXPORT Foo2 : public QObject
+{
+public:
+ Q_OBJECT
+ QML_NAMED_ELEMENT(Bar2)
+ QML_SINGLETON
+};
+
+#endif
diff --git a/tests/auto/qml/qmlsplitlib/main.qml b/tests/auto/qml/qmlsplitlib/main.qml
index 2309a2e8c3..47be48acc4 100644
--- a/tests/auto/qml/qmlsplitlib/main.qml
+++ b/tests/auto/qml/qmlsplitlib/main.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import SplitLib
diff --git a/tests/auto/qml/qmlsplitlib/main2.qml b/tests/auto/qml/qmlsplitlib/main2.qml
new file mode 100644
index 0000000000..c5081c6627
--- /dev/null
+++ b/tests/auto/qml/qmlsplitlib/main2.qml
@@ -0,0 +1,8 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import SplitLib
+
+SplitLib2 {
+ property string s: Bar2.objectName
+}
diff --git a/tests/auto/qml/qmlsplitlib/manual_imports.cpp b/tests/auto/qml/qmlsplitlib/manual_imports.cpp
index f1b30f8352..dd1c8dbe89 100644
--- a/tests/auto/qml/qmlsplitlib/manual_imports.cpp
+++ b/tests/auto/qml/qmlsplitlib/manual_imports.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlextensionplugin.h>
diff --git a/tests/auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp b/tests/auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp
index 893ed77ff7..d04a1c6845 100644
--- a/tests/auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp
+++ b/tests/auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp
@@ -1,17 +1,19 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QQmlEngine>
#include <QQmlComponent>
#include <QObject>
#include <qtest.h>
#include "lib.h"
+#include "lib2.h"
class tst_splitlib : public QObject
{
Q_OBJECT
private slots:
void verifyComponent();
+ void verifyComponent2();
};
void tst_splitlib::verifyComponent()
@@ -25,5 +27,16 @@ void tst_splitlib::verifyComponent()
QVERIFY(lib);
}
+void tst_splitlib::verifyComponent2()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QStringLiteral("qrc:/qt/qml/SplitLib/main2.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer o(c.create());
+ QVERIFY(!o.isNull());
+ auto lib = qobject_cast<SplitLib2 *>(o.get());
+ QVERIFY(lib);
+}
+
QTEST_MAIN(tst_splitlib)
#include "tst_qmlsplitlib.moc"
diff --git a/tests/auto/qml/qmltc/BLACKLIST b/tests/auto/qml/qmltc/BLACKLIST
deleted file mode 100644
index 004fbeb8d9..0000000000
--- a/tests/auto/qml/qmltc/BLACKLIST
+++ /dev/null
@@ -1,5 +0,0 @@
-[listView]
-qnx ci
-# QTBUG-101342
-[listView]
-android
diff --git a/tests/auto/qml/qmltc/CMakeLists.txt b/tests/auto/qml/qmltc/CMakeLists.txt
index 4b86a6c018..1e6c6b9e30 100644
--- a/tests/auto/qml/qmltc/CMakeLists.txt
+++ b/tests/auto/qml/qmltc/CMakeLists.txt
@@ -1,8 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmltc LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
add_subdirectory(QmltcTests)
add_subdirectory(NamespaceTest/Subfolder)
+add_subdirectory(QmltcExportedTests)
+add_subdirectory(QmltcExportedNoFileNameTest)
set(test_sources
nameconflict.h nameconflict.cpp
@@ -18,6 +26,11 @@ set(qmltc_module_libs
# automatic type registration that comes from the plugin)
qmltc_test_moduleplugin
qmltc_namespace_test_module
+ qmltc_namespace_test_moduleplugin
+ qmltc_exported_tests_module
+ qmltc_exported_tests_moduleplugin
+ qmltc_exported_no_file_name_test_module
+ qmltc_exported_no_file_name_test_moduleplugin
)
qt_internal_add_test(tst_qmltc_diskcache
SOURCES ${test_sources}
@@ -25,6 +38,7 @@ qt_internal_add_test(tst_qmltc_diskcache
)
target_compile_definitions(tst_qmltc_diskcache PRIVATE
QMLTC_TESTS_DISABLE_CACHE=0
+ QT_NO_URL_CAST_FROM_STRING #QTBUG-113875
)
qt_internal_add_test(tst_qmltc_nodiskcache
@@ -33,6 +47,7 @@ qt_internal_add_test(tst_qmltc_nodiskcache
)
target_compile_definitions(tst_qmltc_nodiskcache PRIVATE
QMLTC_TESTS_DISABLE_CACHE=1
+ QT_NO_URL_CAST_FROM_STRING #QTBUG-113875
)
# Add qmltc documentation example to the tests. This is not beautiful but allows
diff --git a/tests/auto/qml/qmltc/NamespaceTest/Subfolder/CMakeLists.txt b/tests/auto/qml/qmltc/NamespaceTest/Subfolder/CMakeLists.txt
index f661cdea1e..daf1139a8f 100644
--- a/tests/auto/qml/qmltc/NamespaceTest/Subfolder/CMakeLists.txt
+++ b/tests/auto/qml/qmltc/NamespaceTest/Subfolder/CMakeLists.txt
@@ -24,9 +24,10 @@ qt_autogen_tools_initial_setup(qmltc_namespace_test_module)
target_link_libraries(qmltc_namespace_test_module PUBLIC ${common_libraries})
+qt_policy(SET QTP0001 NEW)
+
qt6_add_qml_module(qmltc_namespace_test_module
URI NamespaceTest.Subfolder
- AUTO_RESOURCE_PREFIX
SOURCES
${cpp_sources}
QML_FILES
diff --git a/tests/auto/qml/qmltc/NamespaceTest/Subfolder/Type.qml b/tests/auto/qml/qmltc/NamespaceTest/Subfolder/Type.qml
index 101e9f69a1..3576353b02 100644
--- a/tests/auto/qml/qmltc/NamespaceTest/Subfolder/Type.qml
+++ b/tests/auto/qml/qmltc/NamespaceTest/Subfolder/Type.qml
@@ -1,5 +1,5 @@
import QtQuick
Item {
- property string data
+ property string data: "Hello from namespace"
}
diff --git a/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/CMakeLists.txt b/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/CMakeLists.txt
new file mode 100644
index 0000000000..47f920129a
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/CMakeLists.txt
@@ -0,0 +1,28 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_add_library(qmltc_exported_no_file_name_test_module STATIC)
+qt_autogen_tools_initial_setup(qmltc_exported_no_file_name_test_module)
+
+set(common_libraries
+ Qt::QuickPrivate
+)
+
+target_link_libraries(qmltc_exported_no_file_name_test_module PUBLIC ${common_libraries})
+
+qt_policy(SET QTP0001 NEW)
+
+qt6_add_qml_module(qmltc_exported_no_file_name_test_module
+ URI QmltcExportedNoFileNameTest
+ QML_FILES
+ HelloExportedWorldNoFileName.qml
+ DEPENDENCIES
+ Qt::Quick
+ ENABLE_TYPE_COMPILER
+ QMLTC_EXPORT_DIRECTIVE "Q_DECL_EXPORT"
+ # explicitly omitting QMLTC_EXPORT_FILE_NAME
+)
+
+target_include_directories(qmltc_exported_no_file_name_test_module PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
+
+qt_autogen_tools_initial_setup(qmltc_exported_no_file_name_test_moduleplugin)
diff --git a/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/HelloExportedWorldNoFileName.qml b/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/HelloExportedWorldNoFileName.qml
new file mode 100644
index 0000000000..89986df5a6
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/HelloExportedWorldNoFileName.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property string myString: "Hello! I should be exported by qmltc"
+}
diff --git a/tests/auto/qml/qmltc/QmltcExportedTests/CMakeLists.txt b/tests/auto/qml/qmltc/QmltcExportedTests/CMakeLists.txt
new file mode 100644
index 0000000000..709297bed4
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcExportedTests/CMakeLists.txt
@@ -0,0 +1,31 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_add_library(qmltc_exported_tests_module STATIC)
+qt_autogen_tools_initial_setup(qmltc_exported_tests_module)
+
+include(GenerateExportHeader)
+generate_export_header(qmltc_exported_tests_module)
+
+set(common_libraries
+ Qt::QuickPrivate
+)
+
+target_link_libraries(qmltc_exported_tests_module PUBLIC ${common_libraries})
+
+qt_policy(SET QTP0001 NEW)
+
+qt6_add_qml_module(qmltc_exported_tests_module
+ URI QmltcExportedTests
+ QML_FILES
+ HelloExportedWorld.qml
+ DEPENDENCIES
+ Qt::Quick
+ ENABLE_TYPE_COMPILER
+ QMLTC_EXPORT_DIRECTIVE "QMLTC_EXPORTED_TESTS_MODULE_EXPORT"
+ QMLTC_EXPORT_FILE_NAME "qmltc_exported_tests_module_export.h"
+)
+
+target_include_directories(qmltc_exported_tests_module PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
+
+qt_autogen_tools_initial_setup(qmltc_exported_tests_moduleplugin)
diff --git a/tests/auto/qml/qmltc/QmltcExportedTests/HelloExportedWorld.qml b/tests/auto/qml/qmltc/QmltcExportedTests/HelloExportedWorld.qml
new file mode 100644
index 0000000000..5e6886bced
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcExportedTests/HelloExportedWorld.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property string myString: "Hello! I should be exported by qmltc"
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
index 870d21f61d..4c472ec4ab 100644
--- a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
+++ b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
@@ -22,6 +22,8 @@ set(cpp_sources
cpptypes/singletontype.h cpptypes/singletontype.cpp
cpptypes/typewithnamespace.h cpptypes/typewithnamespace.cpp
cpptypes/typewithsignal.h
+ cpptypes/custominitialization.h
+ cpptypes/typewithrequiredproperties.h
)
set(qml_sources
@@ -44,11 +46,16 @@ set(qml_sources
regexpBindings.qml
AliasBase.qml
aliasAssignments.qml
+ Connections.qml
qtbug103956/SubComponent.qml
qtbug103956/MainComponent.qml
qtbug103956/qtbug103956_main.qml
+ qtbug120700_main.qml
+
+ qtbug123476.qml
+
signalHandlers.qml
javaScriptFunctions.qml
changingBindings.qml
@@ -108,6 +115,9 @@ set(qml_sources
inlineComponentsFromDifferentFiles.qml
singletons.qml
mySignals.qml
+ stringToUrl.qml
+ myCheckBox.qml
+ signalConnections.qml
# support types:
DefaultPropertySingleChild.qml
@@ -125,6 +135,8 @@ set(qml_sources
NamespacedTypes.qml
badFile.qml
+
+ requiredProperties.qml
)
set(js_sources
@@ -135,10 +147,16 @@ set(common_libraries
Qt::Core
Qt::QmlPrivate
Qt::QuickPrivate
+ Qt::QuickTemplates2Private
Qt::TestPrivate
Qt::Gui # QColor, QMatrix4x4, ...
)
+if (QT_FEATURE_qml_table_model)
+ list(APPEND qml_sources QmlTableModel.qml)
+ list(APPEND common_libraries Qt::LabsQmlModelsPrivate)
+endif()
+
set_source_files_properties(NameConflict.qml PROPERTIES
QT_QMLTC_FILE_BASENAME ResolvedNameConflict)
@@ -166,10 +184,11 @@ qt_internal_add_resource(qmltc_test_module "qmake_immediate"
${qmake_immediate_resource_files}
)
+qt_policy(SET QTP0001 NEW)
+
qt6_add_qml_module(qmltc_test_module
VERSION 1.0
URI QmltcTests
- AUTO_RESOURCE_PREFIX
SOURCES
${cpp_sources}
QML_FILES
diff --git a/tests/auto/qml/qmltc/QmltcTests/Connections.qml b/tests/auto/qml/qmltc/QmltcTests/Connections.qml
new file mode 100644
index 0000000000..d7fc0d87c6
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/Connections.qml
@@ -0,0 +1,12 @@
+import QtQuick
+
+Rectangle {
+ property string hello
+
+ id: root
+
+ Connections {
+ target: root
+ function onHelloChanged(argument) {}
+ }
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/InlineComponentProvider.qml b/tests/auto/qml/qmltc/QmltcTests/InlineComponentProvider.qml
index 9dbe9d6fbe..d3c1cfe293 100644
--- a/tests/auto/qml/qmltc/QmltcTests/InlineComponentProvider.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/InlineComponentProvider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/QmlTableModel.qml b/tests/auto/qml/qmltc/QmltcTests/QmlTableModel.qml
new file mode 100644
index 0000000000..696c2b40bb
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/QmlTableModel.qml
@@ -0,0 +1,62 @@
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.12
+import QtQuick.Window 2.12
+import Qt.labs.qmlmodels 1.0
+
+TableView {
+ anchors.fill: parent
+ columnSpacing: 1
+ rowSpacing: 1
+ boundsBehavior: Flickable.StopAtBounds
+
+ model: TableModel {
+ property string testName: "MyTableModel"
+ TableModelColumn { display: "checked" }
+ TableModelColumn { display: "amount" }
+ TableModelColumn { display: "fruitType" }
+ TableModelColumn { display: "fruitName" }
+ TableModelColumn { display: "fruitPrice" }
+
+ // Each row is one type of fruit that can be ordered
+ rows: [
+ {
+ // Each property is one cell/column.
+ checked: false,
+ amount: 1,
+ fruitType: "Apple",
+ fruitName: "Granny Smith",
+ fruitPrice: 1.50
+ },
+ {
+ checked: true,
+ amount: 4,
+ fruitType: "Orange",
+ fruitName: "Navel",
+ fruitPrice: 2.50
+ },
+ {
+ checked: false,
+ amount: 1,
+ fruitType: "Banana",
+ fruitName: "Cavendish",
+ fruitPrice: 3.50
+ }
+ ]
+ }
+ delegate: TextInput {
+ text: model.display
+ padding: 12
+ selectByMouse: true
+
+ onAccepted: model.display = text
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#efefef"
+ z : -1
+ }
+ }
+}
+
diff --git a/tests/auto/qml/qmltc/QmltcTests/aliases.qml b/tests/auto/qml/qmltc/QmltcTests/aliases.qml
index 9f13f7b17a..41c34b4187 100644
--- a/tests/auto/qml/qmltc/QmltcTests/aliases.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/aliases.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/appendToQQmlListProperty.qml b/tests/auto/qml/qmltc/QmltcTests/appendToQQmlListProperty.qml
index 680e297edb..70636c0a2e 100644
--- a/tests/auto/qml/qmltc/QmltcTests/appendToQQmlListProperty.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/appendToQQmlListProperty.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QmltcTests
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/custominitialization.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/custominitialization.h
new file mode 100644
index 0000000000..7546f344d2
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/custominitialization.h
@@ -0,0 +1,64 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef CUSTOMINITIALIAZATION_H_
+#define CUSTOMINITIALIAZATION_H_
+
+#include <QtCore/qobject.h>
+#include <QtCore/qproperty.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQml/qqmllist.h>
+#include <QtQml/qqmlregistration.h>
+
+class ExtensionType : public QObject
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+ Q_PROPERTY(double propertyFromExtension READ getPropertyFromExtension WRITE
+ setPropertyFromExtension)
+ Q_PROPERTY(QQmlListProperty<QQuickItem> extensionObjectList READ getExtensionObjectList)
+
+ QProperty<double> m_propertyFromExtension{ 0 };
+ QList<QQuickItem *> m_extensionObjectList;
+
+public:
+ ExtensionType(QObject *parent = nullptr) : QObject(parent) { }
+
+ double getPropertyFromExtension() const { return m_propertyFromExtension; }
+ void setPropertyFromExtension(double v) { m_propertyFromExtension = v; }
+
+ QQmlListProperty<QQuickItem> getExtensionObjectList()
+ {
+ return QQmlListProperty<QQuickItem>(this, &m_extensionObjectList);
+ }
+};
+
+class TypeForCustomInitialization : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(QQmlListProperty<QQuickItem> cppObjectList READ getCppObjectList)
+ Q_PROPERTY(
+ double defaultedBindable BINDABLE bindableDefaultedBindable READ default WRITE default)
+
+ QML_EXTENDED(ExtensionType)
+
+ QList<QQuickItem *> m_cppObjectList;
+ QProperty<double> m_defaultedBindable;
+
+public:
+ TypeForCustomInitialization(QObject *parent = nullptr) : QObject(parent) { }
+
+ QQmlListProperty<QQuickItem> getCppObjectList()
+ {
+ return QQmlListProperty<QQuickItem>(this, &m_cppObjectList);
+ }
+
+ QBindable<double> bindableDefaultedBindable()
+ {
+ return QBindable<double>(&m_defaultedBindable);
+ }
+};
+
+#endif // CUSTOMINITIALIAZATION_H_
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.cpp b/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.cpp
index 422e0021f1..1487dbcf15 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.cpp
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "deferredpropertytypes.h"
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.h
index d9aa801c77..1701d6ee91 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DEFERREDPROPERTYTYPES_H
#define DEFERREDPROPERTYTYPES_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.cpp b/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.cpp
index 16f555c0b7..b6ed76eed4 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.cpp
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "extensiontypes.h"
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.h
index 667e2952ce..080d3b4380 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef EXTENSIONTYPES_H
#define EXTENSIONTYPES_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/private/testprivateproperty_p.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/private/testprivateproperty_p.h
index 31cb385cfd..3135f4e3d3 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/private/testprivateproperty_p.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/private/testprivateproperty_p.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// NB: fake private header for testing purposes
#ifndef TESTPRIVATEPROPERTY_P_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/singletontype.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/singletontype.h
index 293aece065..a2e1518fc3 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/singletontype.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/singletontype.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef SINGLETONTYPE_H
#define SINGLETONTYPE_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.cpp b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.cpp
index fd70c0a3f4..b44945fba0 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.cpp
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testattachedtype.h"
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.h
index b7cc6348aa..2e3ef97009 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTATTACHEDTYPE_H
#define TESTATTACHEDTYPE_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.cpp b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.cpp
index 410aae1528..45d6c3e322 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.cpp
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testgroupedtype.h"
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.h
index f895f19531..cef875545c 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTGROUPEDTYPE_H
#define TESTGROUPEDTYPE_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.cpp b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.cpp
index c1d101653c..f24728b597 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.cpp
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "private/testprivateproperty_p.h"
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.h
index 230c86affd..22863ba52a 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTPRIVATEPROPERTY_H
#define TESTPRIVATEPROPERTY_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithmanyproperties.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithmanyproperties.h
index 873c38771e..b0f1a17adc 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithmanyproperties.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithmanyproperties.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef PROPERTYALIASATTRIBUTES_H
#define PROPERTYALIASATTRIBUTES_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.cpp b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.cpp
index fbfaf447da..ae4aaa5092 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.cpp
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "typewithnamespace.h"
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.h
index 7b8bc7803a..173e8624ff 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPEWITHNAMESPACE_H
#define TYPEWITHNAMESPACE_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.cpp b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.cpp
index 80557209a5..eb0dae7465 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.cpp
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "typewithproperties.h"
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.h
index e06f9079f9..d7a0d03405 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPEWITHPROPERTIES_H
#define TYPEWITHPROPERTIES_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithrequiredproperties.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithrequiredproperties.h
new file mode 100644
index 0000000000..cc1ded9f74
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithrequiredproperties.h
@@ -0,0 +1,75 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtCore/qobject.h>
+#include <QtCore/qproperty.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQml/qqmllist.h>
+#include <QtQml/qqmlregistration.h>
+
+#ifndef TYPEWITHREQUIREDPROPERTIES_H_
+# define TYPEWITHREQUIREDPROPERTIES_H_
+
+class ExtensionTypeWithRequiredProperties : public QObject
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+
+ Q_PROPERTY(double requiredPropertyFromExtension READ getRequiredPropertyFromExtension WRITE
+ setRequiredPropertyFromExtension REQUIRED)
+
+ QProperty<double> m_requiredPropertyFromExtension{};
+
+public:
+ ExtensionTypeWithRequiredProperties(QObject *parent = nullptr) : QObject(parent) { }
+
+ double getRequiredPropertyFromExtension() const { return m_requiredPropertyFromExtension; }
+ void setRequiredPropertyFromExtension(double v) { m_requiredPropertyFromExtension = v; }
+};
+
+class TypeWithRequiredProperties : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(QQuickItem *inheritedRequiredProperty READ getInheritedRequiredProperty WRITE
+ setInheritedRequiredProperty REQUIRED)
+ Q_PROPERTY(int inheritedRequiredPropertyThatWillBeBound READ
+ getInheritedRequiredPropertyThatWillBeBound WRITE
+ setInheritedRequiredPropertyThatWillBeBound REQUIRED)
+ Q_PROPERTY(int nonRequiredInheritedPropertyThatWillBeMarkedRequired READ
+ getNonRequiredInheritedPropertyThatWillBeMarkedRequired WRITE
+ setNonRequiredInheritedPropertyThatWillBeMarkedRequired REQUIRED)
+
+ QML_EXTENDED(ExtensionTypeWithRequiredProperties)
+
+ QProperty<QQuickItem *> m_inheritedRequiredProperty{};
+ QProperty<int> m_inheritedRequiredPropertyThatWillBeBound{};
+ QProperty<int> m_nonRequiredInheritedPropertyThatWillBeMarkedRequired{};
+
+public:
+ TypeWithRequiredProperties(QObject *parent = nullptr) : QObject(parent) { }
+
+ QQuickItem *getInheritedRequiredProperty() const { return m_inheritedRequiredProperty; }
+ void setInheritedRequiredProperty(QQuickItem *v) { m_inheritedRequiredProperty = v; }
+
+ int getInheritedRequiredPropertyThatWillBeBound() const
+ {
+ return m_inheritedRequiredPropertyThatWillBeBound;
+ }
+ void setInheritedRequiredPropertyThatWillBeBound(int v)
+ {
+ m_inheritedRequiredPropertyThatWillBeBound = v;
+ }
+
+ int getNonRequiredInheritedPropertyThatWillBeMarkedRequired() const
+ {
+ return m_nonRequiredInheritedPropertyThatWillBeMarkedRequired;
+ }
+ void setNonRequiredInheritedPropertyThatWillBeMarkedRequired(int v)
+ {
+ m_nonRequiredInheritedPropertyThatWillBeMarkedRequired = v;
+ }
+};
+
+#endif // TYPEWITHREQUIREDPROPERTIES_H_
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithsignal.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithsignal.h
index 139b431a40..6bb94ae051 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithsignal.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithsignal.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPEWITHSIGNAL_H
#define TYPEWITHSIGNAL_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithspecialproperties.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithspecialproperties.h
index 9d68275b1e..8bf068ba35 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithspecialproperties.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithspecialproperties.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPEWITHSPECIALPROPERTIES_H
#define TYPEWITHSPECIALPROPERTIES_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/generalizedGroupedProperty.qml b/tests/auto/qml/qmltc/QmltcTests/generalizedGroupedProperty.qml
index a037776a52..2c21298c35 100644
--- a/tests/auto/qml/qmltc/QmltcTests/generalizedGroupedProperty.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/generalizedGroupedProperty.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/inlineComponents.qml b/tests/auto/qml/qmltc/QmltcTests/inlineComponents.qml
index f9146083f6..284a8f5034 100644
--- a/tests/auto/qml/qmltc/QmltcTests/inlineComponents.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/inlineComponents.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick as MyQtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/myCheckBox.qml b/tests/auto/qml/qmltc/QmltcTests/myCheckBox.qml
new file mode 100644
index 0000000000..c5a2f5a7b8
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/myCheckBox.qml
@@ -0,0 +1,5 @@
+import QtQuick.Templates
+
+CheckBox {
+
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/mySignals.qml b/tests/auto/qml/qmltc/QmltcTests/mySignals.qml
index c79a0518c2..0348a0af54 100644
--- a/tests/auto/qml/qmltc/QmltcTests/mySignals.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/mySignals.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QmltcTests
import QtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/properties.qml b/tests/auto/qml/qmltc/QmltcTests/properties.qml
index ca827519d5..f42b14a356 100644
--- a/tests/auto/qml/qmltc/QmltcTests/properties.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/properties.qml
@@ -26,13 +26,13 @@ QtObject {
property date dateP
property font fontP
property matrix4x4 matrix4x4P
- property point pointP
- property quaternion quatP
- property rect rectP
- property size sizeP
- property vector2d vec2dP
- property vector3d vec3dP
- property vector4d vec4dP
+ property point pointP: ({ x: 100, y: 200 })
+ property quaternion quatP: ({ x: 100, y: 200, z: 300, scalar: 400 })
+ property rect rectP: ({ x: 100, y: 200, width: 300, height: 400 })
+ property size sizeP: ({ width: 100, height: 200 })
+ property vector2d vec2dP : ({ x: 100, y: 200 })
+ property vector3d vec3dP: ({ x: 100, y: 200, z: 300 })
+ property vector4d vec4dP: ({ x: 100, y: 200, z: 300, w: 400 })
default property QtObject defaultObjP
readonly property string readonlyStringP: "foobar"
diff --git a/tests/auto/qml/qmltc/QmltcTests/propertyAliasAttributes.qml b/tests/auto/qml/qmltc/QmltcTests/propertyAliasAttributes.qml
index 66cd948ac4..fb57a2bbc8 100644
--- a/tests/auto/qml/qmltc/QmltcTests/propertyAliasAttributes.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/propertyAliasAttributes.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QmltcTests
diff --git a/tests/auto/qml/qmltc/QmltcTests/qtbug120700_main.qml b/tests/auto/qml/qmltc/QmltcTests/qtbug120700_main.qml
new file mode 100644
index 0000000000..0796d00732
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/qtbug120700_main.qml
@@ -0,0 +1,25 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QmltcTests 1.0
+
+TypeForCustomInitialization {
+ id: myWindow
+ required property int someValue
+
+ property alias someValueAlias: myWindow.someValue
+ property int someValueBinding: someValue + 1
+
+ property bool wasSomeValueChanged: false
+
+ property int someComplexValueThatWillBeSet: { return 5 }
+ property int someComplexValueThatWillNotBeSet: { return 5 }
+
+ property list<int> valueTypeList : []
+ property list<Item> objectTypeList : []
+
+ //QTBUG-114403: onValueChanged should not trigger when setting
+ //the initial values.
+ onSomeValueChanged: { wasSomeValueChanged = true; }
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/qtbug123476.qml b/tests/auto/qml/qmltc/QmltcTests/qtbug123476.qml
new file mode 100644
index 0000000000..79aa178de4
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/qtbug123476.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+Item {
+ // qmltc should see that rectangle is used as the type argument
+ // for the list and produce an import for QQuickRectangle.
+ // Failure to do so will produce code that cannot compile and the
+ // test will fail at build time.
+ property list<Rectangle> listWithUniqueReferenceToType : []
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/repeaterCrash.qml b/tests/auto/qml/qmltc/QmltcTests/repeaterCrash.qml
index 7c4dad5a4e..d4eb72786b 100644
--- a/tests/auto/qml/qmltc/QmltcTests/repeaterCrash.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/repeaterCrash.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/requiredProperties.qml b/tests/auto/qml/qmltc/QmltcTests/requiredProperties.qml
new file mode 100644
index 0000000000..77e9c88b9b
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/requiredProperties.qml
@@ -0,0 +1,61 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QmltcTests 1.0
+
+TypeWithRequiredProperties {
+ id: self
+ required property int primitiveType
+ required property list<int> valueList
+ required property list<Item> objectList
+
+ property int propertyThatWillBeMarkedRequired
+
+ // This is already bound so it should not appear as part of the
+ // bundle.
+ inheritedRequiredPropertyThatWillBeBound : 10
+
+ // This should be ignored as it alias a required property we are
+ // already going to consider. It should thus not appear as part of
+ // the bundle.
+ property alias aliasToRequiredProperty : self.primitiveType
+
+ required propertyThatWillBeMarkedRequired
+ required nonRequiredInheritedPropertyThatWillBeMarkedRequired
+
+ property alias aliasToRequiredInner: inner.requiredInner
+
+ // This should be ignored as the underlying property is already bound.
+ property alias aliasToRequiredBoundedInner: inner.requiredBoundedInner
+
+ property alias aliasToInnerThatWillBeMarkedRequired: inner.nonRequiredInner
+ required aliasToInnerThatWillBeMarkedRequired
+
+ property int notRequired
+ property alias requiredAliasToUnrequiredProperty : self.notRequired
+ required requiredAliasToUnrequiredProperty
+
+ // When we have an alias to a required property in the same scope
+ // we exclude the alias in favor of setting the property directly.
+ // See for example aliasToRequiredProperty in this file.
+ //
+ // The following alias should instead be picked up, as it point to
+ // an inner scope.
+ // Nonetheless, an initial implementation had a bug that would
+ // discard the alias as long as a property with the same name as
+ // the target was present in the same scope.
+ //
+ // The following alias tests this initially failing case.
+ property alias aliasToPropertyThatShadows: inner.primitiveType
+
+ property Item children : Item {
+ id: inner
+ required property int requiredInner
+ property int nonRequiredInner
+ required property int requiredBoundedInner
+ requiredBoundedInner: 43
+
+ required property int primitiveType
+ }
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/signalConnections.qml b/tests/auto/qml/qmltc/QmltcTests/signalConnections.qml
new file mode 100644
index 0000000000..d88e3920c3
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/signalConnections.qml
@@ -0,0 +1,46 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ id: root
+
+ property bool cycleEnabled: false
+ property bool cycleFirst: false
+ property bool cycleSecond: false
+
+ property Timer enableTimer: Timer {
+ running: root.cycleEnabled
+ interval: 1
+ onTriggered: {
+ conn.enabled = !conn.enabled;
+ root.cycleEnabled = false;
+ }
+ }
+
+ property Timer firstTimer: Timer {
+ id: firstTimer
+ objectName: "first"
+ running: root.cycleFirst
+ interval: 1
+ onTriggered: root.cycleFirst = false
+ }
+
+ property Timer secondTimer: Timer {
+ objectName: "second"
+ running: root.cycleSecond
+ interval: 1
+ onTriggered: conn.target = this;
+ repeat: true
+ }
+
+ property Connections conn: Connections {
+ id: conn
+ target: firstTimer
+ function onTriggered(m) {
+ root.objectName = target.objectName
+ root.cycleSecond = false;
+ }
+ }
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/singletons.qml b/tests/auto/qml/qmltc/QmltcTests/singletons.qml
index a45e502bc0..d30a50dd6b 100644
--- a/tests/auto/qml/qmltc/QmltcTests/singletons.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/singletons.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QmltcTests
diff --git a/tests/auto/qml/qmltc/QmltcTests/stringToUrl.qml b/tests/auto/qml/qmltc/QmltcTests/stringToUrl.qml
new file mode 100644
index 0000000000..1172c42032
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/stringToUrl.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.12
+
+QtObject {
+ readonly property FontLoader iconLoader: FontLoader {
+ source: "qrc:/qt/qml/path/to/font.ttf"
+ }
+ property string myUrl: "qrc:/qt/qml/path/to/font2.ttf"
+ readonly property FontLoader iconLoader2: FontLoader {
+ source: myUrl
+ }
+}
+
diff --git a/tests/auto/qml/qmltc/QmltcTests/subfolder/code.js b/tests/auto/qml/qmltc/QmltcTests/subfolder/code.js
index a248743d29..7b552e7f67 100644
--- a/tests/auto/qml/qmltc/QmltcTests/subfolder/code.js
+++ b/tests/auto/qml/qmltc/QmltcTests/subfolder/code.js
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
function isGood(value)
{
diff --git a/tests/auto/qml/qmltc/QmltcTests/translations.qml b/tests/auto/qml/qmltc/QmltcTests/translations.qml
index e00d9f5b86..71e9298fd1 100644
--- a/tests/auto/qml/qmltc/QmltcTests/translations.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/translations.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/translationsById.qml b/tests/auto/qml/qmltc/QmltcTests/translationsById.qml
index e3606d9b0f..98fd5cb846 100644
--- a/tests/auto/qml/qmltc/QmltcTests/translationsById.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/translationsById.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/valueTypeListProperty.qml b/tests/auto/qml/qmltc/QmltcTests/valueTypeListProperty.qml
index 7226abbb2e..300af9d31f 100644
--- a/tests/auto/qml/qmltc/QmltcTests/valueTypeListProperty.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/valueTypeListProperty.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QtQuick
diff --git a/tests/auto/qml/qmltc/nameconflict.cpp b/tests/auto/qml/qmltc/nameconflict.cpp
index e95272913f..b1fb21977b 100644
--- a/tests/auto/qml/qmltc/nameconflict.cpp
+++ b/tests/auto/qml/qmltc/nameconflict.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "nameconflict.h"
#include <QtCore/qobject.h>
diff --git a/tests/auto/qml/qmltc/nameconflict.h b/tests/auto/qml/qmltc/nameconflict.h
index ea971b5159..64297af4d4 100644
--- a/tests/auto/qml/qmltc/nameconflict.h
+++ b/tests/auto/qml/qmltc/nameconflict.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef NAME_CONFLICT_FLAG
#define NAME_CONFLICT_FLAG
diff --git a/tests/auto/qml/qmltc/tst_qmltc.cpp b/tests/auto/qml/qmltc/tst_qmltc.cpp
index 1fa4030642..ef33cebc00 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.cpp
+++ b/tests/auto/qml/qmltc/tst_qmltc.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_qmltc.h"
@@ -21,10 +21,12 @@
#include "qjsvalueassignments.h"
#include "extensiontypebindings.h"
#include "qtbug103956_main.h"
+#include "qtbug120700_main.h"
#include "nonstandardinclude.h"
#include "specialproperties.h"
#include "regexpbindings.h"
#include "aliasassignments.h"
+#include "connections.h"
#include "signalhandlers.h"
#include "javascriptfunctions.h"
@@ -77,12 +79,18 @@
#include "repeatercrash.h"
#include "aliases.h"
#include "inlinecomponentsfromdifferentfiles.h"
+#include "helloexportedworld.h"
+#include "helloexportedworldnofilename.h"
#include "testprivateproperty.h"
#include "singletons.h"
#include "mysignals.h"
#include "namespacedtypes.h"
#include "type.h"
+#include "qmltablemodel.h"
+#include "stringtourl.h"
+#include "signalconnections.h"
+#include "requiredproperties.h"
// Qt:
#include <QtCore/qstring.h>
@@ -147,11 +155,14 @@ void tst_qmltc::initTestCase()
QUrl("qrc:/qt/qml/QmltcTests/regexpBindings.qml"),
QUrl("qrc:/qt/qml/QmltcTests/AliasBase.qml"),
QUrl("qrc:/qt/qml/QmltcTests/aliasAssignments.qml"),
+ QUrl("qrc:/qt/qml/QmltcTests/Connections.qml"),
QUrl("qrc:/qt/qml/QmltcTests/qtbug103956/SubComponent.qml"),
QUrl("qrc:/qt/qml/QmltcTests/qtbug103956/MainComponent.qml"),
QUrl("qrc:/qt/qml/QmltcTests/qtbug103956/qtbug103956_main.qml"),
+ QUrl("qrc:/qt/qml/QmltcTests/qtbug120700_main.qml"),
+
QUrl("qrc:/qt/qml/QmltcTests/signalHandlers.qml"),
QUrl("qrc:/qt/qml/QmltcTests/javaScriptFunctions.qml"),
QUrl("qrc:/qt/qml/QmltcTests/changingBindings.qml"),
@@ -192,6 +203,7 @@ void tst_qmltc::initTestCase()
QUrl("qrc:/qt/qml/QmltcTests/calqlatrBits.qml"),
QUrl("qrc:/qt/qml/QmltcTests/valueTypeListProperty.qml"),
QUrl("qrc:/qt/qml/QmltcTests/appendToQQmlListProperty.qml"),
+ QUrl("qrc:/qt/qml/QmltcTests/requiredProperties.qml"),
};
QQmlEngine e;
@@ -374,7 +386,14 @@ void tst_qmltc::properties()
QCOMPARE(created.intP(), 42);
QCOMPARE(created.realP(), 2.32);
QCOMPARE(created.stringP(), u"hello, world"_s);
- QCOMPARE(created.urlP(), u"https://www.qt.io/"_s);
+ QCOMPARE(created.urlP(), QUrl(u"https://www.qt.io/"_s));
+ QCOMPARE(created.pointP(), QPoint(100, 200));
+ QCOMPARE(created.quatP(), QQuaternion(400, 100, 200, 300));
+ QCOMPARE(created.rectP(), QRectF(100, 200, 300, 400));
+ QCOMPARE(created.sizeP(), QSizeF(100, 200));
+ QCOMPARE(created.vec2dP(), QVector2D(100, 200));
+ QCOMPARE(created.vec3dP(), QVector3D(100, 200, 300));
+ QCOMPARE(created.vec4dP(), QVector4D(100, 200, 300, 400));
QCOMPARE(created.varP(), 42.42);
QCOMPARE(created.boolP(), true);
@@ -818,6 +837,103 @@ void tst_qmltc::visibleAliasMethods()
QCOMPARE(created.firstComponent()->setMe(), true);
}
+// QTBUG-120700
+void tst_qmltc::customInitialization()
+{
+ int valueToTest = 10;
+
+ QQuickItem firstItem;
+ QQuickItem secondItem;
+
+ QQmlEngine e;
+ PREPEND_NAMESPACE(qtbug120700_main)
+ created(&e, {valueToTest} ,nullptr, [valueToTest, &firstItem, &secondItem](auto& component) {
+ component.setSomeComplexValueThatWillBeSet(valueToTest);
+ component.setPropertyFromExtension(static_cast<double>(valueToTest));
+ component.setDefaultedBindable(static_cast<double>(valueToTest));
+ component.setValueTypeList({1, 2, 3, 4});
+ component.setObjectTypeList({&firstItem, &secondItem});
+ component.setExtensionObjectList({&firstItem, &secondItem});
+ component.setCppObjectList({&firstItem, &secondItem});
+ });
+
+ // QTBUG-114403: onValueChanged should have not been triggered
+ // when setting the initial value for the property.
+ // If this is true then the handler was called.
+ QCOMPARE(created.wasSomeValueChanged(), false);
+
+ // someComplexValueThatWillBeSet is set through a binding in the
+ // QML code, but is initialized when the instance is created.
+ // The bindings, which is generally set after the custom
+ // initialization was perfomed, should not overwrite the initial
+ // value that the user provided.
+ // On the other side, someComplexValueThatWillNotBeSet should
+ // still respect the original binding as an initial value for it
+ // was not provided.
+ QCOMPARE(created.someComplexValueThatWillBeSet(), valueToTest);
+ QCOMPARE(created.someComplexValueThatWillNotBeSet(), 5);
+
+ QCOMPARE(created.someValue(), valueToTest);
+ QCOMPARE(created.someValueAlias(), valueToTest);
+ QCOMPARE(created.someValueBinding(), valueToTest + 1);
+ QCOMPARE(created.property("propertyFromExtension").toDouble(), static_cast<double>(valueToTest));
+ QCOMPARE(created.bindableDefaultedBindable().value(), static_cast<double>(valueToTest));
+ QCOMPARE(created.valueTypeList(), QList({1, 2, 3, 4}));
+ QCOMPARE(created.objectTypeList().toList<QList<QQuickItem*>>(), QList({&firstItem, &secondItem}));
+ QCOMPARE(
+ created.property("extensionObjectList").value<QQmlListProperty<QQuickItem>>().toList<QList<QQuickItem*>>(),
+ QList({&firstItem, &secondItem})
+ );
+ QCOMPARE(created.getCppObjectList().toList<QList<QQuickItem*>>(), QList({&firstItem, &secondItem}));
+}
+
+void tst_qmltc::requiredPropertiesInitialization()
+{
+ QQuickItem item{};
+
+ int aliasToInnerThatWillBeMarkedRequired = 10;
+ int aliasToPropertyThatShadows = 42;
+ int aliasToRequiredInner = 11;
+ QQuickItem inheritedRequiredProperty{};
+ int nonRequiredInheritedPropertyThatWillBeMarkedRequired = 12;
+ QList<QQuickItem*> objectList{&item};
+ int primitiveType = 13;
+ int propertyThatWillBeMarkedRequired = 14;
+ int requiredAliasToUnrequiredProperty = 15;
+ double requiredPropertyFromExtension = 16.0;
+ QList<int> valueList{1, 2, 3, 4};
+
+ QQmlEngine e;
+ PREPEND_NAMESPACE(requiredProperties) created(
+ &e,
+ {
+ aliasToInnerThatWillBeMarkedRequired,
+ aliasToPropertyThatShadows,
+ aliasToRequiredInner,
+ &inheritedRequiredProperty,
+ nonRequiredInheritedPropertyThatWillBeMarkedRequired,
+ objectList,
+ primitiveType,
+ propertyThatWillBeMarkedRequired,
+ requiredAliasToUnrequiredProperty,
+ requiredPropertyFromExtension,
+ valueList
+ }
+ );
+
+ QCOMPARE(created.aliasToInnerThatWillBeMarkedRequired(), aliasToInnerThatWillBeMarkedRequired);
+ QCOMPARE(created.aliasToPropertyThatShadows(), aliasToPropertyThatShadows);
+ QCOMPARE(created.aliasToRequiredInner(), aliasToRequiredInner);
+ QCOMPARE(created.getInheritedRequiredProperty(), &inheritedRequiredProperty);
+ QCOMPARE(created.getNonRequiredInheritedPropertyThatWillBeMarkedRequired(), nonRequiredInheritedPropertyThatWillBeMarkedRequired);
+ QCOMPARE(created.objectList().toList<QList<QQuickItem*>>(), objectList);
+ QCOMPARE(created.primitiveType(), primitiveType);
+ QCOMPARE(created.propertyThatWillBeMarkedRequired(), propertyThatWillBeMarkedRequired);
+ QCOMPARE(created.requiredAliasToUnrequiredProperty(), requiredAliasToUnrequiredProperty);
+ QCOMPARE(created.property("requiredPropertyFromExtension").toDouble(), requiredPropertyFromExtension);
+ QCOMPARE(created.valueList(), valueList);
+}
+
// QTBUG-104094
void tst_qmltc::nonStandardIncludesInsideModule()
{
@@ -887,6 +1003,12 @@ void tst_qmltc::aliasAssignments()
}
}
+void tst_qmltc::connections()
+{
+ QQmlEngine e;
+ PREPEND_NAMESPACE(Connections) created(&e);
+}
+
void tst_qmltc::signalHandlers()
{
QQmlEngine e;
@@ -1058,7 +1180,7 @@ void tst_qmltc::propertyAlias_external()
void tst_qmltc::propertyAliasAttribute()
{
QQmlEngine e;
- PREPEND_NAMESPACE(propertyAliasAttributes) fromQmltc(&e);
+ PREPEND_NAMESPACE(propertyAliasAttributes) fromQmltc(&e, {""});
QQmlComponent c(&e);
c.loadUrl(QUrl("qrc:/qt/qml/QmltcTests/propertyAliasAttributes.qml"));
@@ -3204,8 +3326,74 @@ void tst_qmltc::namespacedName()
{
// cmake script should be able to auto-fill the namespace of the generated modules, and to
// replace . with ::
- NamespaceTest::Subfolder::Type *t;
- Q_UNUSED(t);
+ QQmlEngine e;
+ NamespaceTest::Subfolder::Type t(&e);
+ QCOMPARE(t.data(), u"Hello from namespace"_s);
+}
+
+void tst_qmltc::checkExportsAreCompiling()
+{
+ QQmlEngine e;
+ QmltcExportedTests::HelloExportedWorld w(&e);
+ QCOMPARE(w.myString(), u"Hello! I should be exported by qmltc"_s);
+}
+
+void tst_qmltc::checkExportsNoFileName()
+{
+ QQmlEngine e;
+ QmltcExportedNoFileNameTest::HelloExportedWorldNoFileName w(&e);
+ QCOMPARE(w.myString(), u"Hello! I should be exported by qmltc"_s);
+}
+
+#if QT_CONFIG(qml_table_model)
+void tst_qmltc::qmlTableModel()
+{
+ QQmlEngine e;
+ PREPEND_NAMESPACE(QmlTableModel) createdByQmltc(&e);
+ // check that the tableModel is not default constructed
+ QVariant model = createdByQmltc.model();
+ QVERIFY(model.isValid());
+ QQmlTableModel *tableModel = model.value<QQmlTableModel *>();
+ QVERIFY(tableModel);
+ QCOMPARE(tableModel->property("testName").toString(), u"MyTableModel"_s);
+}
+#endif
+
+void tst_qmltc::urlToString()
+{
+ QQmlEngine e;
+ PREPEND_NAMESPACE(stringToUrl) createdByQmltc(&e);
+ // check that the tableModel is not default constructed
+ QUrl first = createdByQmltc.iconLoader()->source();
+ QUrl second = createdByQmltc.iconLoader2()->source();
+ QCOMPARE(first, QUrl("qrc:/qt/qml/path/to/font.ttf"));
+ QCOMPARE(second, QUrl("qrc:/qt/qml/path/to/font2.ttf"));
+}
+
+void tst_qmltc::signalConnections()
+{
+ QQmlEngine e;
+ PREPEND_NAMESPACE(signalConnections) createdByQmltc(&e);
+
+ QVERIFY(createdByQmltc.objectName().isEmpty());
+ createdByQmltc.setCycleFirst(true);
+ QTRY_VERIFY(!createdByQmltc.cycleFirst());
+ QCOMPARE(createdByQmltc.objectName(), QLatin1String("first"));
+
+ createdByQmltc.setObjectName(QLatin1String("none"));
+ createdByQmltc.setCycleEnabled(true);
+ QTRY_VERIFY(!createdByQmltc.cycleEnabled());
+
+ createdByQmltc.setCycleFirst(true);
+ QTRY_VERIFY(!createdByQmltc.cycleFirst());
+ QCOMPARE(createdByQmltc.objectName(), QLatin1String("none"));
+
+ createdByQmltc.setCycleEnabled(true);
+ QTRY_VERIFY(!createdByQmltc.cycleEnabled());
+
+ createdByQmltc.setCycleSecond(true);
+ QTRY_VERIFY(!createdByQmltc.cycleSecond());
+ QCOMPARE(createdByQmltc.objectName(), QLatin1String("second"));
}
QTEST_MAIN(tst_qmltc)
diff --git a/tests/auto/qml/qmltc/tst_qmltc.h b/tests/auto/qml/qmltc/tst_qmltc.h
index af084dcc01..ede6d551a0 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.h
+++ b/tests/auto/qml/qmltc/tst_qmltc.h
@@ -1,7 +1,8 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
+#include <private/qtqmlmodelsglobal_p.h>
using namespace Qt::StringLiterals;
@@ -34,10 +35,13 @@ private slots:
void jsvalueAssignments();
void extensionTypeBindings();
void visibleAliasMethods(); // QTBUG-103956
+ void customInitialization(); // QTBUG-120700
+ void requiredPropertiesInitialization();
void nonStandardIncludesInsideModule(); // QTBUG-104094
void specialProperties();
void regexpBindings();
void aliasAssignments();
+ void connections();
void signalHandlers();
void jsFunctions();
@@ -93,4 +97,12 @@ private slots:
void constSignalParameters();
void cppNamespaces();
void namespacedName();
+ void checkExportsAreCompiling();
+ void checkExportsNoFileName();
+
+#if QT_CONFIG(qml_table_model)
+ void qmlTableModel();
+#endif
+ void urlToString();
+ void signalConnections();
};
diff --git a/tests/auto/qml/qmltc_manual/CMakeLists.txt b/tests/auto/qml/qmltc_manual/CMakeLists.txt
index 8101bcbcea..6f1b065f99 100644
--- a/tests/auto/qml/qmltc_manual/CMakeLists.txt
+++ b/tests/auto/qml/qmltc_manual/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmltc_manual LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -19,9 +25,10 @@ qt_internal_add_test(tst_qmltc_manual
TESTDATA ${test_data}
)
+qt_policy(SET QTP0001 NEW)
+
qt6_add_qml_module(tst_qmltc_manual
URI "QmltcManualTests"
- AUTO_RESOURCE_PREFIX
QML_FILES
${test_data}
)
diff --git a/tests/auto/qml/qmltc_manual/testclasses.h b/tests/auto/qml/qmltc_manual/testclasses.h
index a3fc9cfc21..879b815f16 100644
--- a/tests/auto/qml/qmltc_manual/testclasses.h
+++ b/tests/auto/qml/qmltc_manual/testclasses.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTCLASSES_H
#define TESTCLASSES_H
diff --git a/tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp b/tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp
index ca8e0895d7..6e41ff3baa 100644
--- a/tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp
+++ b/tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
diff --git a/tests/auto/qml/qmltc_qprocess/CMakeLists.txt b/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
index bac445dec8..85c01d0a5f 100644
--- a/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
+++ b/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmltc_qprocess LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qmltc_qprocess
SOURCES
tst_qmltc_qprocess.cpp
@@ -14,12 +20,14 @@ qt_internal_add_test(tst_qmltc_qprocess
set_source_files_properties(data/SingletonThing.qml data/singletonUncreatable.qml
PROPERTIES QT_QML_SINGLETON_TYPE true)
+qt_policy(SET QTP0001 NEW)
+
qt6_add_qml_module(tst_qmltc_qprocess
VERSION 1.0
URI QmltcQProcessTests
- AUTO_RESOURCE_PREFIX
SOURCES
cpptypes/testtype.h
+ cpptypes/typewithrequiredproperty.h
DEPENDENCIES
QtQuick/auto
QML_FILES
@@ -33,6 +41,13 @@ qt6_add_qml_module(tst_qmltc_qprocess
data/singletonUncreatable.qml
data/uncreatable.qml
data/invalidSignalHandlers.qml
+ data/QmlBaseFromAnotherModule.qml
+ data/invalidTypeAnnotation.qml
+ data/constructFromString.qml
+ data/unboundRequiredPropertyInInlineComponent.qml
+ data/componentDefinitionInnerRequiredProperty.qml
+ data/componentDefinitionInnerRequiredPropertyFromOutside.qml
+ data/innerLevelRequiredProperty.qml
)
set(common_libraries
diff --git a/tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h b/tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h
index 81c5f00c84..401a63accc 100644
--- a/tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h
+++ b/tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPE_H
#define TESTTYPE_H
diff --git a/tests/auto/qml/qmltc_qprocess/cpptypes/typewithrequiredproperty.h b/tests/auto/qml/qmltc_qprocess/cpptypes/typewithrequiredproperty.h
new file mode 100644
index 0000000000..1b0c69efaa
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/cpptypes/typewithrequiredproperty.h
@@ -0,0 +1,27 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TYPEWITHREQUIREDPROPERTY_H_
+#define TYPEWITHREQUIREDPROPERTY_H_
+
+#include <QtCore/qobject.h>
+#include <QtCore/qproperty.h>
+#include <QtQml/qqmlregistration.h>
+
+class TypeWithRequiredProperty : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(QString requiredProperty READ requiredProperty WRITE setRequiredProperty REQUIRED)
+
+ QProperty<QString> m_requiredProperty;
+
+public:
+ TypeWithRequiredProperty(QObject *parent = nullptr) : QObject(parent) { }
+
+ QString requiredProperty() const { return m_requiredProperty; }
+ void setRequiredProperty(const QString &s) { m_requiredProperty = s; }
+};
+
+#endif // TYPEWITHREQUIREDPROPERTY_H_
diff --git a/tests/auto/qml/qmltc_qprocess/data/QmlBaseFromAnotherModule.qml b/tests/auto/qml/qmltc_qprocess/data/QmlBaseFromAnotherModule.qml
new file mode 100644
index 0000000000..3c62716105
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/QmlBaseFromAnotherModule.qml
@@ -0,0 +1,13 @@
+import QtQml
+import QtQuick
+import QtQuick.Controls.Basic
+import QtQuick.Window
+
+Item {
+ property ScrollBar myBar: ScrollBar {}
+ function f(a: ScrollBar): ScrollBar {}
+
+ // C++ defined QML types from other modules are fine
+ property Item myItem: Item {}
+ function g(a: Item): Item {}
+}
diff --git a/tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredProperty.qml b/tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredProperty.qml
new file mode 100644
index 0000000000..638cf9fa1e
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredProperty.qml
@@ -0,0 +1,18 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ Component {
+ id: mycomp
+
+ Item {
+ Rectangle {
+ // Inner required properties cannot be set so this
+ // should produce an error
+ required property bool bar
+ }
+ }
+ }
+}
diff --git a/tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredPropertyFromOutside.qml b/tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredPropertyFromOutside.qml
new file mode 100644
index 0000000000..56f00edbe9
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredPropertyFromOutside.qml
@@ -0,0 +1,18 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QmltcQProcessTests
+
+Item {
+ Component {
+ id: mycomp
+
+ Item {
+ // This introduces an inner required property
+ // without a binding that cannot be set later and should
+ // thus block the compilation.
+ TypeWithRequiredProperty {}
+ }
+ }
+}
diff --git a/tests/auto/qml/qmltc_qprocess/data/constructFromString.qml b/tests/auto/qml/qmltc_qprocess/data/constructFromString.qml
new file mode 100644
index 0000000000..76ec189f3d
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/constructFromString.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ property point p: "30,50"
+ property rect p3: "10, 20, 30x50"
+ property size p4: "30x50"
+}
diff --git a/tests/auto/qml/qmltc_qprocess/data/innerLevelRequiredProperty.qml b/tests/auto/qml/qmltc_qprocess/data/innerLevelRequiredProperty.qml
new file mode 100644
index 0000000000..8b28418670
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/innerLevelRequiredProperty.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ Item {
+ required property int foo
+ }
+}
diff --git a/tests/auto/qml/qmltc_qprocess/data/invalidAliasRevision.qml b/tests/auto/qml/qmltc_qprocess/data/invalidAliasRevision.qml
index 55e3e73c31..44111430f7 100644
--- a/tests/auto/qml/qmltc_qprocess/data/invalidAliasRevision.qml
+++ b/tests/auto/qml/qmltc_qprocess/data/invalidAliasRevision.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QmltcQProcessTests
diff --git a/tests/auto/qml/qmltc_qprocess/data/invalidTypeAnnotation.qml b/tests/auto/qml/qmltc_qprocess/data/invalidTypeAnnotation.qml
new file mode 100644
index 0000000000..fb8c8eb198
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/invalidTypeAnnotation.qml
@@ -0,0 +1,20 @@
+import QtQuick
+
+
+Item {
+ function f(): Qt.point {
+
+ }
+
+ function g() {
+
+ }
+
+ function h(a: int, b: Item) {
+
+ }
+
+ function alpha(a: int, b) {}
+ function beta(a: int, b): Item {}
+ function gamma(a: Qt.point, b) {}
+}
diff --git a/tests/auto/qml/qmltc_qprocess/data/unboundRequiredPropertyInInlineComponent.qml b/tests/auto/qml/qmltc_qprocess/data/unboundRequiredPropertyInInlineComponent.qml
new file mode 100644
index 0000000000..3955a228d8
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/unboundRequiredPropertyInInlineComponent.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ component InlineComponent: Item { required property int foo }
+
+ InlineComponent {}
+}
diff --git a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
index 7f12f29342..cdbd9695fd 100644
--- a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
+++ b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
@@ -51,6 +51,14 @@ private slots:
void topLevelComponent();
void dashesInFilename();
void invalidSignalHandlers();
+ void exports();
+ void qmlBaseFromAnotherModule();
+ void invalidTypeAnnotation();
+ void constructFromString();
+ void unboundRequiredPropertyInInlineComponent();
+ void componentDefinitionInnerRequiredProperty();
+ void componentDefinitionInnerRequiredPropertyFromOutside();
+ void innerLevelRequiredProperty();
};
#ifndef TST_QMLTC_QPROCESS_RESOURCES
@@ -92,6 +100,7 @@ QString tst_qmltc_qprocess::runQmltc(const QString &inputFile,
args << u"--resource"_s << resource;
args << u"--header"_s << (m_tmpPath + u"/"_s + QFileInfo(inputFile).baseName() + u".h"_s);
args << u"--impl"_s << (m_tmpPath + u"/"_s + QFileInfo(inputFile).baseName() + u".cpp"_s);
+ args << u"--module"_s << u"QmltcQProcessTestModule"_s;
args << extraArgs;
QString errors;
@@ -144,7 +153,7 @@ void tst_qmltc_qprocess::noBuiltins()
QVERIFY(file.rename(original));
};
- for (QString builtin : { u"builtins.qmltypes"_s, u"jsroot.qmltypes"_s }) {
+ for (QString builtin : { u"jsroot.qmltypes"_s, u"builtins.qmltypes"_s }) {
const auto path = QLibraryInfo::path(QLibraryInfo::QmlImportsPath) + u"/"_s + builtin;
QScopeGuard scope(std::bind(renameBack, path));
@@ -261,5 +270,120 @@ void tst_qmltc_qprocess::invalidSignalHandlers()
}
}
+void tst_qmltc_qprocess::qmlBaseFromAnotherModule()
+{
+ {
+ const auto errors = runQmltc(u"QmlBaseFromAnotherModule.qml"_s, false);
+ QVERIFY(errors.contains(
+ u"QmlBaseFromAnotherModule.qml:6:1: Can't compile the QML property type \"ScrollBar\" to C++ because it lives in \"QtQuick.Controls.Basic\" instead of the current file's \"QmltcQProcessTestModule\" QML module."_s));
+ QVERIFY(errors.contains(
+ u"QmlBaseFromAnotherModule.qml:6:1: Can't compile the QML method return type \"ScrollBar\" to C++ because it lives in \"QtQuick.Controls.Basic\" instead of the current file's \"QmltcQProcessTestModule\" QML module."_s));
+ QVERIFY(errors.contains(
+ u"QmlBaseFromAnotherModule.qml:6:1: Can't compile the QML parameter type \"ScrollBar\" to C++ because it lives in \"QtQuick.Controls.Basic\" instead of the current file's \"QmltcQProcessTestModule\" QML module."_s));
+ // it should not complain about the usages of Item, a C++ defined QML element from another
+ // module
+ QVERIFY(!errors.contains(u"\"Item\""_s));
+ }
+}
+
+void tst_qmltc_qprocess::invalidTypeAnnotation()
+{
+ {
+ const auto errors = runQmltc(u"invalidTypeAnnotation.qml"_s, false);
+ QVERIFY(errors.contains(
+ u"invalidTypeAnnotation.qml:5:17: \"Qt.point\" was not found for the return type of method \"f\"."_s));
+ QVERIFY(errors.contains(
+ u"invalidTypeAnnotation.qml:19:21: \"Qt.point\" was not found for the type of parameter \"a\" in method \"gamma\"."_s));
+ QVERIFY(!errors.contains(u"\"var\""_s));
+ QVERIFY(!errors.contains(u"\"void\""_s));
+ }
+}
+
+static QString fileToString(const QString &path)
+{
+ QFile f(path);
+ if (f.open(QIODevice::ReadOnly))
+ return QString::fromLatin1(f.readAll());
+ return QString();
+}
+
+void tst_qmltc_qprocess::exports()
+{
+ const QString fileName = u"dummy.qml"_s;
+ QStringList extraArgs;
+ extraArgs << "--export"
+ << "MYLIB_EXPORT_MACRO"
+ << "--exportInclude"
+ << "exportheader.h";
+ const auto errors = runQmltc(fileName, true, extraArgs);
+
+ const QString headerName = m_tmpPath + u"/"_s + QFileInfo(fileName).baseName() + u".h"_s;
+ const QString header = fileToString(headerName);
+ const QString implementationName =
+ m_tmpPath + u"/"_s + QFileInfo(fileName).baseName() + u".cpp"_s;
+ const QString implementation = fileToString(implementationName);
+
+ QCOMPARE(errors.size(), 0);
+
+ QVERIFY(header.contains(u"class MYLIB_EXPORT_MACRO dummy : public QObject\n"_s));
+ QVERIFY(!implementation.contains(u"MYLIB_EXPORT_MACRO"_s));
+
+ QVERIFY(header.contains(u"#include \"exportheader.h\"\n"_s));
+ QVERIFY(!implementation.contains(u"exportheader.h"_s));
+}
+
+void tst_qmltc_qprocess::constructFromString()
+{
+ const auto errors = runQmltc(u"constructFromString.qml"_s, false);
+ const QString warningMessage =
+ u"constructFromString.qml:%1:%2: Binding is not supported: Type %3 should be"
+ u" constructed using QML_STRUCTURED_VALUE's construction mechanism, instead of a"
+ u" string."_s;
+ QVERIFY(errors.contains(warningMessage.arg(4).arg(23).arg(u"QPointF")));
+ QVERIFY(errors.contains(warningMessage.arg(5).arg(23).arg(u"QRectF")));
+ QVERIFY(errors.contains(warningMessage.arg(6).arg(23).arg(u"QSizeF")));
+}
+
+void tst_qmltc_qprocess::unboundRequiredPropertyInInlineComponent()
+{
+ {
+ const auto errors = runQmltc(u"unboundRequiredPropertyInInlineComponent.qml"_s, false);
+ QVERIFY(errors.contains(
+ u"unboundRequiredPropertyInInlineComponent.qml:9:5: Component is missing required property foo from InlineComponent [required]"_s
+ ));
+ }
+}
+
+void tst_qmltc_qprocess::componentDefinitionInnerRequiredProperty()
+{
+ {
+ const auto errors = runQmltc(u"componentDefinitionInnerRequiredProperty.qml"_s, false);
+ QVERIFY(errors.contains(
+ u"componentDefinitionInnerRequiredProperty.qml:11:13: Component is missing required property bar from here [required]"
+ ));
+ }
+}
+
+void tst_qmltc_qprocess::componentDefinitionInnerRequiredPropertyFromOutside()
+{
+ {
+ const auto errors =
+ runQmltc(u"componentDefinitionInnerRequiredPropertyFromOutside.qml"_s, false);
+ QVERIFY(errors.contains(
+ u"componentDefinitionInnerRequiredPropertyFromOutside.qml:15:13: Component is missing required property requiredProperty from TypeWithRequiredProperty [required]"
+ ));
+ }
+}
+
+void tst_qmltc_qprocess::innerLevelRequiredProperty()
+{
+ {
+ const auto errors = runQmltc(u"innerLevelRequiredProperty.qml"_s, false);
+ QVERIFY(errors.contains(
+ u"innerLevelRequiredProperty.qml:7:5: Component is missing required property foo from here [required]"
+ ));
+ }
+}
+
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 039f1647db..45669769e4 100644
--- a/tests/auto/qml/qmltyperegistrar/CMakeLists.txt
+++ b/tests/auto/qml/qmltyperegistrar/CMakeLists.txt
@@ -7,12 +7,18 @@
## tst_qmltyperegistrar Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmltyperegistrar LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
add_subdirectory(VersionZero)
add_subdirectory(UnregisteredTypes)
add_subdirectory(foreign)
qt_manual_moc(moc_files OUTPUT_MOC_JSON_FILES json_list noextheader
- INCLUDE_DIRECTORY_TARGETS Qt::Qml)
+ TARGETS Qt6::Qml)
# Dummy target to pass --private-includes to qmltyperegistrar for tst_qmltyperegistrar.
# We want to test that it expects files named foo_p.h appearing in foreign metatypes
@@ -76,9 +82,11 @@ qt_add_library(tst-qmltyperegistrar-with-dashes)
qt_autogen_tools_initial_setup(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_policy(SET QTP0001 NEW)
+
qt_add_qml_module(tst-qmltyperegistrar-with-dashes
URI Module-With-Dashes
- AUTO_RESOURCE_PREFIX
SOURCES
foo.cpp foo.h
OUTPUT_DIRECTORY Module-With-Dashes
@@ -90,4 +98,20 @@ qt_internal_add_resource(tst_qmltyperegistrar "resources"
"/"
FILES
duplicatedExports.json
+ missingTypes.json
)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+qt_add_library(tst-qmltyperegistrar-enum-foreign STATIC enum.cpp)
+qt_autogen_tools_initial_setup(tst-qmltyperegistrar-enum-foreign)
+qt_enable_autogen_tool(tst-qmltyperegistrar-enum-foreign "moc" ON)
+target_link_libraries(tst-qmltyperegistrar-enum-foreign PRIVATE Qt::QmlIntegration)
+
+qt_add_library(tst-qmltyperegistrar-enum STATIC)
+qt_autogen_tools_initial_setup(tst-qmltyperegistrar-enum)
+qt_enable_autogen_tool(tst-qmltyperegistrar-enum "moc" ON)
+target_link_libraries(tst-qmltyperegistrar-enum PRIVATE Qt::Qml tst-qmltyperegistrar-enum-foreign)
+
+qt_add_qml_module(tst-qmltyperegistrar-enum URI TstEnum OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/TstEnum)
+qt_autogen_tools_initial_setup(tst-qmltyperegistrar-enumplugin)
+qt_generate_foreign_qml_types(tst-qmltyperegistrar-enum-foreign tst-qmltyperegistrar-enum)
diff --git a/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/CMakeLists.txt b/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/CMakeLists.txt
index cb020e95e0..d469f1e97f 100644
--- a/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/CMakeLists.txt
+++ b/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/CMakeLists.txt
@@ -2,13 +2,15 @@
# SPDX-License-Identifier: BSD-3-Clause
# Use NO_GENERATE_QMLTYPES to avoid static asserts during compilation of the types to be tested, same for NO_PLUGIN
+
+qt_policy(SET QTP0001 NEW)
+
qt_add_qml_module(UnregisteredTypes
STATIC
URI UnregisteredTypes
NO_GENERATE_QMLTYPES
NO_PLUGIN
SOURCES uncreatable.h
- AUTO_RESOURCE_PREFIX
)
qt_enable_autogen_tool(UnregisteredTypes "moc" ON)
diff --git a/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/uncreatable.h b/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/uncreatable.h
index 9726f4683c..2274f87e3d 100644
--- a/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/uncreatable.h
+++ b/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/uncreatable.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef UNCREATABLE_H
#define UNCREATABLE_H
@@ -39,6 +39,39 @@ public:
static SingletonCreatable3 *create(QQmlEngine *, QJSEngine *) { return nullptr; }
};
+class SingletonForeign : public QObject
+{
+ Q_OBJECT
+ SingletonForeign() = delete;
+};
+
+class SingletonLocalCreatable
+{
+ Q_GADGET
+ QML_FOREIGN(SingletonForeign)
+ QML_ELEMENT
+ QML_SINGLETON
+public:
+ static SingletonForeign *create(QQmlEngine *, QJSEngine *) { return nullptr; }
+};
+
+class SingletonLocalUncreatable1
+{
+ Q_GADGET
+ QML_FOREIGN(SingletonForeign)
+ QML_ELEMENT
+ QML_SINGLETON
+ static SingletonForeign *create(QQmlEngine *, QJSEngine *) { return nullptr; }
+};
+
+class SingletonLocalUncreatable2
+{
+ Q_GADGET
+ QML_FOREIGN(SingletonForeign)
+ QML_ELEMENT
+ QML_SINGLETON
+};
+
class SingletonIncreatable : public QObject
{
Q_OBJECT
@@ -184,4 +217,20 @@ class FixingBadUncreatable
QML_FOREIGN(BadUncreatable)
QML_UNCREATABLE("")
};
+
+class SingletonVesion0 : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+ // is default constructible
+};
+
+class SingletonVesion1 : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+ // is default constructible
+};
#endif // UNCREATABLE_H
diff --git a/tests/auto/qml/qmltyperegistrar/VersionZero/version_zero_type.h b/tests/auto/qml/qmltyperegistrar/VersionZero/version_zero_type.h
index a3277e6ab3..0ad477c3cb 100644
--- a/tests/auto/qml/qmltyperegistrar/VersionZero/version_zero_type.h
+++ b/tests/auto/qml/qmltyperegistrar/VersionZero/version_zero_type.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef VERSION_ZERO_TYPE_H
#define VERSION_ZERO_TYPE_H
diff --git a/tests/auto/qml/qmltyperegistrar/duplicatedExports.h b/tests/auto/qml/qmltyperegistrar/duplicatedExports.h
index 5ae2e77551..e72a2f19c9 100644
--- a/tests/auto/qml/qmltyperegistrar/duplicatedExports.h
+++ b/tests/auto/qml/qmltyperegistrar/duplicatedExports.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DUPLICATEDEXPORTS_H
#define DUPLICATEDEXPORTS_H
diff --git a/tests/auto/qml/qmltyperegistrar/enum.cpp b/tests/auto/qml/qmltyperegistrar/enum.cpp
new file mode 100644
index 0000000000..34d2e00ffa
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/enum.cpp
@@ -0,0 +1,5 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "enum.h"
+#include "moc_enum.cpp"
diff --git a/tests/auto/qml/qmltyperegistrar/enum.h b/tests/auto/qml/qmltyperegistrar/enum.h
new file mode 100644
index 0000000000..653c48c79f
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/enum.h
@@ -0,0 +1,40 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef ENUM_NS_HELLO_H
+#define ENUM_NS_HELLO_H
+
+#include <QObject>
+#include <QtQmlIntegration/qqmlintegration.h>
+
+namespace Hello {
+ Q_NAMESPACE
+ QML_NAMED_ELEMENT(World)
+ enum class World {
+ Europe = 2024,
+ };
+ Q_ENUM_NS(World)
+}
+
+namespace Universe {
+ namespace Galaxy {
+ Q_NAMESPACE
+ QML_NAMED_ELEMENT(Solar)
+ enum class Solar {
+ Earth,
+ };
+ Q_ENUM_NS(Solar)
+ }
+
+ class Blackhole {
+ Q_GADGET
+ QML_ELEMENT
+ public:
+ enum SagittariusA {
+ Singularity
+ };
+ Q_ENUM(SagittariusA)
+ };
+}
+
+#endif // ENUM_NS_HELLO_H
diff --git a/tests/auto/qml/qmltyperegistrar/foo.cpp b/tests/auto/qml/qmltyperegistrar/foo.cpp
index ba95235bd6..c5ef8313dc 100644
--- a/tests/auto/qml/qmltyperegistrar/foo.cpp
+++ b/tests/auto/qml/qmltyperegistrar/foo.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "foo.h"
#include <QDebug>
diff --git a/tests/auto/qml/qmltyperegistrar/foo.h b/tests/auto/qml/qmltyperegistrar/foo.h
index 7872c35c17..5af2e11eaa 100644
--- a/tests/auto/qml/qmltyperegistrar/foo.h
+++ b/tests/auto/qml/qmltyperegistrar/foo.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef FOO_H
#define FOO_H
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/CMakeLists.txt b/tests/auto/qml/qmltyperegistrar/foreign/CMakeLists.txt
index 5334225692..68223ae6a5 100644
--- a/tests/auto/qml/qmltyperegistrar/foreign/CMakeLists.txt
+++ b/tests/auto/qml/qmltyperegistrar/foreign/CMakeLists.txt
@@ -10,7 +10,8 @@
qt_internal_add_cmake_library(foreign
STATIC
SOURCES
- foreign.cpp foreign.h foreign_p.h
+ foreign.cpp foreign.h
+ private/foreign_p.h
PUBLIC_LIBRARIES
Qt::Core
)
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp b/tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp
index f78dd47237..1691f5396a 100644
--- a/tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp
+++ b/tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "foreign.h"
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/foreign.h b/tests/auto/qml/qmltyperegistrar/foreign/foreign.h
index ea78a58432..79ac8074cf 100644
--- a/tests/auto/qml/qmltyperegistrar/foreign/foreign.h
+++ b/tests/auto/qml/qmltyperegistrar/foreign/foreign.h
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef FOREIGN_H
#define FOREIGN_H
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/foreign_p.h b/tests/auto/qml/qmltyperegistrar/foreign/private/foreign_p.h
index fe7986471f..ed23d78284 100644
--- a/tests/auto/qml/qmltyperegistrar/foreign/foreign_p.h
+++ b/tests/auto/qml/qmltyperegistrar/foreign/private/foreign_p.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef FOREIGN_P_H
#define FOREIGN_P_H
@@ -7,7 +7,6 @@
#include <QtCore/qobject.h>
// qmltyperegistrar will assume this file is reachable under <private/foreign_p.h>
-// It's not true, but this is how it works on actual private headers in Qt.
// See the trick in tst_qmltyperegistrar's CMakeLists.txt to turn on the --private-includes option.
class ForeignPrivate : public QObject
{
diff --git a/tests/auto/qml/qmltyperegistrar/hppheader.hpp b/tests/auto/qml/qmltyperegistrar/hppheader.hpp
index dc82fc8530..4278601a9e 100644
--- a/tests/auto/qml/qmltyperegistrar/hppheader.hpp
+++ b/tests/auto/qml/qmltyperegistrar/hppheader.hpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef HPPHEADER_HPP
#define HPPHEADER_HPP
diff --git a/tests/auto/qml/qmltyperegistrar/missingTypes.json b/tests/auto/qml/qmltyperegistrar/missingTypes.json
new file mode 100644
index 0000000000..dacec11c4c
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/missingTypes.json
@@ -0,0 +1,167 @@
+[
+ {
+ "classes": [
+ {
+ "classInfos": [
+ {
+ "name": "QML.Element",
+ "value": "int"
+ },
+ {
+ "name": "QML.Extended",
+ "value": "QQmlIntForeign"
+ },
+ {
+ "name": "QML.Foreign",
+ "value": "int"
+ }
+ ],
+ "className": "QQmlIntForeign",
+ "gadget": true,
+ "qualifiedClassName": "QQmlIntForeign"
+ },
+ {
+ "classInfos": [
+ {
+ "name": "QML.Element",
+ "value": "auto"
+ }
+ ],
+ "className": "ExcessiveVersion",
+ "object": true,
+ "properties": [
+ {
+ "constant": false,
+ "designable": true,
+ "final": false,
+ "index": 0,
+ "name": "palette",
+ "notify": "paletteChanged",
+ "read": "palette",
+ "required": false,
+ "revision": 1536,
+ "scriptable": true,
+ "stored": true,
+ "type": "int",
+ "user": false,
+ "write": "setPalette"
+ }
+ ],
+ "enums": [
+ {
+ "isClass": false,
+ "isFlag": false,
+ "name": "RestorationMode",
+ "type": "NotAnUnderlyingType",
+ "values": [
+ "RestoreNone",
+ "RestoreBinding",
+ "RestoreValue",
+ "RestoreBindingOrValue"
+ ]
+ }
+ ],
+ "qualifiedClassName": "ExcessiveVersion",
+ "signals": [
+ {
+ "access": "public",
+ "name": "paletteChanged",
+ "returnType": "void",
+ "revision": 1536
+ }
+ ],
+ "superClasses": [
+ {
+ "access": "public",
+ "name": "NotQObject"
+ }
+ ]
+ },
+ {
+ "classInfos": [
+ {
+ "name": "QML.Element",
+ "value": "Versioned"
+ },
+ {
+ "name": "QML.AddedInVersion",
+ "value": "264"
+ }
+ ],
+ "className": "AddedInLateVersion",
+ "object": true,
+ "properties": [
+ {
+ "constant": true,
+ "designable": true,
+ "final": false,
+ "index": 0,
+ "name": "revisioned",
+ "read": "revisioned",
+ "required": false,
+ "revision": 260,
+ "scriptable": true,
+ "stored": true,
+ "type": "NotAPropertyType",
+ "user": false
+ }
+ ],
+ "methods": [
+ {
+ "access": "public",
+ "arguments": [
+ {
+ "type": "NotAnArgumentType"
+ }
+ ],
+ "name": "createAThing",
+ "returnType": "NotAReturnType"
+ }
+ ],
+ "qualifiedClassName": "AddedInLateVersion",
+ "superClasses": [
+ {
+ "access": "public",
+ "name": "NotQObject"
+ }
+ ]
+ },
+ {
+ "classInfos": [
+ {
+ "name": "QML.Foreign",
+ "value": "Invisible"
+ },
+ {
+ "name": "QML.Element",
+ "value": "Invisible"
+ }
+ ],
+ "className": "InvisibleForeign",
+ "gadget": true,
+ "qualifiedClassName": "InvisibleForeign"
+ },
+ {
+ "classInfos": [
+ {
+ "name": "QML.Element",
+ "value": "anonymous"
+ },
+ {
+ "name": "QML.Sequence",
+ "value": "NotQByteArray"
+ },
+ {
+ "name": "QML.Foreign",
+ "value": "std::vector<NotQByteArray>"
+ }
+ ],
+ "className": "NotQByteArrayStdVectorForeign",
+ "gadget": true,
+ "qualifiedClassName": "NotQByteArrayStdVectorForeign"
+ }
+ ],
+ "inputFile": "tst_qmltyperegistrar.h",
+ "outputRevision": 68
+ }
+]
diff --git a/tests/auto/qml/qmltyperegistrar/noextheader b/tests/auto/qml/qmltyperegistrar/noextheader
index 1bad168044..2b3579a34b 100644
--- a/tests/auto/qml/qmltyperegistrar/noextheader
+++ b/tests/auto/qml/qmltyperegistrar/noextheader
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef NOEXTHEADER
#define NOEXTHEADER
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
index a0f9a92b5c..e79e9b84b6 100644
--- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_qmltyperegistrar.h"
#include <QtTest/qtest.h>
@@ -116,8 +116,8 @@ void tst_qmltyperegistrar::pastMajorVersions()
void tst_qmltyperegistrar::implementsInterfaces()
{
- QVERIFY(qmltypesData.contains("interfaces: [\"Interface\"]"));
- QVERIFY(qmltypesData.contains("interfaces: [\"Interface\", \"Interface2\"]"));
+ QVERIFY(qmltypesData.contains("interfaces: [\"Interface1\"]"));
+ QVERIFY(qmltypesData.contains("interfaces: [\"Interface1\", \"Interface2\"]"));
}
void tst_qmltyperegistrar::namespacedElement()
@@ -145,9 +145,9 @@ void tst_qmltyperegistrar::metaTypesRegistered()
auto verifyMetaType = [](const char *name, const char *className) {
const auto foundMetaType = QMetaType::fromName(name);
- QVERIFY(foundMetaType.isValid());
+ QVERIFY2(foundMetaType.isValid(), name);
QCOMPARE(foundMetaType.name(), name);
- QVERIFY(foundMetaType.metaObject());
+ QVERIFY2(foundMetaType.metaObject(), name);
QCOMPARE(foundMetaType.metaObject()->className(), className);
};
@@ -356,6 +356,12 @@ void tst_qmltyperegistrar::addRemoveVersion()
QCOMPARE(o->property("thing").toInt(), thingAccessible ? 24 : 0);
}
+void tst_qmltyperegistrar::addInMinorVersion()
+{
+ QVERIFY(qmltypesData.contains("exports: [\"QmlTypeRegistrarTest/MinorVersioned 1.5\"]"));
+ QVERIFY(qmltypesData.contains("exports: [\"QmlTypeRegistrarTest/MinorVersioned 1.2\"]"));
+}
+
#ifdef QT_QUICK_LIB
void tst_qmltyperegistrar::foreignRevisionedProperty()
{
@@ -398,23 +404,83 @@ void tst_qmltyperegistrar::duplicateExportWarnings()
MetaTypesJsonProcessor processor(true);
QVERIFY(processor.processTypes({ ":/duplicatedExports.json" }));
processor.postProcessTypes();
- QVector<QJsonObject> types = processor.types();
- QVector<QJsonObject> typesforeign = processor.foreignTypes();
+ QVector<MetaType> types = processor.types();
+ QVector<MetaType> typesforeign = processor.foreignTypes();
r.setTypes(types, typesforeign);
- auto expectWarning = [](QString message) {
- QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
+ const auto expectWarning = [](const char *message) {
+ QTest::ignoreMessage(QtWarningMsg, message);
};
- expectWarning("Warning: ExportedQmlElement was registered multiple times by following Cpp "
- "classes: ExportedQmlElement, ExportedQmlElement2 (added in 1.2), "
- "ExportedQmlElementDifferentVersion (added in 1.0) (removed in 1.7)");
- expectWarning("Warning: SameNameSameExport was registered multiple times by following Cpp "
- "classes: SameNameSameExport, SameNameSameExport2 (added in 1.2), "
- "SameNameSameExportDifferentVersion (added in 1.0)");
+ expectWarning("Warning: duplicatedExports.h:: ExportedQmlElement is registered multiple times "
+ "by the following C++ classes: ExportedQmlElement, ExportedQmlElement2 "
+ "(added in 1.2), ExportedQmlElementDifferentVersion (added in 1.0) "
+ "(removed in 1.7)");
+ expectWarning("Warning: duplicatedExports.h:: SameNameSameExport is registered multiple times "
+ "by the following C++ classes: SameNameSameExport, SameNameSameExport2 "
+ "(added in 1.2), SameNameSameExportDifferentVersion (added in 1.0)");
QString outputData;
QTextStream output(&outputData, QIODeviceBase::ReadWrite);
- r.write(output);
+ r.write(output, "tst_qmltyperegistrar_qmltyperegistrations.cpp");
+}
+
+void tst_qmltyperegistrar::consistencyWarnings()
+{
+ QmlTypeRegistrar r;
+ r.setModuleVersions(QTypeRevision::fromVersion(1, 1), {}, false);
+ QString moduleName = "tstmodule";
+ QString targetNamespace = "tstnamespace";
+ r.setModuleNameAndNamespace(moduleName, targetNamespace);
+
+ MetaTypesJsonProcessor processor(true);
+
+ QVERIFY(processor.processTypes({ ":/missingTypes.json" }));
+ processor.postProcessTypes();
+
+ const auto expectWarning = [](const char *message) {
+ QTest::ignoreMessage(QtWarningMsg, message);
+ };
+
+ expectWarning("Warning: tst_qmltyperegistrar.h:: "
+ "NotQObject is used as base type but cannot be found.");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: NotQObject is used as base type "
+ "but cannot be found.");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: Invisible is declared as foreign type, "
+ "but cannot be found.");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: NotQByteArray is used as sequence value type "
+ "but cannot be found.");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: NotAPropertyType is used as property type "
+ "but cannot be found.");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: NotAnArgumentType is used as argument type "
+ "but cannot be found.");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: NotAReturnType is used as return type "
+ "but cannot be found.");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: NotAnUnderlyingType is used as enum type "
+ "but cannot be found.");
+
+ processor.postProcessForeignTypes();
+
+ QVector<MetaType> types = processor.types();
+ QVector<MetaType> typesforeign = processor.foreignTypes();
+ r.setTypes(types, typesforeign);
+
+ QString outputData;
+ QTextStream output(&outputData, QIODeviceBase::ReadWrite);
+
+ expectWarning("Warning: tst_qmltyperegistrar.h:: AddedInLateVersion is trying to register "
+ "property revisioned with future version 1.4 when module version is only 1.1");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: ExcessiveVersion is trying to register "
+ "property palette with future version 6.0 when module version is only 1.1");
+
+ r.write(output, "tst_qmltyperegistrar_qmltyperegistrations.cpp");
+
+ QTemporaryFile pluginTypes;
+ QVERIFY(pluginTypes.open());
+
+ expectWarning("Warning: tst_qmltyperegistrar.h:: Refusing to generate non-lowercase name "
+ "Invisible for unknown foreign type");
+
+ r.generatePluginTypes(pluginTypes.fileName());
}
void tst_qmltyperegistrar::clonedSignal()
@@ -432,17 +498,17 @@ void tst_qmltyperegistrar::hasIsConstantInParameters()
QVERIFY(qmltypesData.contains(R"( Signal {
name: "mySignal"
Parameter { name: "myObject"; type: "QObject"; isPointer: true }
- Parameter { name: "myConstObject"; type: "QObject"; isPointer: true; isConstant: true }
- Parameter { name: "myConstObject2"; type: "QObject"; isPointer: true; isConstant: true }
+ Parameter { name: "myConstObject"; type: "QObject"; isPointer: true; isTypeConstant: true }
+ Parameter { name: "myConstObject2"; type: "QObject"; isPointer: true; isTypeConstant: true }
Parameter { name: "myObject2"; type: "QObject"; isPointer: true }
- Parameter { name: "myConstObject3"; type: "QObject"; isPointer: true; isConstant: true }
+ Parameter { name: "myConstObject3"; type: "QObject"; isPointer: true; isTypeConstant: true }
}
)"));
QVERIFY(qmltypesData.contains(R"(Signal {
name: "myVolatileSignal"
- Parameter { name: "a"; type: "volatile QObject"; isPointer: true; isConstant: true }
- Parameter { name: "b"; type: "volatile QObject"; isPointer: true; isConstant: true }
+ Parameter { name: "a"; type: "volatile QObject"; isPointer: true; isTypeConstant: true }
+ Parameter { name: "b"; type: "volatile QObject"; isPointer: true; isTypeConstant: true }
Parameter { name: "nonConst"; type: "volatile QObject"; isPointer: true }
}
)"));
@@ -450,70 +516,101 @@ void tst_qmltyperegistrar::hasIsConstantInParameters()
void tst_qmltyperegistrar::uncreatable()
{
+ using namespace QQmlPrivate;
+
// "normal" constructible types
- QVERIFY(QQmlPrivate::QmlMetaType<Creatable>::hasAcceptableCtors());
- QVERIFY(QQmlPrivate::QmlMetaType<Creatable2>::hasAcceptableCtors());
+ QVERIFY(QmlMetaType<Creatable>::hasAcceptableCtors());
+ QVERIFY(QmlMetaType<Creatable2>::hasAcceptableCtors());
// good singletons
- QVERIFY(QQmlPrivate::QmlMetaType<SingletonCreatable>::hasAcceptableSingletonCtors());
- QVERIFY(QQmlPrivate::QmlMetaType<SingletonCreatable2>::hasAcceptableSingletonCtors());
- QVERIFY(QQmlPrivate::QmlMetaType<SingletonCreatable3>::hasAcceptableSingletonCtors());
+ QCOMPARE((singletonConstructionMode<SingletonCreatable, SingletonCreatable>()),
+ SingletonConstructionMode::Factory);
+ QCOMPARE((singletonConstructionMode<SingletonCreatable2, SingletonCreatable2>()),
+ SingletonConstructionMode::Constructor);
+ QCOMPARE((singletonConstructionMode<SingletonCreatable2, SingletonCreatable2>()),
+ SingletonConstructionMode::Constructor);
+ QCOMPARE((singletonConstructionMode<SingletonForeign, SingletonLocalCreatable>()),
+ SingletonConstructionMode::FactoryWrapper);
// bad singletons
- QVERIFY(!QQmlPrivate::QmlMetaType<SingletonIncreatable>::hasAcceptableSingletonCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<SingletonIncreatable2>::hasAcceptableSingletonCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<SingletonIncreatable3>::hasAcceptableSingletonCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<SingletonIncreatable4>::hasAcceptableSingletonCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<SingletonIncreatableExtended>::hasAcceptableSingletonCtors());
+ QCOMPARE((singletonConstructionMode<SingletonIncreatable, SingletonIncreatable>()),
+ SingletonConstructionMode::None);
+ QCOMPARE((singletonConstructionMode<SingletonIncreatable2, SingletonIncreatable2>()),
+ SingletonConstructionMode::None);
+ QCOMPARE((singletonConstructionMode<SingletonIncreatable3, SingletonIncreatable3>()),
+ SingletonConstructionMode::None);
+ QCOMPARE((singletonConstructionMode<SingletonIncreatable4, SingletonIncreatable4>()),
+ SingletonConstructionMode::None);
+ QCOMPARE((singletonConstructionMode<SingletonIncreatableExtended,
+ SingletonIncreatableExtended>()),
+ SingletonConstructionMode::None);
+ QCOMPARE((singletonConstructionMode<SingletonForeign, SingletonLocalUncreatable1>()),
+ SingletonConstructionMode::None);
+ QCOMPARE((singletonConstructionMode<SingletonForeign, SingletonLocalUncreatable2>()),
+ SingletonConstructionMode::None);
#if QT_DEPRECATED_SINCE(6, 4)
QTest::ignoreMessage(
QtWarningMsg,
- "Singleton SingletonIncreatable needs either a default constructor or, "
- "when adding a default constructor is infeasible, a public static "
- "create(QQmlEngine *, QJSEngine *) method.");
+ "Singleton SingletonIncreatable needs to be a concrete class with either a "
+ "default constructor or, when adding a default constructor is infeasible, "
+ "a public static create(QQmlEngine *, QJSEngine *) method.");
qmlRegisterTypesAndRevisions<SingletonIncreatable>("A", 1);
QTest::ignoreMessage(
QtWarningMsg,
- "Singleton SingletonIncreatable2 needs either a default constructor or, "
- "when adding a default constructor is infeasible, a public static "
- "create(QQmlEngine *, QJSEngine *) method.");
+ "Singleton SingletonIncreatable2 needs to be a concrete class with either a "
+ "default constructor or, when adding a default constructor is infeasible, "
+ "a public static create(QQmlEngine *, QJSEngine *) method.");
qmlRegisterTypesAndRevisions<SingletonIncreatable2>("A", 1);
QTest::ignoreMessage(
QtWarningMsg,
- "Singleton SingletonIncreatable3 needs either a default constructor or, "
- "when adding a default constructor is infeasible, a public static "
- "create(QQmlEngine *, QJSEngine *) method.");
+ "Singleton SingletonIncreatable3 needs to be a concrete class with either a "
+ "default constructor or, when adding a default constructor is infeasible, "
+ "a public static create(QQmlEngine *, QJSEngine *) method.");
qmlRegisterTypesAndRevisions<SingletonIncreatable3>("A", 1);
QTest::ignoreMessage(
QtWarningMsg,
- "Singleton SingletonIncreatable4 needs either a default constructor or, "
- "when adding a default constructor is infeasible, a public static "
- "create(QQmlEngine *, QJSEngine *) method.");
+ "Singleton SingletonIncreatable4 needs to be a concrete class with either a "
+ "default constructor or, when adding a default constructor is infeasible, "
+ "a public static create(QQmlEngine *, QJSEngine *) method.");
qmlRegisterTypesAndRevisions<SingletonIncreatable4>("A", 1);
QTest::ignoreMessage(
QtWarningMsg,
- "Singleton SingletonIncreatableExtended needs either a default constructor or, "
- "when adding a default constructor is infeasible, a public static "
- "create(QQmlEngine *, QJSEngine *) method.");
+ "Singleton SingletonIncreatableExtended needs to be a concrete class with either a "
+ "default constructor or, when adding a default constructor is infeasible, "
+ "a public static create(QQmlEngine *, QJSEngine *) method.");
qmlRegisterTypesAndRevisions<SingletonIncreatableExtended>("A", 1);
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "Singleton SingletonForeign needs to be a concrete class with either a "
+ "default constructor or, when adding a default constructor is infeasible, "
+ "a public static create(QQmlEngine *, QJSEngine *) method.");
+ qmlRegisterTypesAndRevisions<SingletonLocalUncreatable1>("A", 1);
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "Singleton SingletonForeign needs to be a concrete class with either a "
+ "default constructor or, when adding a default constructor is infeasible, "
+ "a public static create(QQmlEngine *, QJSEngine *) method.");
+ qmlRegisterTypesAndRevisions<SingletonLocalUncreatable2>("A", 1);
#endif
// QML_UNCREATABLE types
- QVERIFY(!QQmlPrivate::QmlMetaType<BadUncreatable>::hasAcceptableCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<BadUncreatableExtended>::hasAcceptableCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<GoodUncreatable>::hasAcceptableCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<UncreatableNeedsForeign>::hasAcceptableCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<GoodUncreatableExtended>::hasAcceptableCtors());
+ QVERIFY(!QmlMetaType<BadUncreatable>::hasAcceptableCtors());
+ QVERIFY(!QmlMetaType<BadUncreatableExtended>::hasAcceptableCtors());
+ QVERIFY(!QmlMetaType<GoodUncreatable>::hasAcceptableCtors());
+ QVERIFY(!QmlMetaType<UncreatableNeedsForeign>::hasAcceptableCtors());
+ QVERIFY(!QmlMetaType<GoodUncreatableExtended>::hasAcceptableCtors());
#if QT_DEPRECATED_SINCE(6, 4)
QTest::ignoreMessage(
QtWarningMsg,
- "BadUncreatable is neither a QObject, nor default- and copy-constructible, "
- "nor uncreatable. You should not use it as a QML type.");
+ "BadUncreatable is neither a default constructible QObject, nor a default- "
+ "and copy-constructible Q_GADGET, nor marked as uncreatable.\n"
+ "You should not use it as a QML type.");
qmlRegisterTypesAndRevisions<BadUncreatable>("A", 1);
QTest::ignoreMessage(
QtWarningMsg,
- "BadUncreatableExtended is neither a QObject, nor default- and copy-constructible, "
- "nor uncreatable. You should not use it as a QML type.");
+ "BadUncreatableExtended is neither a default constructible QObject, nor a default- "
+ "and copy-constructible Q_GADGET, nor marked as uncreatable.\n"
+ "You should not use it as a QML type.");
qmlRegisterTypesAndRevisions<BadUncreatableExtended>("A", 1);
#endif
@@ -537,6 +634,26 @@ void tst_qmltyperegistrar::uncreatable()
qmlRegisterTypesAndRevisions<GoodUncreatableExtended>("A", 1);
}
+void tst_qmltyperegistrar::singletonVersions()
+{
+ QQmlEngine engine;
+ qmlRegisterTypesAndRevisions<SingletonVesion0>("A", 0);
+ qmlRegisterTypesAndRevisions<SingletonVesion1>("B", 1);
+
+ QQmlComponent c(&engine);
+ c.setData("import QtQuick\n"
+ "import A\n"
+ "import B\n"
+ "QtObject {\n"
+ " property QtObject v0: SingletonVesion0\n"
+ " property QtObject v1: SingletonVesion1\n"
+ "}", QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> obj(c.create());
+ QVERIFY2(!obj->property("v0").isNull(), "Singleton version 0 is not registered");
+ QVERIFY2(!obj->property("v1").isNull(), "Singleton version 1 is not registered");
+}
+
void tst_qmltyperegistrar::baseVersionInQmltypes()
{
// Since it has no QML_ADDED_IN_VERSION, WithMethod was added in .0 of the current version.
@@ -544,4 +661,428 @@ void tst_qmltyperegistrar::baseVersionInQmltypes()
QVERIFY(qmltypesData.contains("exports: [\"QmlTypeRegistrarTest/WithMethod 1.0\"]"));
}
+void tst_qmltyperegistrar::unconstructibleValueType()
+{
+ QVERIFY(qmltypesData.contains(
+ R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "Unconstructible"
+ accessSemantics: "value"
+ exports: ["QmlTypeRegistrarTest/unconstructible 1.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [256]
+ })"));
+}
+
+void tst_qmltyperegistrar::constructibleValueType()
+{
+ QVERIFY(qmltypesData.contains(
+ R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "Constructible"
+ accessSemantics: "value"
+ exports: ["QmlTypeRegistrarTest/constructible 1.0"]
+ exportMetaObjectRevisions: [256]
+ Method {
+ name: "Constructible"
+ isConstructor: true
+ Parameter { name: "i"; type: "int" }
+ }
+ Method { name: "Constructible"; isCloned: true; isConstructor: true }
+ })"));
+}
+
+void tst_qmltyperegistrar::structuredValueType()
+{
+ QVERIFY(qmltypesData.contains(
+ R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "Structured"
+ accessSemantics: "value"
+ exports: ["QmlTypeRegistrarTest/structured 1.0"]
+ isStructured: true
+ exportMetaObjectRevisions: [256]
+ Property { name: "i"; type: "int"; index: 0; isFinal: true }
+ })"));
+}
+
+void tst_qmltyperegistrar::anonymousAndUncreatable()
+{
+ QVERIFY(qmltypesData.contains(
+ R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "AnonymousAndUncreatable"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ })"));
+}
+
+void tst_qmltyperegistrar::omitInvisible()
+{
+ // If it cannot resolve the type a QML_FOREIGN refers to, it should not generate anything.
+ QVERIFY(qmltypesData.contains(
+ R"(Component { file: "tst_qmltyperegistrar.h"; name: "Invisible"; accessSemantics: "none" })"));
+}
+
+void tst_qmltyperegistrar::typedEnum()
+{
+ QVERIFY(qmltypesData.contains(
+ R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "TypedEnum"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["QmlTypeRegistrarTest/TypedEnum 1.0"]
+ exportMetaObjectRevisions: [256]
+ Enum {
+ name: "UChar"
+ type: "quint8"
+ values: ["V0"]
+ }
+ Enum {
+ name: "Int8_T"
+ type: "qint8"
+ values: ["V1"]
+ }
+ Enum {
+ name: "UInt8_T"
+ type: "quint8"
+ values: ["V2"]
+ }
+ Enum {
+ name: "Int16_T"
+ type: "short"
+ values: ["V3"]
+ }
+ Enum {
+ name: "UInt16_T"
+ type: "ushort"
+ values: ["V4"]
+ }
+ Enum {
+ name: "Int32_T"
+ type: "int"
+ values: ["V5"]
+ }
+ Enum {
+ name: "UInt32_T"
+ type: "uint"
+ values: ["V6"]
+ }
+ Enum {
+ name: "S"
+ type: "short"
+ values: ["A", "B", "C"]
+ }
+ Enum {
+ name: "T"
+ type: "ushort"
+ values: ["D", "E", "F"]
+ }
+ Enum {
+ name: "U"
+ type: "qint8"
+ values: ["G", "H", "I"]
+ }
+ Enum {
+ name: "V"
+ type: "quint8"
+ values: ["J", "K", "L"]
+ }
+ })"));
+}
+
+void tst_qmltyperegistrar::listSignal()
+{
+ QVERIFY(qmltypesData.contains(
+ R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "ListSignal"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Signal {
+ name: "objectListHappened"
+ Parameter { type: "QObjectList" }
+ }
+ })"));
+}
+
+void tst_qmltyperegistrar::withNamespace()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "Bar"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property {
+ name: "outerBarProp"
+ type: "int"
+ read: "bar"
+ index: 0
+ isReadonly: true
+ isPropertyConstant: true
+ }
+ })"));
+
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "Testing::Bar"
+ accessSemantics: "reference"
+ prototype: "Testing::Foo"
+ exports: ["QmlTypeRegistrarTest/Bar 1.0"]
+ exportMetaObjectRevisions: [256]
+ Property {
+ name: "barProp"
+ type: "int"
+ read: "bar"
+ index: 0
+ isReadonly: true
+ isPropertyConstant: true
+ }
+ })"));
+
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "Testing::Foo"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property {
+ name: "fooProp"
+ type: "int"
+ read: "foo"
+ index: 0
+ isReadonly: true
+ isPropertyConstant: true
+ }
+ })"));
+
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "Testing::Inner::Baz"
+ accessSemantics: "reference"
+ prototype: "Testing::Bar"
+ extension: "Bar"
+ exports: ["QmlTypeRegistrarTest/Baz 1.0"]
+ exportMetaObjectRevisions: [256]
+ attachedType: "Testing::Foo"
+ })"));
+}
+
+void tst_qmltyperegistrar::sequenceRegistration()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "std::vector<QByteArray>"
+ accessSemantics: "sequence"
+ valueType: "QByteArray"
+ })"));
+}
+
+void tst_qmltyperegistrar::valueTypeSelfReference()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "QPersistentModelIndex"
+ accessSemantics: "value"
+ extension: "QPersistentModelIndexValueType"
+ })"));
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "QPersistentModelIndexValueType"
+ accessSemantics: "value"
+ Property { name: "row"; type: "int"; read: "row"; index: 0; isReadonly: true; isFinal: true }
+ })"));
+}
+
+void tst_qmltyperegistrar::foreignNamespaceFromGadget()
+{
+ QQmlEngine engine;
+ {
+ QQmlComponent c(&engine);
+ c.setData(QStringLiteral(R"(
+ import QtQml
+ import QmlTypeRegistrarTest
+ QtObject {
+ objectName: 'b' + NetworkManager.B
+ }
+ )").toUtf8(), QUrl("foreignNamespaceFromGadget.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QCOMPARE(o->objectName(), QStringLiteral("b1"));
+ }
+
+ {
+ QQmlComponent c(&engine);
+ c.setData(QStringLiteral(R"(
+ import QtQml
+ import QmlTypeRegistrarTest
+ QtObject {
+ objectName: 'b' + NotNamespaceForeign.B
+ }
+ )").toUtf8(), QUrl("foreignNamespaceFromGadget2.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QCOMPARE(o->objectName(), QStringLiteral("b1"));
+ }
+}
+
+void tst_qmltyperegistrar::nameExplosion_data()
+{
+ QTest::addColumn<QByteArray>("qml");
+ QTest::addRow("Name1") << QByteArray("import QmlTypeRegistrarTest\nName1{}");
+ QTest::addRow("Name2") << QByteArray("import QmlTypeRegistrarTest\nName2{}");
+ QTest::addRow("NameExplosion") << QByteArray("import QmlTypeRegistrarTest\nNameExplosion{}");
+}
+
+void tst_qmltyperegistrar::nameExplosion()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "NameExplosion"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: [
+ "QmlTypeRegistrarTest/Name1 1.0",
+ "QmlTypeRegistrarTest/Name2 1.0",
+ "QmlTypeRegistrarTest/NameExplosion 1.0"
+ ]
+ exportMetaObjectRevisions: [256]
+ })"));
+
+ QFETCH(QByteArray, qml);
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine);
+
+ c.setData(qml, QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
+
+void tst_qmltyperegistrar::javaScriptExtension()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "JavaScriptExtension"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ extension: "SymbolPrototype"
+ extensionIsJavaScript: true
+ exports: ["QmlTypeRegistrarTest/JavaScriptExtension 1.0"]
+ exportMetaObjectRevisions: [256]
+ })"));
+}
+
+void tst_qmltyperegistrar::relatedAddedInVersion()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "AddedIn1_0"
+ accessSemantics: "reference"
+ prototype: "AddedIn1_5"
+ exports: [
+ "QmlTypeRegistrarTest/AddedIn1_0 1.0",
+ "QmlTypeRegistrarTest/AddedIn1_0 1.5"
+ ]
+ exportMetaObjectRevisions: [256, 261]
+ })"));
+}
+
+void tst_qmltyperegistrar::longNumberTypes()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "LongNumberTypes"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["QmlTypeRegistrarTest/LongNumberTypes 1.0"]
+ exportMetaObjectRevisions: [256]
+ Property { name: "a"; type: "qlonglong"; index: 0 }
+ Property { name: "b"; type: "qlonglong"; index: 1 }
+ Property { name: "c"; type: "qulonglong"; index: 2 }
+ Property { name: "d"; type: "qulonglong"; index: 3 }
+ })"));
+}
+
+void tst_qmltyperegistrar::enumList() {
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "QList<NetworkManager::NM>"
+ accessSemantics: "sequence"
+ valueType: "NetworkManager::NM"
+ })"));
+}
+
+void tst_qmltyperegistrar::constReturnType()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "ConstInvokable"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["QmlTypeRegistrarTest/ConstInvokable 1.0"]
+ exportMetaObjectRevisions: [256]
+ Method { name: "getObject"; type: "QObject"; isPointer: true; isTypeConstant: true }
+ })"));
+}
+
+void tst_qmltyperegistrar::usingDeclaration()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "WithMyInt"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["QmlTypeRegistrarTest/WithMyInt 1.0"]
+ exportMetaObjectRevisions: [256]
+ Property { name: "a"; type: "int"; read: "a"; index: 0; isReadonly: true; isPropertyConstant: true }
+ })"));
+}
+
+void tst_qmltyperegistrar::enumsRegistered()
+{
+ QCOMPARE(QMetaType::fromName("SizeEnums::Unit"), QMetaType::fromType<SizeEnums::Unit>());
+ QCOMPARE(QMetaType::fromName("Local::Flag"), QMetaType::fromType<Local::Flag>());
+ QCOMPARE(QMetaType::fromName("Local::Flags"), QMetaType::fromType<Local::Flags>());
+ QCOMPARE(QMetaType::fromName("ValueTypeWithEnum1::Quality"),
+ QMetaType::fromType<ValueTypeWithEnum1::Quality>());
+ QCOMPARE(QMetaType::fromName("ValueTypeWithEnum2::Quality"),
+ QMetaType::fromType<ValueTypeWithEnum2::Quality>());
+ QCOMPARE(QMetaType::fromName("BaseNamespace::BBB"), QMetaType::fromType<BaseNamespace::BBB>());
+ QCOMPARE(QMetaType::fromName("ExtensionValueType::EEE"),
+ QMetaType::fromType<ExtensionValueType::EEE>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::UChar"), QMetaType::fromType<TypedEnum::UChar>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::Int8_T"), QMetaType::fromType<TypedEnum::Int8_T>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::UInt8_T"), QMetaType::fromType<TypedEnum::UInt8_T>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::Int16_T"), QMetaType::fromType<TypedEnum::Int16_T>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::UInt16_T"), QMetaType::fromType<TypedEnum::UInt16_T>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::Int32_T"), QMetaType::fromType<TypedEnum::Int32_T>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::UInt32_T"), QMetaType::fromType<TypedEnum::UInt32_T>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::S"), QMetaType::fromType<TypedEnum::S>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::T"), QMetaType::fromType<TypedEnum::T>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::U"), QMetaType::fromType<TypedEnum::U>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::V"), QMetaType::fromType<TypedEnum::V>());
+ QCOMPARE(QMetaType::fromName("NetworkManager::NM"), QMetaType::fromType<NetworkManager::NM>());
+ QCOMPARE(QMetaType::fromName("NotNamespace::Abc"), QMetaType::fromType<NotNamespace::Abc>());
+}
+
+void tst_qmltyperegistrar::doNotDuplicateQtNamespace()
+{
+ QVERIFY(!qmltypesData.contains(R"(file: "qnamespace.h")"));
+}
+
+void tst_qmltyperegistrar::slotsBeforeInvokables()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "SlotsBeforeInvokables"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Method { name: "bar" }
+ Method { name: "foo" }
+ Method { name: "baz" }
+ })"));
+}
+
QTEST_MAIN(tst_qmltyperegistrar)
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
index df755472d7..1eff2af024 100644
--- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
@@ -1,46 +1,50 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TST_QMLTYPEREGISTRAR_H
#define TST_QMLTYPEREGISTRAR_H
#include "foreign.h"
-#include "foreign_p.h"
+#include "private/foreign_p.h"
-#include <QtQml/qqml.h>
-#include <QtQml/qqmlcomponent.h>
-#include <QtCore/qproperty.h>
-#include <QtCore/qtimeline.h>
-#include <QtCore/qrect.h>
#include <QtQmlTypeRegistrar/private/qqmltyperegistrar_p.h>
-#include <QtCore/qtemporaryfile.h>
#ifdef QT_QUICK_LIB
# include <QtQuick/qquickitem.h>
#endif
-class Interface {};
+#include <QtQml/qqml.h>
+#include <QtQml/qqmlcomponent.h>
+
+#include <QtCore/qabstractitemmodel.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore/qproperty.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qtemporaryfile.h>
+#include <QtCore/qtimeline.h>
+
+class Interface1 {};
class Interface2 {};
class Interface3 {};
QT_BEGIN_NAMESPACE
-Q_DECLARE_INTERFACE(Interface, "io.qt.bugreports.Interface");
+Q_DECLARE_INTERFACE(Interface1, "io.qt.bugreports.Interface1");
Q_DECLARE_INTERFACE(Interface2, "io.qt.bugreports.Interface2");
Q_DECLARE_INTERFACE(Interface3, "io.qt.bugreports.Interface3");
QT_END_NAMESPACE
-class ImplementsInterfaces : public QObject, public Interface
+class ImplementsInterfaces : public QObject, public Interface1
{
Q_OBJECT
QML_ELEMENT
- QML_IMPLEMENTS_INTERFACES(Interface)
+ QML_IMPLEMENTS_INTERFACES(Interface1)
};
-class ImplementsInterfaces2 : public QObject, public Interface, public Interface2
+class ImplementsInterfaces2 : public QObject, public Interface1, public Interface2
{
Q_OBJECT
QML_ELEMENT
- QML_IMPLEMENTS_INTERFACES(Interface Interface2)
+ QML_IMPLEMENTS_INTERFACES(Interface1 Interface2)
};
class ExcessiveVersion : public QObject
@@ -458,6 +462,29 @@ public:
int revisioned() const { return 24; }
};
+class AddedInLateMinorVersion : public QObject
+{
+ Q_OBJECT
+ QML_ADDED_IN_VERSION(1, 5)
+ Q_PROPERTY(int revisioned READ revisioned CONSTANT)
+ QML_NAMED_ELEMENT(MinorVersioned)
+public:
+ AddedInLateMinorVersion(QObject *parent = nullptr) : QObject(parent) {}
+ int revisioned() const { return 123; }
+};
+
+class RemovedInLateMinorVersion : public QObject
+{
+ Q_OBJECT
+ QML_ADDED_IN_VERSION(1, 2)
+ QML_REMOVED_IN_VERSION(1, 4)
+ Q_PROPERTY(int revisioned READ revisioned CONSTANT)
+ QML_NAMED_ELEMENT(MinorVersioned)
+public:
+ RemovedInLateMinorVersion(QObject *parent = nullptr) : QObject(parent) { }
+ int revisioned() const { return 456; }
+};
+
class RemovedInEarlyVersion : public AddedInLateVersion
{
Q_OBJECT
@@ -468,6 +495,23 @@ public:
RemovedInEarlyVersion(QObject *parent = nullptr) : AddedInLateVersion(parent) {}
};
+class AddedIn1_5 : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_ADDED_IN_VERSION(1, 5)
+};
+
+// Slightly absurd. The reason for such a thing may be a change in the versioning
+// scheme of the base class. We still have to retain all of the version information
+// so that you can at least use version 1.5.
+class AddedIn1_0 : public AddedIn1_5
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_ADDED_IN_VERSION(1, 0)
+};
+
class HasResettableProperty : public QObject
{
Q_OBJECT
@@ -501,6 +545,293 @@ signals:
void clonedSignal(int i = 7);
};
+class Unconstructible
+{
+ Q_GADGET
+ QML_VALUE_TYPE(unconstructible)
+ int m_i = 11;
+};
+
+class Constructible
+{
+ Q_GADGET
+ QML_VALUE_TYPE(constructible)
+ QML_CONSTRUCTIBLE_VALUE
+public:
+ Q_INVOKABLE Constructible(int i = 12) : m_i(i) {}
+
+private:
+ int m_i;
+};
+
+class Structured
+{
+ Q_GADGET
+ QML_VALUE_TYPE(structured)
+ QML_STRUCTURED_VALUE
+ Q_PROPERTY(int i MEMBER m_i FINAL)
+
+private:
+ int m_i;
+};
+
+class AnonymousAndUncreatable : public QObject
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+ QML_UNCREATABLE("Pointless uncreatable message")
+};
+
+class Invisible : public QObject
+{
+};
+
+struct InvisibleForeign
+{
+ Q_GADGET
+ QML_FOREIGN(Invisible)
+ QML_NAMED_ELEMENT(Invisible)
+};
+
+class TypedEnum : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ enum UChar: uchar { V0 = 41 };
+ Q_ENUM(UChar)
+ enum Int8_T: int8_t { V1 = 42 };
+ Q_ENUM(Int8_T)
+ enum UInt8_T: uint8_t { V2 = 43 };
+ Q_ENUM(UInt8_T)
+ enum Int16_T: int16_t { V3 = 44 };
+ Q_ENUM(Int16_T)
+ enum UInt16_T: uint16_t { V4 = 45 };
+ Q_ENUM(UInt16_T)
+ enum Int32_T: int32_t { V5 = 46 };
+ Q_ENUM(Int32_T)
+ enum UInt32_T: uint32_t { V6 = 47 };
+ Q_ENUM(UInt32_T)
+
+ // TODO: We cannot handle 64bit numbers as underlying types for enums.
+ // Luckily, moc generates bad code for those. So we don't have to, for now.
+
+ enum S: qint16 {
+ A, B, C
+ };
+ Q_ENUM(S)
+
+ enum T: quint16 {
+ D, E, F
+ };
+ Q_ENUM(T)
+
+ enum U: qint8 {
+ G, H, I
+ };
+ Q_ENUM(U)
+
+ enum V: quint8 {
+ J, K, L
+ };
+ Q_ENUM(V)
+};
+
+class ListSignal : public QObject
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+
+Q_SIGNALS:
+ void objectListHappened(const QList<QObject *> &);
+};
+
+class Bar : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int outerBarProp READ bar CONSTANT)
+public:
+ Bar(QObject *parent = nullptr) : QObject(parent) {}
+ int bar() const { return 44; }
+};
+
+namespace Testing {
+
+class Foo : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int fooProp READ foo CONSTANT)
+
+public:
+ int foo() const { return 42; }
+};
+
+class Bar : public Foo
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(int barProp READ bar CONSTANT)
+
+public:
+ int bar() const { return 43; }
+};
+
+namespace Inner {
+
+class Baz : public Bar
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ QML_EXTENDED(::Bar)
+ QML_ATTACHED(Foo)
+
+public:
+ static Foo *qmlAttachedProperties(QObject *) { return new Foo; }
+};
+
+} // namespace Inner
+} // namespace Testing
+
+struct QByteArrayStdVectorForeign
+{
+ Q_GADGET
+ QML_ANONYMOUS
+ QML_SEQUENTIAL_CONTAINER(QByteArray)
+ QML_FOREIGN(std::vector<QByteArray>)
+};
+
+// Anonymous value type for an unknown foreign type
+struct QPersistentModelIndexValueType
+{
+ QPersistentModelIndex v;
+ Q_PROPERTY(int row READ row FINAL)
+ Q_GADGET
+ QML_ANONYMOUS
+ QML_EXTENDED(QPersistentModelIndexValueType)
+ QML_FOREIGN(QPersistentModelIndex)
+
+public:
+ inline int row() const { return v.row(); }
+};
+
+
+namespace NetworkManager {
+Q_NAMESPACE
+
+enum NM { A, B, C};
+Q_ENUM_NS(NM)
+}
+
+struct NMForeign
+{
+ Q_GADGET
+ QML_NAMED_ELEMENT(NetworkManager)
+ QML_FOREIGN_NAMESPACE(NetworkManager)
+};
+
+struct NotNamespace {
+ Q_GADGET
+public:
+ enum Abc {
+ A, B, C, D
+ };
+ Q_ENUM(Abc);
+};
+
+struct NotNamespaceForeign {
+ Q_GADGET
+ QML_FOREIGN_NAMESPACE(NotNamespace)
+ QML_ELEMENT
+};
+
+class NameExplosion : public QObject
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(Name1)
+ QML_NAMED_ELEMENT(Name2)
+ QML_ELEMENT
+ QML_ANONYMOUS
+};
+
+class JavaScriptExtension : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_CLASSINFO("QML.Extended", "SymbolPrototype")
+ Q_CLASSINFO("QML.ExtensionIsJavaScript", "true")
+};
+
+class LongNumberTypes : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(qint64 a MEMBER m_a)
+ Q_PROPERTY(int64_t b MEMBER m_b)
+ Q_PROPERTY(quint64 c MEMBER m_c)
+ Q_PROPERTY(uint64_t d MEMBER m_d)
+
+ qint64 m_a = 1;
+ int64_t m_b = 2;
+ quint64 m_c = 3;
+ uint64_t m_d = 4;
+};
+
+struct EnumList
+{
+ Q_GADGET
+ QML_ANONYMOUS
+ QML_FOREIGN(QList<NetworkManager::NM>)
+ QML_SEQUENTIAL_CONTAINER(NetworkManager::NM)
+};
+
+class ConstInvokable : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ Q_INVOKABLE const QObject *getObject() { return nullptr; }
+};
+
+using myint = int;
+
+struct IntAlias
+{
+ Q_GADGET
+ QML_FOREIGN(myint)
+ QML_USING(int);
+};
+
+class WithMyInt : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(myint a READ a CONSTANT)
+public:
+ myint a() const { return 10; }
+};
+
+class UsesQtNamespace : public QObject
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+ Q_PROPERTY(Qt::Key key READ key CONSTANT)
+public:
+ Qt::Key key() const { return Qt::Key_Escape; }
+};
+
+class SlotsBeforeInvokables : public QObject
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+public:
+ Q_INVOKABLE void foo() {}
+public Q_SLOTS:
+ void bar() {}
+public:
+ Q_INVOKABLE void baz() {}
+};
+
class tst_qmltyperegistrar : public QObject
{
Q_OBJECT
@@ -537,6 +868,7 @@ private slots:
void methodReturnType();
void hasIsConstantInParameters();
void uncreatable();
+ void singletonVersions();
#ifdef QT_QUICK_LIB
void foreignRevisionedProperty();
@@ -544,11 +876,39 @@ private slots:
void addRemoveVersion_data();
void addRemoveVersion();
+ void addInMinorVersion();
void typeInModuleMajorVersionZero();
void resettableProperty();
void duplicateExportWarnings();
void clonedSignal();
void baseVersionInQmltypes();
+ void unconstructibleValueType();
+ void constructibleValueType();
+ void structuredValueType();
+ void anonymousAndUncreatable();
+ void omitInvisible();
+ void typedEnum();
+ void listSignal();
+ void withNamespace();
+ void sequenceRegistration();
+ void valueTypeSelfReference();
+ void foreignNamespaceFromGadget();
+
+ void nameExplosion_data();
+ void nameExplosion();
+
+ void javaScriptExtension();
+
+ void consistencyWarnings();
+ void relatedAddedInVersion();
+ void longNumberTypes();
+ void enumList();
+ void constReturnType();
+
+ void usingDeclaration();
+ void enumsRegistered();
+ void doNotDuplicateQtNamespace();
+ void slotsBeforeInvokables();
private:
QByteArray qmltypesData;
diff --git a/tests/auto/qml/qqmlanybinding/CMakeLists.txt b/tests/auto/qml/qqmlanybinding/CMakeLists.txt
index 8cdecae3a8..f80acd8187 100644
--- a/tests/auto/qml/qqmlanybinding/CMakeLists.txt
+++ b/tests/auto/qml/qqmlanybinding/CMakeLists.txt
@@ -5,6 +5,12 @@
## tst_qqmlanybinding Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlanybinding LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlanybinding/tst_qqmlanybinding.cpp b/tests/auto/qml/qqmlanybinding/tst_qqmlanybinding.cpp
index 9e2ba24969..7e0a1c659a 100644
--- a/tests/auto/qml/qqmlanybinding/tst_qqmlanybinding.cpp
+++ b/tests/auto/qml/qqmlanybinding/tst_qqmlanybinding.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/QQmlEngine>
#include <QtQml/QQmlComponent>
#include <QtCore/QScopedPointer>
@@ -39,7 +39,7 @@ static int getRefCount(const QQmlAnyBinding &binding)
} else {
// this temporarily adds a refcount because we construc a new untypedpropertybinding
// thus -1
- return QPropertyBindingPrivate::get(binding.asUntypedPropertyBinding())->ref - 1;
+ return QPropertyBindingPrivate::get(binding.asUntypedPropertyBinding())->refCount() - 1;
}
}
diff --git a/tests/auto/qml/qqmlanybinding/withbindable.h b/tests/auto/qml/qqmlanybinding/withbindable.h
index 0672532344..322459f991 100644
--- a/tests/auto/qml/qqmlanybinding/withbindable.h
+++ b/tests/auto/qml/qqmlanybinding/withbindable.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef WITH_BINDABLE_H
#define WITH_BINDABLE_H
diff --git a/tests/auto/qml/qqmlapplicationengine/CMakeLists.txt b/tests/auto/qml/qqmlapplicationengine/CMakeLists.txt
index 0570b9a95c..3b02ed09ef 100644
--- a/tests/auto/qml/qqmlapplicationengine/CMakeLists.txt
+++ b/tests/auto/qml/qqmlapplicationengine/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlapplicationengine Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlapplicationengine LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -57,5 +63,12 @@ qt_internal_extend_target(tst_qqmlapplicationengine CONDITION NOT ANDROID AND NO
DEFINES
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
)
+
add_subdirectory(testapp)
add_subdirectory(androidassets)
+add_dependencies(tst_qqmlapplicationengine testapp)
+
+add_subdirectory(loadFromModuleTranslationsQmlType)
+add_subdirectory(loadFromModuleTranslationsCppType)
+add_dependencies(tst_qqmlapplicationengine i18nLoadFromModuleQmlType)
+add_dependencies(tst_qqmlapplicationengine i18nLoadFromModuleCppType)
diff --git a/tests/auto/qml/qqmlapplicationengine/androidassets/CMakeLists.txt b/tests/auto/qml/qqmlapplicationengine/androidassets/CMakeLists.txt
index c5d42ed9c4..eca18010ee 100644
--- a/tests/auto/qml/qqmlapplicationengine/androidassets/CMakeLists.txt
+++ b/tests/auto/qml/qqmlapplicationengine/androidassets/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_androidassets LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_androidassets
SOURCES
tst_androidassets.cpp
diff --git a/tests/auto/qml/qqmlapplicationengine/androidassets/tst_androidassets.cpp b/tests/auto/qml/qqmlapplicationengine/androidassets/tst_androidassets.cpp
index 7a6774c268..ed55afc693 100644
--- a/tests/auto/qml/qqmlapplicationengine/androidassets/tst_androidassets.cpp
+++ b/tests/auto/qml/qqmlapplicationengine/androidassets/tst_androidassets.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlapplicationengine.h>
#include <QtTest/qsignalspy.h>
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/CMakeLists.txt b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/CMakeLists.txt
new file mode 100644
index 0000000000..f6fa23e010
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/CMakeLists.txt
@@ -0,0 +1,30 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_standard_project_setup(REQUIRES 6.5 I18N_LANGUAGES es)
+
+qt_internal_add_executable(i18nLoadFromModuleCppType
+ OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
+ SOURCES
+ main.cpp
+ LIBRARIES
+ Qt::Gui
+ Qt::Qml
+)
+
+qt_add_qml_module(i18nLoadFromModuleCppType
+ URI TranslatedCpp
+ QML_FILES Main.qml
+)
+
+qt_internal_extend_target(i18nLoadFromModuleCppType
+ ENABLE_AUTOGEN_TOOLS
+ uic
+)
+
+qt_add_resources(i18nLoadFromModuleCppType "loadFromModuleCppTypeQmFile"
+ PREFIX
+ /qt/qml/TranslatedCpp/
+ FILES
+ i18n/qml_es.qm
+)
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/Main.qml b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/Main.qml
new file mode 100644
index 0000000000..f1d2010837
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/Main.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ Component.onCompleted: Qt.exit(0)
+}
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.qm b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.qm
new file mode 100644
index 0000000000..e35ee63f89
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.qm
Binary files differ
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.ts b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.ts
new file mode 100644
index 0000000000..f8d478f056
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.ts
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="es_ES">
+<context>
+ <name>QObject</name>
+ <message>
+ <location filename="../main.cpp" line="17"/>
+ <source>Hello</source>
+ <translation>Hola</translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/main.cpp b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/main.cpp
new file mode 100644
index 0000000000..326a1397dc
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/main.cpp
@@ -0,0 +1,26 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+
+int main(int argc, char *argv[])
+{
+ QLocale::setDefault(QLocale(QLocale::Language(qEnvironmentVariableIntValue("qtlang"))));
+ QGuiApplication app(argc, argv);
+ QQmlApplicationEngine engine;
+
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
+ &app, []() { QCoreApplication::exit(-1); },
+ Qt::QueuedConnection);
+ engine.loadFromModule("TranslatedCpp", "Main");
+ app.exec();
+
+ QString expected = qgetenv("LOADFROMMODULE_TEST_EXPECTED_OUTPUT");
+ QString actual = QObject::tr("Hello");
+
+ if (actual == expected)
+ return 0;
+
+ return actual[0].toLatin1();
+}
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/CMakeLists.txt b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/CMakeLists.txt
new file mode 100644
index 0000000000..088648040d
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/CMakeLists.txt
@@ -0,0 +1,30 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_standard_project_setup(REQUIRES 6.5 I18N_LANGUAGES fr)
+
+qt_internal_add_executable(i18nLoadFromModuleQmlType
+ OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
+ SOURCES
+ main.cpp
+ LIBRARIES
+ Qt::Gui
+ Qt::Qml
+)
+
+qt_add_qml_module(i18nLoadFromModuleQmlType
+ URI TranslatedQml
+ QML_FILES Main.qml
+)
+
+qt_internal_extend_target(i18nLoadFromModuleQmlType
+ ENABLE_AUTOGEN_TOOLS
+ uic
+)
+
+qt_add_resources(i18nLoadFromModuleQmlType "loadFromModuleQmlTypeQmFile"
+ PREFIX
+ /qt/qml/TranslatedQml/
+ FILES
+ i18n/qml_fr.qm
+)
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/Main.qml b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/Main.qml
new file mode 100644
index 0000000000..9f8e1984e9
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/Main.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+QtObject {
+ property string expected: "placeholder"
+ property string actual: qsTr("Hello")
+
+ function f() {
+ if (expected === actual)
+ Qt.exit(0)
+ else
+ Qt.exit(actual.charCodeAt(0))
+ }
+}
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.qm b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.qm
new file mode 100644
index 0000000000..a53cf121a2
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.qm
Binary files differ
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.ts b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.ts
new file mode 100644
index 0000000000..87b46be9ca
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.ts
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fr_FR">
+<context>
+ <name>Main</name>
+ <message>
+ <location filename="../Main.qml" line="5"/>
+ <source>Hello</source>
+ <translation>Salut</translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/main.cpp b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/main.cpp
new file mode 100644
index 0000000000..6f28ec8148
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/main.cpp
@@ -0,0 +1,23 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+
+int main(int argc, char *argv[])
+{
+ QLocale::setDefault(QLocale(QLocale::Language(qEnvironmentVariableIntValue("qtlang"))));
+ QGuiApplication app(argc, argv);
+ QQmlApplicationEngine engine;
+
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
+ &app, []() { QCoreApplication::exit(-1); },
+ Qt::QueuedConnection);
+ engine.loadFromModule("TranslatedQml", "Main");
+
+ QString expected = qgetenv("LOADFROMMODULE_TEST_EXPECTED_OUTPUT");
+ auto *root = engine.rootObjects().first();
+ root->setProperty("expected", expected);
+ root->metaObject()->invokeMethod(root, "f");
+ return app.exec();
+}
diff --git a/tests/auto/qml/qqmlapplicationengine/testapp/main.cpp b/tests/auto/qml/qqmlapplicationengine/testapp/main.cpp
index 468c8428ba..6ccd256cca 100644
--- a/tests/auto/qml/qqmlapplicationengine/testapp/main.cpp
+++ b/tests/auto/qml/qqmlapplicationengine/testapp/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Research In Motion.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QCoreApplication>
#include <QQmlApplicationEngine>
diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
index 5774b68c32..3bf83d81e1 100644
--- a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
+++ b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Research In Motion.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QQmlApplicationEngine>
#include <QScopedPointer>
@@ -28,6 +28,8 @@ private slots:
void removeObjectsWhenDestroyed();
void loadTranslation_data();
void loadTranslation();
+ void loadFromModuleTranslation_data();
+ void loadFromModuleTranslation();
void translationChange();
void setInitialProperties();
void failureToLoadTriggersWarningSignal();
@@ -144,7 +146,7 @@ void tst_qqmlapplicationengine::application()
#if QT_CONFIG(process)
QDir::setCurrent(buildDir);
- QProcess *testProcess = new QProcess(this);
+ std::unique_ptr<QProcess> testProcess = std::make_unique<QProcess>(this);
#ifdef Q_OS_QNX
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert("QT_FORCE_STDERR_LOGGING", "1"); // QTBUG-76546
@@ -164,7 +166,7 @@ void tst_qqmlapplicationengine::application()
QVERIFY2(QString(testStdErr).endsWith(QString(expectedStdErr)),
QByteArray("\nExpected ending:\n") + expectedStdErr
+ QByteArray("\nActual output:\n") + testStdErr);
- delete testProcess;
+ testProcess.reset();
QDir::setCurrent(srcDir);
#else // process
QSKIP("No process support");
@@ -191,7 +193,7 @@ void tst_qqmlapplicationengine::applicationProperties()
QCoreApplication::setOrganizationName(firstOrganization);
QCoreApplication::setOrganizationDomain(firstDomain);
- QQmlApplicationEngine *test = new QQmlApplicationEngine(testFileUrl("applicationTest.qml"));
+ std::unique_ptr<QQmlApplicationEngine> test = std::make_unique<QQmlApplicationEngine>(testFileUrl("applicationTest.qml"));
QObject* root = test->rootObjects().at(0);
QVERIFY(root);
QCOMPARE(root->property("originalName").toString(), firstName);
@@ -223,8 +225,6 @@ void tst_qqmlapplicationengine::applicationProperties()
QCOMPARE(versionChanged.size(), 1);
QCOMPARE(organizationChanged.size(), 1);
QCOMPARE(domainChanged.size(), 1);
-
- delete test;
}
void tst_qqmlapplicationengine::removeObjectsWhenDestroyed()
@@ -268,6 +268,53 @@ void tst_qqmlapplicationengine::loadTranslation()
QCOMPARE(rootObject->property("translation").toString(), translation);
}
+void tst_qqmlapplicationengine::loadFromModuleTranslation_data()
+{
+ QTest::addColumn<QString>("executable");
+ QTest::addColumn<QLocale::Language>("LANG");
+ QTest::addColumn<QString>("output");
+
+ QString qmlTypeExecutable = "loadFromModuleTranslationsQmlType/i18nLoadFromModuleQmlType";
+ QString cppTypeExecutable = "loadFromModuleTranslationsCppType/i18nLoadFromModuleCppType";
+
+ QTest::newRow("Qml: en -> en") << qmlTypeExecutable << QLocale::English << "Hello";
+ QTest::newRow("Qml: en -> fr") << qmlTypeExecutable << QLocale::French << "Salut";
+ QTest::newRow("Cpp: en -> en") << cppTypeExecutable << QLocale::English << "Hello";
+ QTest::newRow("Cpp: en -> es") << cppTypeExecutable << QLocale::Spanish << "Hola";
+}
+
+void tst_qqmlapplicationengine::loadFromModuleTranslation()
+{
+#if defined(Q_OS_ANDROID)
+ QSKIP("Test doesn't currently run on Android");
+ return;
+#endif
+
+#if QT_CONFIG(process)
+ QFETCH(QString, executable);
+ QFETCH(QLocale::Language, LANG);
+ QFETCH(QString, output);
+
+ QDir::setCurrent(buildDir);
+ QProcess app;
+ auto env = QProcessEnvironment::systemEnvironment();
+ env.insert("qtlang", QString::number(int(LANG)));
+ env.insert("LOADFROMMODULE_TEST_EXPECTED_OUTPUT", output);
+ app.setProcessEnvironment(env);
+ app.start(executable);
+ QVERIFY(app.waitForStarted());
+ QVERIFY(app.waitForFinished());
+
+ auto status = app.exitStatus();
+ auto code = app.exitCode();
+ QVERIFY2(code == 0,
+ QStringLiteral("status: %1, exitCode: %2").arg(status).arg(code).toStdString().c_str());
+ app.kill();
+#else
+ QSKIP("No process support");
+#endif
+}
+
void tst_qqmlapplicationengine::translationChange()
{
if (QLocale().language() == QLocale::SwissGerman) {
diff --git a/tests/auto/qml/qqmlbinding/CMakeLists.txt b/tests/auto/qml/qqmlbinding/CMakeLists.txt
index bcddd51730..0249bb0f25 100644
--- a/tests/auto/qml/qqmlbinding/CMakeLists.txt
+++ b/tests/auto/qml/qqmlbinding/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlbinding Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlbinding LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -22,9 +28,27 @@ qt_internal_add_test(tst_qqmlbinding
Qt::Gui
Qt::GuiPrivate
Qt::QmlPrivate
+ Qt::QmlMetaPrivate
+ Qt::QuickPrivate
+ Qt::QuickTestUtilsPrivate
+ TESTDATA ${test_data}
+)
+
+qt_internal_add_test(tst_qqmlbinding_no_deferred_properties
+ SOURCES
+ tst_qqmlbinding.cpp
+ WithBindableProperties.h
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::Gui
+ Qt::GuiPrivate
+ Qt::QmlPrivate
+ Qt::QmlMetaPrivate
Qt::QuickPrivate
Qt::QuickTestUtilsPrivate
TESTDATA ${test_data}
+ DEFINES
+ QML_DISABLE_INTERNAL_DEFERRED_PROPERTIES
)
set_target_properties(tst_qqmlbinding PROPERTIES
@@ -34,9 +58,13 @@ set_target_properties(tst_qqmlbinding PROPERTIES
_qt_internal_qml_type_registration(tst_qqmlbinding)
+set_target_properties(tst_qqmlbinding_no_deferred_properties PROPERTIES
+ QT_QML_MODULE_URI "test"
+ QT_QML_MODULE_VERSION 1.0
+)
+
+_qt_internal_qml_type_registration(tst_qqmlbinding_no_deferred_properties)
-## Scopes:
-#####################################################################
qt_internal_extend_target(tst_qqmlbinding CONDITION ANDROID OR IOS
DEFINES
@@ -47,3 +75,13 @@ qt_internal_extend_target(tst_qqmlbinding CONDITION NOT ANDROID AND NOT IOS
DEFINES
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
)
+
+qt_internal_extend_target(tst_qqmlbinding_no_deferred_properties CONDITION ANDROID OR IOS
+ DEFINES
+ QT_QMLTEST_DATADIR=":/data"
+)
+
+qt_internal_extend_target(tst_qqmlbinding_no_deferred_properties CONDITION NOT ANDROID AND NOT IOS
+ DEFINES
+ QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+)
diff --git a/tests/auto/qml/qqmlbinding/WithBindableProperties.h b/tests/auto/qml/qqmlbinding/WithBindableProperties.h
index 17fa3cd9b3..8837098d81 100644
--- a/tests/auto/qml/qqmlbinding/WithBindableProperties.h
+++ b/tests/auto/qml/qqmlbinding/WithBindableProperties.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef WithBindableProperties_H
#define WithBindableProperties_H
diff --git a/tests/auto/qml/qqmlbinding/data/bindingOverwriting2.qml b/tests/auto/qml/qqmlbinding/data/bindingOverwriting2.qml
new file mode 100644
index 0000000000..8d15185506
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/bindingOverwriting2.qml
@@ -0,0 +1,21 @@
+pragma ComponentBehavior: Bound
+import QtQuick
+
+ListView {
+ id: list
+ property int i: 0
+
+ model: 1
+ delegate: Item {
+ id: cellRootID
+ required property int index
+ Timer {
+ interval: 1
+ running: true
+ onTriggered: {
+ cellRootID.index = index + 123
+ list.i = cellRootID.index
+ }
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/data/propertiesAttachedToBindingItself.qml b/tests/auto/qml/qqmlbinding/data/propertiesAttachedToBindingItself.qml
new file mode 100644
index 0000000000..98b3aa6606
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/propertiesAttachedToBindingItself.qml
@@ -0,0 +1,18 @@
+import QtQml.Models
+import QtQuick
+
+Instantiator {
+ id: inst
+ model: 1
+ property int check: 0
+
+ delegate: Binding {
+ ListView.delayRemove: true
+ Component.onCompleted: inst.check += 1
+ }
+
+ Component.onCompleted: {
+ if (inst.objectAt(0))
+ inst.check += 2
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/data/restoreBinding2.qml b/tests/auto/qml/qqmlbinding/data/restoreBinding2.qml
index 8d89989613..40d4806b8c 100644
--- a/tests/auto/qml/qqmlbinding/data/restoreBinding2.qml
+++ b/tests/auto/qml/qqmlbinding/data/restoreBinding2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQml 2.14
diff --git a/tests/auto/qml/qqmlbinding/data/restoreBinding3.qml b/tests/auto/qml/qqmlbinding/data/restoreBinding3.qml
index 9fd5fc77d0..5742a849b9 100644
--- a/tests/auto/qml/qqmlbinding/data/restoreBinding3.qml
+++ b/tests/auto/qml/qqmlbinding/data/restoreBinding3.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQml 2.14
diff --git a/tests/auto/qml/qqmlbinding/data/restoreBinding4.qml b/tests/auto/qml/qqmlbinding/data/restoreBinding4.qml
index ee183a0d10..e9d90b5e8b 100644
--- a/tests/auto/qml/qqmlbinding/data/restoreBinding4.qml
+++ b/tests/auto/qml/qqmlbinding/data/restoreBinding4.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQml 2.14
diff --git a/tests/auto/qml/qqmlbinding/data/toggleEnableProperlyRemembersValues.qml b/tests/auto/qml/qqmlbinding/data/toggleEnableProperlyRemembersValues.qml
new file mode 100644
index 0000000000..251e71f771
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/toggleEnableProperlyRemembersValues.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+QtObject {
+ id: root
+ property bool enabled: false
+ property var func: function() { return 1 }
+ property var arr: [1, 2]
+ property Binding b: Binding {
+ root.func: function() { return 2 };
+ root.arr: [1, 2, 3]
+ when: root.enabled
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/data/whenEvaluatedEarlyEnough.qml b/tests/auto/qml/qqmlbinding/data/whenEvaluatedEarlyEnough.qml
new file mode 100644
index 0000000000..6245270e14
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/whenEvaluatedEarlyEnough.qml
@@ -0,0 +1,23 @@
+import QtQuick
+
+Item {
+ id: root
+ property bool toggle: true
+ property bool forceEnable: false
+
+ Item {
+ id: item1
+ property int i
+ }
+
+ Item {
+ id: item2
+ }
+
+ Binding {
+ target: root.toggle ? item1 : item2
+ when: root.forceEnable || (root.toggle ? item1 : item2).hasOwnProperty("i")
+ property: "i"
+ value: 42
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
index c78763cf5f..b13379a103 100644
--- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
+++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
@@ -1,13 +1,17 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <qtest.h>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "WithBindableProperties.h"
+
+#include <private/qmlutils_p.h>
+#include <private/qqmlbind_p.h>
+#include <private/qqmlcomponentattached_p.h>
+#include <private/qquickrectangle_p.h>
+
+#include <QtTest/qtest.h>
+
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
-#include <QtQml/private/qqmlbind_p.h>
-#include <QtQml/private/qqmlcomponentattached_p.h>
-#include <QtQuick/private/qquickrectangle_p.h>
-#include <QtQuickTestUtils/private/qmlutils_p.h>
-#include "WithBindableProperties.h"
class tst_qqmlbinding : public QQmlDataTest
{
@@ -38,6 +42,9 @@ private slots:
void intOverflow();
void generalizedGroupedProperties();
void localSignalHandler();
+ void whenEvaluatedEarlyEnough();
+ void propertiesAttachedToBindingItself();
+ void toggleEnableProperlyRemembersValues();
private:
QQmlEngine engine;
@@ -46,6 +53,9 @@ private:
tst_qqmlbinding::tst_qqmlbinding()
: QQmlDataTest(QT_QMLTEST_DATADIR)
{
+#ifdef QML_DISABLE_INTERNAL_DEFERRED_PROPERTIES
+ qputenv("QML_DISABLE_INTERNAL_DEFERRED_PROPERTIES", "1");
+#endif
}
void tst_qqmlbinding::binding()
@@ -365,10 +375,6 @@ void tst_qqmlbinding::disabledOnReadonlyProperty()
void tst_qqmlbinding::delayed()
{
-#ifdef Q_OS_ANDROID
- QSKIP("This test crashes on Android. QTBUG-103310");
-#endif
-
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("delayed.qml"));
QScopedPointer<QQuickItem> item {qobject_cast<QQuickItem*>(c.create())};
@@ -455,9 +461,15 @@ void tst_qqmlbinding::bindingOverwriting()
QQmlComponent c(&engine, testFileUrl("bindingOverwriting.qml"));
QScopedPointer<QQuickItem> item {qobject_cast<QQuickItem*>(c.create())};
QVERIFY(item);
+ QCOMPARE(messageHandler.messages().size(), 2);
+
+ QQmlComponent c2(&engine, testFileUrl("bindingOverwriting2.qml"));
+ QScopedPointer<QObject> o(c2.create());
+ QVERIFY(o);
+ QTRY_COMPARE(o->property("i").toInt(), 123);
+ QCOMPARE(messageHandler.messages().size(), 3);
QLoggingCategory::setFilterRules(QString());
- QCOMPARE(messageHandler.messages().size(), 2);
}
void tst_qqmlbinding::bindToQmlComponent()
@@ -593,6 +605,55 @@ void tst_qqmlbinding::localSignalHandler()
QCOMPARE(o->property("output").toString(), QStringLiteral("abc"));
}
+void tst_qqmlbinding::whenEvaluatedEarlyEnough()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("whenEvaluatedEarlyEnough.qml"));
+ QTest::failOnWarning(QRegularExpression(".*"));
+ std::unique_ptr<QObject> root { c.create() };
+ root->setProperty("toggle", false); // should not cause warnings
+ // until "when" is actually true
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg,
+ QRegularExpression(".*QML Binding: Property 'i' does not exist on Item.*"));
+ root->setProperty("forceEnable", true);
+}
+
+void tst_qqmlbinding::propertiesAttachedToBindingItself()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("propertiesAttachedToBindingItself.qml"));
+ QTest::failOnWarning(QRegularExpression(".*"));
+ std::unique_ptr<QObject> root { c.create() };
+ QVERIFY2(root, qPrintable(c.errorString()));
+ // 0 => everything broken; 1 => normal attached properties broken;
+ // 2 => Component.onCompleted broken, 3 => everything works
+ QTRY_COMPARE(root->property("check").toInt(), 3);
+}
+
+void tst_qqmlbinding::toggleEnableProperlyRemembersValues()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("toggleEnableProperlyRemembersValues.qml"));
+ std::unique_ptr<QObject> root { c.create() };
+ QVERIFY2(root, qPrintable(c.errorString()));
+ for (int i = 0; i < 3; ++i) {
+ {
+ QJSManagedValue arr(root->property("arr"), &e);
+ QJSManagedValue func(root->property("func"), &e);
+ QCOMPARE(arr.property("length").toInt(), 2);
+ QCOMPARE(func.call().toInt(), 1);
+ }
+ root->setProperty("enabled", true);
+ {
+ QJSManagedValue arr(root->property("arr"), &e);
+ QJSManagedValue func(root->property("func"), &e);
+ QCOMPARE(arr.property("length").toInt(), 3);
+ QCOMPARE(func.call().toInt(), 2);
+ }
+ root->setProperty("enabled", false);
+ }
+}
+
QTEST_MAIN(tst_qqmlbinding)
#include "tst_qqmlbinding.moc"
diff --git a/tests/auto/qml/qqmlchangeset/CMakeLists.txt b/tests/auto/qml/qqmlchangeset/CMakeLists.txt
index c4038b0eaf..32a20d7edf 100644
--- a/tests/auto/qml/qqmlchangeset/CMakeLists.txt
+++ b/tests/auto/qml/qqmlchangeset/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlchangeset Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlchangeset LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlchangeset
SOURCES
tst_qqmlchangeset.cpp
diff --git a/tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp b/tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp
index 1aec5dcac3..8712d4953d 100644
--- a/tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp
+++ b/tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <qrandom.h>
#include <private/qqmlchangeset_p.h>
@@ -94,7 +95,7 @@ public:
bool applyChanges(QVector<int> &list, const QVector<QVector<Signal> > &changes)
{
- foreach (const SignalList &sl, changes) {
+ for (const SignalList &sl : changes) {
if (!applyChanges(list, sl))
return false;
}
@@ -104,7 +105,7 @@ public:
bool applyChanges(QVector<int> &list, const QVector<Signal> &changes)
{
QHash<QQmlChangeSet::MoveKey, int> removedValues;
- foreach (const Signal &signal, changes) {
+ for (const Signal &signal : changes) {
if (signal.isInsert()) {
if (signal.index < 0 || signal.index > list.size()) {
qDebug() << "insert out of range" << signal.index << list.size();
@@ -1133,7 +1134,7 @@ void tst_qqmlchangeset::sequence()
QQmlChangeSet set;
- foreach (const Signal &signal, input) {
+ for (const Signal &signal : std::as_const(input)) {
if (signal.isRemove())
set.remove(signal.index, signal.count);
else if (signal.isInsert())
@@ -1145,11 +1146,11 @@ void tst_qqmlchangeset::sequence()
}
SignalList changes;
- foreach (const QQmlChangeSet::Change &remove, set.removes())
+ for (const QQmlChangeSet::Change &remove : set.removes())
changes << Remove(remove.index, remove.count, remove.moveId, remove.offset);
- foreach (const QQmlChangeSet::Change &insert, set.inserts())
+ for (const QQmlChangeSet::Change &insert : set.inserts())
changes << Insert(insert.index, insert.count, insert.moveId, insert.offset);
- foreach (const QQmlChangeSet::Change &change, set.changes())
+ for (const QQmlChangeSet::Change &change : set.changes())
changes << Change(change.index, change.count);
VERIFY_EXPECTED_OUTPUT
@@ -1267,9 +1268,9 @@ void tst_qqmlchangeset::apply()
QQmlChangeSet set;
QQmlChangeSet linearSet;
- foreach (const SignalList &list, input) {
+ for (const SignalList &list : std::as_const(input)) {
QQmlChangeSet intermediateSet;
- foreach (const Signal &signal, list) {
+ for (const Signal &signal : list) {
if (signal.isRemove()) {
intermediateSet.remove(signal.index, signal.count);
linearSet.remove(signal.index, signal.count);
@@ -1285,15 +1286,15 @@ void tst_qqmlchangeset::apply()
}
SignalList changes;
- foreach (const QQmlChangeSet::Change &remove, set.removes())
+ for (const QQmlChangeSet::Change &remove : set.removes())
changes << Remove(remove.index, remove.count, remove.moveId, remove.offset);
- foreach (const QQmlChangeSet::Change &insert, set.inserts())
+ for (const QQmlChangeSet::Change &insert : set.inserts())
changes << Insert(insert.index, insert.count, insert.moveId, insert.offset);
SignalList linearChanges;
- foreach (const QQmlChangeSet::Change &remove, linearSet.removes())
+ for (const QQmlChangeSet::Change &remove : linearSet.removes())
linearChanges << Remove(remove.index, remove.count, remove.moveId, remove.offset);
- foreach (const QQmlChangeSet::Change &insert, linearSet.inserts())
+ for (const QQmlChangeSet::Change &insert : linearSet.inserts())
linearChanges << Insert(insert.index, insert.count, insert.moveId, insert.offset);
// The output in the failing tests isn't incorrect, merely sub-optimal.
@@ -1328,7 +1329,7 @@ void tst_qqmlchangeset::removeConsecutive()
QFETCH(SignalList, output);
QVector<QQmlChangeSet::Change> removes;
- foreach (const Signal &signal, input) {
+ for (const Signal &signal : std::as_const(input)) {
QVERIFY(signal.isRemove());
removes.append(QQmlChangeSet::Change(signal.index, signal.count, signal.moveId, signal.offset));
}
@@ -1337,7 +1338,7 @@ void tst_qqmlchangeset::removeConsecutive()
set.remove(removes);
SignalList changes;
- foreach (const QQmlChangeSet::Change &remove, set.removes())
+ for (const QQmlChangeSet::Change &remove : set.removes())
changes << Remove(remove.index, remove.count, remove.moveId, remove.offset);
QVERIFY(set.inserts().isEmpty());
QVERIFY(set.changes().isEmpty());
@@ -1368,7 +1369,7 @@ void tst_qqmlchangeset::insertConsecutive()
QFETCH(SignalList, output);
QVector<QQmlChangeSet::Change> inserts;
- foreach (const Signal &signal, input) {
+ for (const Signal &signal : std::as_const(input)) {
QVERIFY(signal.isInsert());
inserts.append(QQmlChangeSet::Change(signal.index, signal.count, signal.moveId, signal.offset));
}
@@ -1377,7 +1378,7 @@ void tst_qqmlchangeset::insertConsecutive()
set.insert(inserts);
SignalList changes;
- foreach (const QQmlChangeSet::Change &insert, set.inserts())
+ for (const QQmlChangeSet::Change &insert : set.inserts())
changes << Insert(insert.index, insert.count, insert.moveId, insert.offset);
QVERIFY(set.removes().isEmpty());
QVERIFY(set.changes().isEmpty());
@@ -1496,9 +1497,9 @@ void tst_qqmlchangeset::random()
}
SignalList output;
- foreach (const QQmlChangeSet::Change &remove, accumulatedSet.removes())
+ for (const QQmlChangeSet::Change &remove : accumulatedSet.removes())
output << Remove(remove.index, remove.count, remove.moveId, remove.offset);
- foreach (const QQmlChangeSet::Change &insert, accumulatedSet.inserts())
+ for (const QQmlChangeSet::Change &insert : accumulatedSet.inserts())
output << Insert(insert.index, insert.count, insert.moveId, insert.offset);
QVector<int> inputList;
diff --git a/tests/auto/qml/qqmlcomponent/CMakeLists.txt b/tests/auto/qml/qqmlcomponent/CMakeLists.txt
index cab87ac08d..874c7f0cc3 100644
--- a/tests/auto/qml/qqmlcomponent/CMakeLists.txt
+++ b/tests/auto/qml/qqmlcomponent/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlcomponent Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlcomponent LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -36,10 +42,13 @@ if(TARGET Qt::QuickControls2)
target_compile_definitions(tst_qqmlcomponent PRIVATE HAS_CONTROLS)
endif()
+qt_policy(SET QTP0001 NEW)
+
qt_add_qml_module(
tst_qqmlcomponent
+ SOURCES
+ lifecyclewatcher.h
URI test
- AUTO_RESOURCE_PREFIX
QML_FILES
"data/TestComponentWithIC.qml"
"data/withAot.qml"
diff --git a/tests/auto/qml/qqmlcomponent/data/complexObjectArgument.qml b/tests/auto/qml/qqmlcomponent/data/complexObjectArgument.qml
new file mode 100644
index 0000000000..71676a4415
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/complexObjectArgument.qml
@@ -0,0 +1,28 @@
+import QtQml 2.15
+
+QtObject {
+ id: root
+ Component.onCompleted: {
+ function WithPrototype(refMsgSeqNr) {
+ this.init(refMsgSeqNr)
+ };
+
+ WithPrototype.prototype = {
+ init: function(refMsgSeqNr) {
+ this.testObj = {
+ has: function(a) { return a === refMsgSeqNr }
+ }
+
+ this.protocolSubTypeID = 2
+ this.messageControl = 0
+ this.referredMsgSequenceNumber = refMsgSeqNr
+ }
+ };
+
+ let comp = Qt.createComponent("dynamic.qml");
+ let inst1 = comp.createObject(root, { testObj: new Set(), });
+ let inst2 = comp.createObject(root, new WithPrototype(1));
+
+ objectName = inst1.use() + " - " + inst2.use();
+ }
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/createObject.qml b/tests/auto/qml/qqmlcomponent/data/createObject.qml
index afd9e71229..c9ca605f8f 100644
--- a/tests/auto/qml/qqmlcomponent/data/createObject.qml
+++ b/tests/auto/qml/qqmlcomponent/data/createObject.qml
@@ -1,5 +1,4 @@
-import QtQuick 2.0
-import QtQuick.Window 2.0
+import QtQuick
Item {
property QtObject qtobjectParent: QtObject { }
diff --git a/tests/auto/qml/qqmlcomponent/data/createObjectWithScript.qml b/tests/auto/qml/qqmlcomponent/data/createObjectWithScript.qml
index 3391b3a266..63aeb9415e 100644
--- a/tests/auto/qml/qqmlcomponent/data/createObjectWithScript.qml
+++ b/tests/auto/qml/qqmlcomponent/data/createObjectWithScript.qml
@@ -11,6 +11,9 @@ Item{
property QtObject badRequired: null
property QtObject goodRequired: null
+ property QtObject bindingAsInitial: null
+ property bool bindingUsed: false
+
Component{
id: a
Rectangle {
@@ -21,7 +24,7 @@ Item{
id: b
Item{
property bool testBool: false
- property int testInt: null
+ property int testInt: { return null; }
property QtObject testObject: null
}
}
@@ -43,6 +46,11 @@ Item{
}
}
+ Component {
+ id: e
+ Rectangle {}
+ }
+
Component.onCompleted: {
root.declarativerectangle = a.createObject(root, {"x":17,"y":17, "color":"white", "border.width":3, "innerRect.border.width": 20});
root.declarativeitem = b.createObject(root, {"x":17,"y":17,"testBool":true,"testInt":17,"testObject":root});
@@ -52,5 +60,9 @@ Item{
root.badRequired = d.createObject(root, { "not_i": 42 });
root.goodRequired = d.createObject(root, { "i": 42 });
+
+ root.bindingAsInitial = e.createObject(root, {color: Qt.binding(() => {
+ root.bindingUsed = true; return '#ff0000'
+ })});
}
}
diff --git a/tests/auto/qml/qqmlcomponent/data/createQmlObject.qml b/tests/auto/qml/qqmlcomponent/data/createQmlObject.qml
index 282ab509f0..480835a5b1 100644
--- a/tests/auto/qml/qqmlcomponent/data/createQmlObject.qml
+++ b/tests/auto/qml/qqmlcomponent/data/createQmlObject.qml
@@ -1,5 +1,4 @@
-import QtQuick 2.0
-import QtQuick.Window 2.0
+import QtQuick
Item {
property QtObject qtobjectParent: QtObject { }
@@ -19,14 +18,14 @@ Item {
property QtObject window_window : null
Component.onCompleted: {
- qtobject_qtobject = Qt.createQmlObject("import QtQuick 2.0; QtObject{}", qtobjectParent);
- qtobject_item = Qt.createQmlObject("import QtQuick 2.0; Item{}", qtobjectParent);
- qtobject_window = Qt.createQmlObject("import QtQuick.Window 2.0; Window{}", qtobjectParent);
- item_qtobject = Qt.createQmlObject("import QtQuick 2.0; QtObject{}", itemParent);
- item_item = Qt.createQmlObject("import QtQuick 2.0; Item{}", itemParent);
- item_window = Qt.createQmlObject("import QtQuick.Window 2.0; Window{}", itemParent);
- window_qtobject = Qt.createQmlObject("import QtQuick 2.0; QtObject{}", windowParent);
- window_item = Qt.createQmlObject("import QtQuick 2.0; Item{}", windowParent);
- window_window = Qt.createQmlObject("import QtQuick.Window 2.0; Window{}", windowParent);
+ qtobject_qtobject = Qt.createQmlObject("import QtQuick; QtObject{}", qtobjectParent);
+ qtobject_item = Qt.createQmlObject("import QtQuick; Item{}", qtobjectParent);
+ qtobject_window = Qt.createQmlObject("import QtQuick; Window{}", qtobjectParent);
+ item_qtobject = Qt.createQmlObject("import QtQuick; QtObject{}", itemParent);
+ item_item = Qt.createQmlObject("import QtQuick; Item{}", itemParent);
+ item_window = Qt.createQmlObject("import QtQuick; Window{}", itemParent);
+ window_qtobject = Qt.createQmlObject("import QtQuick; QtObject{}", windowParent);
+ window_item = Qt.createQmlObject("import QtQuick; Item{}", windowParent);
+ window_window = Qt.createQmlObject("import QtQuick; Window{}", windowParent);
}
}
diff --git a/tests/auto/qml/qqmlcomponent/data/dynamic.qml b/tests/auto/qml/qqmlcomponent/data/dynamic.qml
new file mode 100644
index 0000000000..b9a54d53ff
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/dynamic.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ property var testObj
+ function use() { return testObj.has(1) ? 25 : 26; }
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/removeBinding.qml b/tests/auto/qml/qqmlcomponent/data/removeBinding.qml
new file mode 100644
index 0000000000..091f6991be
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/removeBinding.qml
@@ -0,0 +1,32 @@
+import QtQml 2.15
+
+QtObject {
+ id: root
+ objectName: "400"
+
+ property Component c: Component {
+ id: customItem
+ QtObject {
+ objectName: root.objectName
+ }
+ }
+
+ property string result: {
+ const properties = {
+ "objectName": "42",
+ }
+ const item = customItem.createObject(root, properties)
+ return item.objectName;
+ }
+
+ property string result2: {
+ const properties = {
+ "objectName": "43",
+ }
+
+ // add some junk argument to trigger the QQmlV4Function overload
+ const item = customItem.createObject(root, properties, 13)
+
+ return item.objectName;
+ }
+}
diff --git a/tests/auto/qml/qqmlcomponent/lifecyclewatcher.h b/tests/auto/qml/qqmlcomponent/lifecyclewatcher.h
new file mode 100644
index 0000000000..e974681d25
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/lifecyclewatcher.h
@@ -0,0 +1,24 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef LIFECYCLEWATCHER_H
+#define LIFECYCLEWATCHER_H
+
+#include <QtQml/qqmlparserstatus.h>
+#include <private/qqmlfinalizer_p.h>
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+class LifeCycleWatcher : public QObject, public QQmlParserStatus, public QQmlFinalizerHook
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_INTERFACES(QQmlParserStatus)
+ Q_INTERFACES(QQmlFinalizerHook)
+public:
+ void classBegin() override {states.push_back(1); }
+ void componentComplete() override {states.push_back(2);};
+ void componentFinalized() override { states.push_back(3); }
+ QList<int> states;
+};
+#endif
diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
index 5203ba9615..ea06a11006 100644
--- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
+++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
@@ -21,7 +21,7 @@
#include <private/qv4executablecompilationunit_p.h>
#include <qcolor.h>
#include <qsignalspy.h>
-
+#include "lifecyclewatcher.h"
#include <algorithm>
using namespace Qt::StringLiterals;
@@ -90,13 +90,6 @@ public slots:
}
};
-static void gc(QQmlEngine &engine)
-{
- engine.collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
-}
-
class tst_qqmlcomponent : public QQmlDataTest
{
Q_OBJECT
@@ -140,11 +133,16 @@ private slots:
void boundComponent();
void loadFromModule_data();
void loadFromModule();
+ void loadFromModuleLifecycle();
void loadFromModuleThenCreateWithIncubator();
void loadFromModuleFailures_data();
void loadFromModuleFailures();
void loadFromModuleRequired();
void loadFromQrc();
+ void removeBinding();
+ void complexObjectArgument();
+ void bindingEvaluationOrder();
+ void compilationUnitsWithSameUrl();
private:
QQmlEngine engine;
@@ -182,14 +180,12 @@ void tst_qqmlcomponent::loadEmptyUrl()
void tst_qqmlcomponent::qmlIncubateObject()
{
QQmlComponent component(&engine, testFileUrl("incubateObject.qml"));
- QObject *object = component.create();
+ std::unique_ptr<QObject> object { component.create() };
QVERIFY(object != nullptr);
QCOMPARE(object->property("test1").toBool(), true);
QCOMPARE(object->property("test2").toBool(), false);
QTRY_VERIFY(object->property("test2").toBool());
-
- delete object;
}
void tst_qqmlcomponent::qmlCreateWindow()
@@ -282,7 +278,7 @@ void tst_qqmlcomponent::qmlCreateObjectWithProperties()
QTest::ignoreMessage(
QtMsgType::QtWarningMsg,
QRegularExpression(
- ".*createObjectWithScript.qml:42:13: Required property i was not initialized"));
+ ".*createObjectWithScript.qml:45:13: Required property i was not initialized"));
QQmlComponent component(&engine, testFileUrl("createObjectWithScript.qml"));
QVERIFY2(component.errorString().isEmpty(), component.errorString().toUtf8());
@@ -342,6 +338,12 @@ void tst_qqmlcomponent::qmlCreateObjectWithProperties()
QCOMPARE(goodRequired->parent(), object.data());
QCOMPARE(goodRequired->property("i").value<int>(), 42);
}
+
+ {
+ QScopedPointer<QObject> bindingAsInitial(object->property("bindingAsInitial").value<QObject *>());
+ QVERIFY(bindingAsInitial);
+ QVERIFY(object->property("bindingUsed").toBool());
+ }
}
void tst_qqmlcomponent::qmlCreateObjectClean()
@@ -390,11 +392,11 @@ void tst_qqmlcomponent::qmlCreateParentReference()
QQmlComponent component(&engine, testFileUrl("createParentReference.qml"));
QVERIFY2(component.errorString().isEmpty(), component.errorString().toUtf8());
- QObject *object = component.create();
+ std::unique_ptr<QObject> object { component.create() };
QVERIFY(object != nullptr);
- QVERIFY(QMetaObject::invokeMethod(object, "createChild"));
- delete object;
+ QVERIFY(QMetaObject::invokeMethod(object.get(), "createChild"));
+ object.reset();
engine.setOutputWarningsToStandardError(false);
QCOMPARE(engine.outputWarningsToStandardError(), false);
@@ -416,10 +418,8 @@ void tst_qqmlcomponent::async()
QCOMPARE(watcher.ready, 1);
QCOMPARE(watcher.error, 0);
- QObject *object = component.create();
+ std::unique_ptr<QObject> object { component.create() };
QVERIFY(object != nullptr);
-
- delete object;
}
void tst_qqmlcomponent::asyncHierarchy()
@@ -437,7 +437,7 @@ void tst_qqmlcomponent::asyncHierarchy()
QCOMPARE(watcher.ready, 1);
QCOMPARE(watcher.error, 0);
- QObject *root = component.create();
+ std::unique_ptr<QObject> root { component.create() };
QVERIFY(root != nullptr);
// ensure that the parent-child relationship hierarchy is correct
@@ -461,8 +461,6 @@ void tst_qqmlcomponent::asyncHierarchy()
// ensure that values and bindings are assigned correctly
QVERIFY(root->property("success").toBool());
-
- delete root;
}
void tst_qqmlcomponent::asyncForceSync()
@@ -1245,12 +1243,14 @@ void tst_qqmlcomponent::boundComponent()
{
QQmlComponent component(&engine, testFileUrl("nestedBoundComponent.qml"));
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QVERIFY(component.isBound());
QScopedPointer<QObject> o(component.create());
QVERIFY(!o.isNull());
QQmlComponent *nestedComponent = o->property("c").value<QQmlComponent *>();
QVERIFY(nestedComponent != nullptr);
+ QVERIFY(nestedComponent->isBound());
QObject *nestedObject = o->property("o").value<QObject *>();
QVERIFY(nestedObject != nullptr);
@@ -1269,6 +1269,7 @@ void tst_qqmlcomponent::boundComponent()
{
QQmlComponent component(&engine, testFileUrl("BoundInlineComponent.qml"));
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QVERIFY(component.isBound());
QScopedPointer<QObject> o(component.create());
QVERIFY2(!o.isNull(), qPrintable(component.errorString()));
@@ -1282,11 +1283,22 @@ void tst_qqmlcomponent::boundComponent()
{
QQmlComponent component(&engine, testFileUrl("boundInlineComponentUser.qml"));
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QVERIFY(!component.isBound());
QScopedPointer<QObject> o(component.create());
QVERIFY(o.isNull());
QVERIFY(component.errorString().contains(
QLatin1String("Cannot instantiate bound inline component in different file")));
+
+ }
+
+ {
+ QQmlComponent component(&engine);
+ QVERIFY(!component.isBound());
+
+ component.setData("pragma ComponentBehavior: Bound\nsyntax error", QUrl());
+ QCOMPARE(component.errorString(), ":2 Syntax error\n"_L1);
+ QVERIFY(!component.isBound());
}
}
@@ -1334,6 +1346,34 @@ void tst_qqmlcomponent::loadFromModule()
name);
}
+void tst_qqmlcomponent::loadFromModuleLifecycle()
+{
+ QQmlEngine engine;
+ QList<int> loadFromModuleOrder;
+ QList<int> plainLoadOrder;
+ const QList<int> expected {1, 2, 3};
+ {
+ QQmlComponent component(&engine);
+ component.loadFromModule("test", "LifeCycleWatcher");
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ std::unique_ptr<QObject> root{ component.create() };
+ LifeCycleWatcher *watcher = qobject_cast<LifeCycleWatcher *>(root.get());
+ QVERIFY(watcher);
+ loadFromModuleOrder = watcher->states;
+ QCOMPARE(loadFromModuleOrder, expected);
+ }
+ {
+ QQmlComponent component(&engine);
+ component.setData("import test; LifeCycleWatcher {}", {});
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ std::unique_ptr<QObject> root{ component.create() };
+ LifeCycleWatcher *watcher = qobject_cast<LifeCycleWatcher *>(root.get());
+ QVERIFY(watcher);
+ plainLoadOrder = watcher->states;
+ }
+ QCOMPARE(loadFromModuleOrder, plainLoadOrder);
+}
+
struct CallVerifyingIncubtor : QQmlIncubator
{
void setInitialState(QObject *) override { setInitialStateCalled = true; }
@@ -1373,6 +1413,10 @@ void tst_qqmlcomponent::loadFromModuleFailures_data()
QTest::addRow("CppSingleton") << u"QtQuick"_s
<< u"Application"_s
<< u"Application is a singleton, and cannot be loaded"_s;
+ QTest::addRow("passedFileName") << "plainqml"
+ << "Plain.qml"
+ << R"(Type "Plain" from module "plainqml" contains no inline component named "qml". )"
+ R"(To load the type "Plain", drop the ".qml" extension.)";
}
void tst_qqmlcomponent::loadFromModuleFailures()
@@ -1384,7 +1428,11 @@ void tst_qqmlcomponent::loadFromModuleFailures()
QQmlEngine engine;
QQmlComponent component(&engine);
QSignalSpy errorSpy(&component, &QQmlComponent::statusChanged);
+ QSignalSpy progressSpy(&component, &QQmlComponent::progressChanged);
component.loadFromModule(uri, typeName);
+ // verify that we changed the progress correctly to 1
+ QTRY_VERIFY(!progressSpy.isEmpty());
+ QTRY_COMPARE(progressSpy.last().at(0).toDouble(), 1.0);
QVERIFY(!errorSpy.isEmpty());
QCOMPARE(errorSpy.first().first().value<QQmlComponent::Status>(),
QQmlComponent::Error);
@@ -1422,7 +1470,99 @@ void tst_qqmlcomponent::loadFromQrc()
QQmlComponentPrivate *p = QQmlComponentPrivate::get(&component);
QVERIFY(p);
QVERIFY(p->compilationUnit);
- QVERIFY(p->compilationUnit->aotCompiledFunctions);
+ QVERIFY(p->compilationUnit->baseCompilationUnit()->aotCompiledFunctions);
+}
+
+void tst_qqmlcomponent::removeBinding()
+{
+ QQmlEngine e;
+ const QUrl url = testFileUrl("removeBinding.qml");
+ QQmlComponent c(&e, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + QStringLiteral(":7:27: QML Component: Unsuitable arguments "
+ "passed to createObject(). The first argument "
+ "should be a QObject* or null, and the second "
+ "argument should be a JavaScript object or a "
+ "QVariantMap")));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("result"), QStringLiteral("42"));
+ QCOMPARE(o->property("result2"), QStringLiteral("43"));
+}
+
+void tst_qqmlcomponent::complexObjectArgument()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("complexObjectArgument.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), QStringLiteral("26 - 25"));
+}
+
+void tst_qqmlcomponent::bindingEvaluationOrder()
+{
+ // Note: This test explicitly tests the order in which bindings are
+ // evaluated, which is generally unspecified. This, however, exists
+ // as a regression test for QQmlObjectCreator code that is supposed
+ // to *not* mess with the QmlIR given to it.
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(R"(
+ import QtQml
+ QtObject {
+ property var myList: ["dummy"]
+ property int p1: { myList.push("p1"); return 0; }
+ property int p2: { myList.push("p2"); return 0; }
+ })", QUrl());
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+
+ const QList<QVariant> myList = o->property("myList").toList();
+ QCOMPARE(myList.size(), 3);
+ QCOMPARE(myList[0].toString(), u"dummy"_s);
+ QCOMPARE(myList[1].toString(), u"p1"_s);
+ QCOMPARE(myList[2].toString(), u"p2"_s);
+}
+
+void tst_qqmlcomponent::compilationUnitsWithSameUrl()
+{
+ QQmlEngine engine;
+ engine.setUiLanguage("de_CH");
+
+ std::vector<std::unique_ptr<QObject>> objects;
+ for (int i = 0; i < 10; ++i) {
+ QQmlComponent component(&engine);
+ component.setData(R"(
+ import QtQml
+ QtObject {
+ function returnThing() : string { return Qt.uiLanguage }
+ }
+ )", QUrl("duplicate.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+
+ std::unique_ptr<QObject> o(component.create());
+ QVERIFY(o.get());
+
+ QString result;
+ QMetaObject::invokeMethod(o.get(), "returnThing", Q_RETURN_ARG(QString, result));
+ QCOMPARE(result, "de_CH");
+
+ objects.push_back(std::move(o));
+ }
+
+ gc(engine);
+
+ for (const auto &o: objects) {
+ QString result;
+ QMetaObject::invokeMethod(o.get(), "returnThing", Q_RETURN_ARG(QString, result));
+ QCOMPARE(result, "de_CH");
+ }
}
QTEST_MAIN(tst_qqmlcomponent)
diff --git a/tests/auto/qml/qqmlconnections/CMakeLists.txt b/tests/auto/qml/qqmlconnections/CMakeLists.txt
index d75c86f417..0e6947370d 100644
--- a/tests/auto/qml/qqmlconnections/CMakeLists.txt
+++ b/tests/auto/qml/qqmlconnections/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlconnections Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlconnections LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -21,6 +27,7 @@ qt_internal_add_test(tst_qqmlconnections
Qt::Gui
Qt::GuiPrivate
Qt::QmlPrivate
+ Qt::QmlMetaPrivate
Qt::QuickPrivate
Qt::QuickTestUtilsPrivate
TESTDATA ${test_data}
diff --git a/tests/auto/qml/qqmlconnections/data/badSignalHandlerName.qml b/tests/auto/qml/qqmlconnections/data/badSignalHandlerName.qml
new file mode 100644
index 0000000000..921787aa36
--- /dev/null
+++ b/tests/auto/qml/qqmlconnections/data/badSignalHandlerName.qml
@@ -0,0 +1,15 @@
+import QtQml
+
+QtObject {
+ id: root
+ signal _foo
+
+ property int handled: 0
+
+ property Connections c: Connections {
+ target: root
+ function on_Foo() { root.handled += 1 }
+ function on_foo() { root.handled += 2 }
+ }
+}
+
diff --git a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
index f23c474907..88441e9dac 100644
--- a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
+++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -55,6 +55,7 @@ private slots:
void bindToPropertyWithUnderscoreChangeHandler();
void invalidTarget();
+ void badSignalHandlerName();
private:
QQmlEngine engine;
void prefixes();
@@ -76,26 +77,22 @@ void tst_qqmlconnections::defaultValues()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("test-connection3.qml"));
- QQmlConnections *item = qobject_cast<QQmlConnections*>(c.create());
+ std::unique_ptr<QQmlConnections> item { qobject_cast<QQmlConnections*>(c.create()) };
QVERIFY(item != nullptr);
QVERIFY(!item->target());
-
- delete item;
}
void tst_qqmlconnections::properties()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("test-connection2.qml"));
- QQmlConnections *item = qobject_cast<QQmlConnections*>(c.create());
+ std::unique_ptr<QQmlConnections> item { qobject_cast<QQmlConnections*>(c.create()) };
QVERIFY(item != nullptr);
QVERIFY(item != nullptr);
- QCOMPARE(item->target(), item);
-
- delete item;
+ QCOMPARE(item->target(), item.get());
}
void tst_qqmlconnections::connection()
@@ -103,7 +100,7 @@ void tst_qqmlconnections::connection()
QFETCH(QString, prefix);
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/test-connection.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ std::unique_ptr<QQuickItem> item { qobject_cast<QQuickItem*>(c.create()) };
QVERIFY(item != nullptr);
@@ -112,8 +109,6 @@ void tst_qqmlconnections::connection()
emit item->setWidth(100.);
QCOMPARE(item->width(), 100.);
QCOMPARE(item->property("tested").toBool(), true);
-
- delete item;
}
void tst_qqmlconnections::trimming()
@@ -121,20 +116,18 @@ void tst_qqmlconnections::trimming()
QFETCH(QString, prefix);
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/trimming.qml"));
- QObject *object = c.create();
+ std::unique_ptr<QObject> object { c.create() };
QVERIFY(object != nullptr);
QCOMPARE(object->property("tested").toString(), QString(""));
int index = object->metaObject()->indexOfSignal("testMe(int,QString)");
QMetaMethod method = object->metaObject()->method(index);
- method.invoke(object,
+ method.invoke(object.get(),
Qt::DirectConnection,
Q_ARG(int, 5),
Q_ARG(QString, "worked"));
QCOMPARE(object->property("tested").toString(), QString("worked5"));
-
- delete object;
}
// Confirm that target can be changed by one of our signal handlers
@@ -143,7 +136,7 @@ void tst_qqmlconnections::targetChanged()
QFETCH(QString, prefix);
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/connection-targetchange.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ std::unique_ptr<QQuickItem> item { qobject_cast<QQuickItem*>(c.create()) };
QVERIFY(item != nullptr);
QQmlConnections *connections = item->findChild<QQmlConnections*>("connections");
@@ -159,8 +152,6 @@ void tst_qqmlconnections::targetChanged()
QCOMPARE(connections->target(), item2);
// If we don't crash then we're OK
-
- delete item;
}
void tst_qqmlconnections::unknownSignals_data()
@@ -193,7 +184,7 @@ void tst_qqmlconnections::unknownSignals()
QQmlEngine engine;
QQmlComponent c(&engine, url);
- QObject *object = c.create();
+ std::unique_ptr<QObject> object { c.create() };
QVERIFY(object != nullptr);
// check that connection is created (they are all runtime errors)
@@ -202,8 +193,6 @@ void tst_qqmlconnections::unknownSignals()
if (file == "connection-unknownsignals-ignored.qml")
QVERIFY(connections->ignoreUnknownSignals());
-
- delete object;
}
void tst_qqmlconnections::errors_data()
@@ -260,25 +249,21 @@ void tst_qqmlconnections::rewriteErrors()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/rewriteError-unnamed.qml"));
QTest::ignoreMessage(QtWarningMsg, (c.url().toString() + ":5:35: QML Connections: Signal uses unnamed parameter followed by named parameter.").toLatin1());
- TestObject *obj = qobject_cast<TestObject*>(c.create());
+ std::unique_ptr<TestObject> obj { qobject_cast<TestObject*>(c.create()) };
QVERIFY(obj != nullptr);
obj->unnamedArgumentSignal(1, .5, "hello");
QCOMPARE(obj->ran(), false);
-
- delete obj;
}
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/rewriteError-global.qml"));
QTest::ignoreMessage(QtWarningMsg, (c.url().toString() + ":5:35: QML Connections: Signal parameter \"parseInt\" hides global variable.").toLatin1());
- TestObject *obj = qobject_cast<TestObject*>(c.create());
+ std::unique_ptr<TestObject> obj { qobject_cast<TestObject*>(c.create()) };
QVERIFY(obj != nullptr);
obj->signalWithGlobalName(10);
QCOMPARE(obj->ran(), false);
-
- delete obj;
}
}
@@ -324,26 +309,24 @@ void tst_qqmlconnections::singletonTypeTarget()
QFETCH(QString, prefix);
qmlRegisterSingletonType<MyTestSingletonType>("MyTestSingletonType", 1, 0, "Api", module_api_factory);
QQmlComponent component(&engine, testFileUrl(prefix + "/singletontype-target.qml"));
- QObject *object = component.create();
+ std::unique_ptr<QObject> object { component.create() };
QVERIFY(object != nullptr);
QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 0);
QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0);
- QMetaObject::invokeMethod(object, "setModuleIntProp");
+ QMetaObject::invokeMethod(object.get(), "setModuleIntProp");
QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 1);
QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0);
- QMetaObject::invokeMethod(object, "setModuleIntProp");
+ QMetaObject::invokeMethod(object.get(), "setModuleIntProp");
QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 2);
QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0);
// the singleton Type emits otherSignal every 3 times the int property changes.
- QMetaObject::invokeMethod(object, "setModuleIntProp");
+ QMetaObject::invokeMethod(object.get(), "setModuleIntProp");
QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 3);
QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 1);
-
- delete object;
}
void tst_qqmlconnections::enableDisable_QTBUG_36350()
@@ -351,7 +334,7 @@ void tst_qqmlconnections::enableDisable_QTBUG_36350()
QFETCH(QString, prefix);
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/test-connection.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ std::unique_ptr<QQuickItem> item { qobject_cast<QQuickItem*>(c.create()) };
QVERIFY(item != nullptr);
QQmlConnections *connections = item->findChild<QQmlConnections*>("connections");
@@ -370,8 +353,6 @@ void tst_qqmlconnections::enableDisable_QTBUG_36350()
emit item->setWidth(50.);
QCOMPARE(item->width(), 50.);
QCOMPARE(item->property("tested").toBool(), true); //Should have received signal to change property
-
- delete item;
}
void tst_qqmlconnections::disabledAtStart()
@@ -379,17 +360,15 @@ void tst_qqmlconnections::disabledAtStart()
QFETCH(QString, prefix);
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/disabled-at-start.qml"));
- QObject * const object = c.create();
+ std::unique_ptr<QObject> object { c.create() };
QVERIFY(object != nullptr);
QCOMPARE(object->property("tested").toBool(), false);
const int index = object->metaObject()->indexOfSignal("testMe()");
const QMetaMethod method = object->metaObject()->method(index);
- method.invoke(object, Qt::DirectConnection);
+ method.invoke(object.get(), Qt::DirectConnection);
QCOMPARE(object->property("tested").toBool(), false);
-
- delete object;
}
//QTBUG-56499
@@ -398,7 +377,7 @@ void tst_qqmlconnections::clearImplicitTarget()
QFETCH(QString, prefix);
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/test-connection-implicit.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ std::unique_ptr<QQuickItem> item { qobject_cast<QQuickItem*>(c.create()) };
QVERIFY(item != nullptr);
@@ -415,8 +394,6 @@ void tst_qqmlconnections::clearImplicitTarget()
// target cleared: no longer fire Connections
item->setWidth(150.);
QCOMPARE(item->property("tested").toBool(), false);
-
- delete item;
}
void tst_qqmlconnections::onWithoutASignal()
@@ -485,6 +462,26 @@ void tst_qqmlconnections::invalidTarget()
QTRY_VERIFY(root->objectName().isEmpty());
}
+void tst_qqmlconnections::badSignalHandlerName()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("badSignalHandlerName.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "\"on_foo\" is not a properly capitalized signal handler name. "
+ "\"on_Foo\" would be correct.");
+
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
+
+ QCOMPARE(root->property("handled").toInt(), 0);
+ QMetaObject::invokeMethod(root.data(), "_foo");
+ QCOMPARE(root->property("handled").toInt(), 3);
+}
+
+
QTEST_MAIN(tst_qqmlconnections)
#include "tst_qqmlconnections.moc"
diff --git a/tests/auto/qml/qqmlconsole/CMakeLists.txt b/tests/auto/qml/qqmlconsole/CMakeLists.txt
index a4eb33f1df..121b0863d0 100644
--- a/tests/auto/qml/qqmlconsole/CMakeLists.txt
+++ b/tests/auto/qml/qqmlconsole/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlconsole Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlconsole LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlconsole/data/assert.qml b/tests/auto/qml/qqmlconsole/data/assert.qml
index 38a103e233..04ea18a3e5 100644
--- a/tests/auto/qml/qqmlconsole/data/assert.qml
+++ b/tests/auto/qml/qqmlconsole/data/assert.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlconsole/data/categorized_logging.qml b/tests/auto/qml/qqmlconsole/data/categorized_logging.qml
index 9593abbaa9..dd03c0c773 100644
--- a/tests/auto/qml/qqmlconsole/data/categorized_logging.qml
+++ b/tests/auto/qml/qqmlconsole/data/categorized_logging.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Pelagicore AG
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/qml/qqmlconsole/data/exception.qml b/tests/auto/qml/qqmlconsole/data/exception.qml
index 769b196c10..d3d022ca22 100644
--- a/tests/auto/qml/qqmlconsole/data/exception.qml
+++ b/tests/auto/qml/qqmlconsole/data/exception.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlconsole/data/logging.qml b/tests/auto/qml/qqmlconsole/data/logging.qml
index af1c97ee01..309534615e 100644
--- a/tests/auto/qml/qqmlconsole/data/logging.qml
+++ b/tests/auto/qml/qqmlconsole/data/logging.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlconsole/data/profiling.qml b/tests/auto/qml/qqmlconsole/data/profiling.qml
index fc655ab26c..528726b268 100644
--- a/tests/auto/qml/qqmlconsole/data/profiling.qml
+++ b/tests/auto/qml/qqmlconsole/data/profiling.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlconsole/data/tracing.qml b/tests/auto/qml/qqmlconsole/data/tracing.qml
index 750e4f5688..52be9d84de 100644
--- a/tests/auto/qml/qqmlconsole/data/tracing.qml
+++ b/tests/auto/qml/qqmlconsole/data/tracing.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
index 4bffdb0dd7..40d849969c 100644
--- a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
+++ b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
#include <QQmlEngine>
@@ -95,7 +95,7 @@ void tst_qqmlconsole::categorized_logging()
QVERIFY(testCategory.isCriticalEnabled());
QQmlComponent component(&engine, testUrl);
- QObject *object = component.create();
+ std::unique_ptr<QObject> object { component.create() };
QVERIFY2(object != nullptr, component.errorString().toUtf8());
QVERIFY(messageHandler.messages().contains("qt.test: console.info"));
@@ -131,8 +131,6 @@ void tst_qqmlconsole::categorized_logging()
QString useEmptyCategory = "default: " + QString::fromLatin1("%1:%2: ").arg(testUrl.toString()).arg(42) +
"Error: A QmlLoggingCatgory was provided without a valid name";
QVERIFY(messageHandler.messages().contains(useEmptyCategory));
-
- delete object;
}
void tst_qqmlconsole::tracing()
@@ -147,9 +145,17 @@ void tst_qqmlconsole::tracing()
QTest::ignoreMessage(QtDebugMsg, qPrintable(traceText));
QQmlComponent component(&engine, testUrl);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
- delete object;
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
+
+ const QString traceText2
+ = QLatin1String("qml: tracing (%1:%2)\nexpression for onCompleted (%1:%3)")
+ .arg(testUrl.toString()).arg(12).arg(16);
+
+ QQmlTestMessageHandler messageHandler;
+ messageHandler.setIncludeCategoriesEnabled(true);
+ std::unique_ptr<QObject> object2 { component.create() };
+ QCOMPARE(messageHandler.messageString(), traceText2);
}
void tst_qqmlconsole::profiling()
@@ -161,9 +167,8 @@ void tst_qqmlconsole::profiling()
QTest::ignoreMessage(QtWarningMsg, "Ignoring console.profileEnd(): the debug service is disabled.");
QQmlComponent component(&engine, testUrl);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
- delete object;
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
}
void tst_qqmlconsole::testAssert()
@@ -186,9 +191,8 @@ void tst_qqmlconsole::testAssert()
QTest::ignoreMessage(QtCriticalMsg, qPrintable(assert2));
QQmlComponent component(&engine, testUrl);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
- delete object;
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
}
void tst_qqmlconsole::exception()
@@ -211,9 +215,8 @@ void tst_qqmlconsole::exception()
QTest::ignoreMessage(QtCriticalMsg, qPrintable(exception2));
QQmlComponent component(&engine, testUrl);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
- delete object;
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
}
QTEST_MAIN(tst_qqmlconsole)
diff --git a/tests/auto/qml/qqmlcontext/CMakeLists.txt b/tests/auto/qml/qqmlcontext/CMakeLists.txt
index c8d5ec6810..b50e3ff7fe 100644
--- a/tests/auto/qml/qqmlcontext/CMakeLists.txt
+++ b/tests/auto/qml/qqmlcontext/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlcontext Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlcontext LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlcontext/data/A.qml b/tests/auto/qml/qqmlcontext/data/A.qml
new file mode 100644
index 0000000000..1a44f005af
--- /dev/null
+++ b/tests/auto/qml/qqmlcontext/data/A.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+B {
+ id: b
+ property int y: 2
+}
diff --git a/tests/auto/qml/qqmlcontext/data/B.qml b/tests/auto/qml/qqmlcontext/data/B.qml
new file mode 100644
index 0000000000..7754728304
--- /dev/null
+++ b/tests/auto/qml/qqmlcontext/data/B.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+C {
+ id: z
+ property int z: 3
+}
diff --git a/tests/auto/qml/qqmlcontext/data/C.qml b/tests/auto/qml/qqmlcontext/data/C.qml
new file mode 100644
index 0000000000..6afd23aa6c
--- /dev/null
+++ b/tests/auto/qml/qqmlcontext/data/C.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ id: outer
+ objectName: "the" + "C"
+}
diff --git a/tests/auto/qml/qqmlcontext/data/destroyContextObject.qml b/tests/auto/qml/qqmlcontext/data/destroyContextObject.qml
new file mode 100644
index 0000000000..7b1f46d7d1
--- /dev/null
+++ b/tests/auto/qml/qqmlcontext/data/destroyContextObject.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property A a: A {}
+}
diff --git a/tests/auto/qml/qqmlcontext/data/gcDeletesContextObject.qml b/tests/auto/qml/qqmlcontext/data/gcDeletesContextObject.qml
new file mode 100644
index 0000000000..a478a587df
--- /dev/null
+++ b/tests/auto/qml/qqmlcontext/data/gcDeletesContextObject.qml
@@ -0,0 +1,5 @@
+import QtQml
+QtObject {
+ property Component c: MyItem {}
+ property QtObject o: c.createObject()
+}
diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
index 8398f8b9d7..8e726857cc 100644
--- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
+++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
@@ -49,6 +49,10 @@ private slots:
void outerContextObject();
void contextObjectHierarchy();
void destroyContextProperty();
+ void destroyContextObject();
+
+ void numericContextProperty();
+ void gcDeletesContextObject();
private:
QQmlEngine engine;
@@ -92,13 +96,13 @@ void tst_qqmlcontext::resolvedUrl()
// Relative to a deleted parent
{
- QQmlContext *ctxt = new QQmlContext(&engine);
+ std::unique_ptr<QQmlContext> ctxt = std::make_unique<QQmlContext>(&engine);
ctxt->setBaseUrl(QUrl("http://www.qt-project.org/"));
- QQmlContext ctxt2(ctxt);
+ QQmlContext ctxt2(ctxt.get());
QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl("http://www.qt-project.org/main2.qml"));
- delete ctxt; ctxt = nullptr;
+ ctxt.reset();
QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl());
}
@@ -114,58 +118,58 @@ void tst_qqmlcontext::resolvedUrl()
void tst_qqmlcontext::engineMethod()
{
- QQmlEngine *engine = new QQmlEngine;
+ std::unique_ptr<QQmlEngine> engine = std::make_unique<QQmlEngine>();
- QQmlContext ctxt(engine);
+ QQmlContext ctxt(engine.get());
QQmlContext ctxt2(&ctxt);
QQmlContext ctxt3(&ctxt2);
QQmlContext ctxt4(&ctxt2);
- QCOMPARE(ctxt.engine(), engine);
- QCOMPARE(ctxt2.engine(), engine);
- QCOMPARE(ctxt3.engine(), engine);
- QCOMPARE(ctxt4.engine(), engine);
+ QCOMPARE(ctxt.engine(), engine.get());
+ QCOMPARE(ctxt2.engine(), engine.get());
+ QCOMPARE(ctxt3.engine(), engine.get());
+ QCOMPARE(ctxt4.engine(), engine.get());
- delete engine; engine = nullptr;
+ engine.reset();
- QCOMPARE(ctxt.engine(), engine);
- QCOMPARE(ctxt2.engine(), engine);
- QCOMPARE(ctxt3.engine(), engine);
- QCOMPARE(ctxt4.engine(), engine);
+ QCOMPARE(ctxt.engine(), engine.get());
+ QCOMPARE(ctxt2.engine(), engine.get());
+ QCOMPARE(ctxt3.engine(), engine.get());
+ QCOMPARE(ctxt4.engine(), engine.get());
}
void tst_qqmlcontext::parentContext()
{
- QQmlEngine *engine = new QQmlEngine;
+ std::unique_ptr<QQmlEngine> engine = std::make_unique<QQmlEngine>();
QCOMPARE(engine->rootContext()->parentContext(), (QQmlContext *)nullptr);
- QQmlContext *ctxt = new QQmlContext(engine);
- QQmlContext *ctxt2 = new QQmlContext(ctxt);
- QQmlContext *ctxt3 = new QQmlContext(ctxt2);
- QQmlContext *ctxt4 = new QQmlContext(ctxt2);
- QQmlContext *ctxt5 = new QQmlContext(ctxt);
- QQmlContext *ctxt6 = new QQmlContext(engine);
- QQmlContext *ctxt7 = new QQmlContext(engine->rootContext());
+ std::unique_ptr<QQmlContext> ctxt = std::make_unique<QQmlContext>(engine.get());
+ std::unique_ptr<QQmlContext> ctxt2 = std::make_unique<QQmlContext>(ctxt.get());
+ std::unique_ptr<QQmlContext> ctxt3 = std::make_unique<QQmlContext>(ctxt2.get());
+ std::unique_ptr<QQmlContext> ctxt4 = std::make_unique<QQmlContext>(ctxt2.get());
+ std::unique_ptr<QQmlContext> ctxt5 = std::make_unique<QQmlContext>(ctxt.get());
+ std::unique_ptr<QQmlContext> ctxt6 = std::make_unique<QQmlContext>(engine.get());
+ std::unique_ptr<QQmlContext> ctxt7 = std::make_unique<QQmlContext>(engine->rootContext());
QCOMPARE(ctxt->parentContext(), engine->rootContext());
- QCOMPARE(ctxt2->parentContext(), ctxt);
- QCOMPARE(ctxt3->parentContext(), ctxt2);
- QCOMPARE(ctxt4->parentContext(), ctxt2);
- QCOMPARE(ctxt5->parentContext(), ctxt);
+ QCOMPARE(ctxt2->parentContext(), ctxt.get());
+ QCOMPARE(ctxt3->parentContext(), ctxt2.get());
+ QCOMPARE(ctxt4->parentContext(), ctxt2.get());
+ QCOMPARE(ctxt5->parentContext(), ctxt.get());
QCOMPARE(ctxt6->parentContext(), engine->rootContext());
QCOMPARE(ctxt7->parentContext(), engine->rootContext());
- delete ctxt2; ctxt2 = nullptr;
+ ctxt2.reset();
QCOMPARE(ctxt->parentContext(), engine->rootContext());
QCOMPARE(ctxt3->parentContext(), (QQmlContext *)nullptr);
QCOMPARE(ctxt4->parentContext(), (QQmlContext *)nullptr);
- QCOMPARE(ctxt5->parentContext(), ctxt);
+ QCOMPARE(ctxt5->parentContext(), ctxt.get());
QCOMPARE(ctxt6->parentContext(), engine->rootContext());
QCOMPARE(ctxt7->parentContext(), engine->rootContext());
- delete engine; engine = nullptr;
+ engine.reset();
QCOMPARE(ctxt->parentContext(), (QQmlContext *)nullptr);
QCOMPARE(ctxt3->parentContext(), (QQmlContext *)nullptr);
@@ -173,13 +177,6 @@ void tst_qqmlcontext::parentContext()
QCOMPARE(ctxt5->parentContext(), (QQmlContext *)nullptr);
QCOMPARE(ctxt6->parentContext(), (QQmlContext *)nullptr);
QCOMPARE(ctxt7->parentContext(), (QQmlContext *)nullptr);
-
- delete ctxt7;
- delete ctxt6;
- delete ctxt5;
- delete ctxt4;
- delete ctxt3;
- delete ctxt;
}
class TestObject : public QObject
@@ -229,11 +226,9 @@ private:
QQmlComponent component(&engine); \
component.setData("import QtQuick 2.0; QtObject { property variant test: " #name " }", QUrl()); \
\
- QObject *obj = component.create(ctxt); \
+ std::unique_ptr<QObject> obj { component.create(ctxt) }; \
\
QCOMPARE(obj->property("test"), value); \
-\
- delete obj; \
}
void tst_qqmlcontext::setContextProperty()
@@ -279,39 +274,33 @@ void tst_qqmlcontext::setContextProperty()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { property variant test: a }", QUrl());
- QObject *obj = component.create(&ctxt2);
+ std::unique_ptr<QObject> obj { component.create(&ctxt2) };
QCOMPARE(obj->property("test"), QVariant(13));
ctxt.setContextProperty("a", QVariant(19));
QCOMPARE(obj->property("test"), QVariant(19));
-
- delete obj;
}
{
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { property variant test: b }", QUrl());
- QObject *obj = component.create(&ctxt2);
+ std::unique_ptr<QObject> obj { component.create(&ctxt2) };
QCOMPARE(obj->property("test"), QVariant(8));
ctxt.setContextProperty("b", QVariant(5));
QCOMPARE(obj->property("test"), QVariant(8));
ctxt2.setContextProperty("b", QVariant(1912));
QCOMPARE(obj->property("test"), QVariant(1912));
-
- delete obj;
}
{
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { property variant test: e.a }", QUrl());
- QObject *obj = component.create(&ctxt2);
+ std::unique_ptr<QObject> obj { component.create(&ctxt2) };
QCOMPARE(obj->property("test"), QVariant(12));
obj1.setA(13);
QCOMPARE(obj->property("test"), QVariant(13));
-
- delete obj;
}
// New context properties
@@ -319,13 +308,11 @@ void tst_qqmlcontext::setContextProperty()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { property variant test: a }", QUrl());
- QObject *obj = component.create(&ctxt2);
+ std::unique_ptr<QObject> obj { component.create(&ctxt2) };
QCOMPARE(obj->property("test"), QVariant(19));
ctxt2.setContextProperty("a", QVariant(1945));
QCOMPARE(obj->property("test"), QVariant(1945));
-
- delete obj;
}
// Setting an object-variant context property
@@ -337,15 +324,13 @@ void tst_qqmlcontext::setContextProperty()
ctxt.setContextProperty("ctxtProp", QVariant());
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:1: TypeError: Cannot read property 'a' of undefined");
- QObject *obj = component.create(&ctxt);
+ std::unique_ptr<QObject> obj { component.create(&ctxt) };
QVariant v = obj->property("obj");
ctxt.setContextProperty("ctxtProp", v);
QCOMPARE(obj->property("test"), QVariant(10));
-
- delete obj;
}
}
@@ -407,13 +392,11 @@ void tst_qqmlcontext::setContextObject()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { property variant test: a }", QUrl());
- QObject *obj = component.create(&ctxt);
+ std::unique_ptr<QObject> obj { component.create(&ctxt) };
QCOMPARE(obj->property("test"), QVariant(12));
to.setA(14);
QCOMPARE(obj->property("test"), QVariant(14));
-
- delete obj;
}
// Change of context object
@@ -431,19 +414,19 @@ void tst_qqmlcontext::setContextObject()
void tst_qqmlcontext::destruction()
{
- QQmlContext *ctxt = new QQmlContext(&engine);
+ std::unique_ptr<QQmlContext> ctxt = std::make_unique<QQmlContext>(&engine);
QObject obj;
- QQmlEngine::setContextForObject(&obj, ctxt);
- QQmlExpression expr(ctxt, nullptr, "a");
+ QQmlEngine::setContextForObject(&obj, ctxt.get());
+ QQmlExpression expr(ctxt.get(), nullptr, "a");
- QCOMPARE(ctxt, QQmlEngine::contextForObject(&obj));
- QCOMPARE(ctxt, expr.context());
+ QCOMPARE(ctxt.get(), QQmlEngine::contextForObject(&obj));
+ QCOMPARE(ctxt.get(), expr.context());
- delete ctxt; ctxt = nullptr;
+ ctxt.reset();
- QCOMPARE(ctxt, QQmlEngine::contextForObject(&obj));
- QCOMPARE(ctxt, expr.context());
+ QCOMPARE(ctxt.get(), QQmlEngine::contextForObject(&obj));
+ QCOMPARE(ctxt.get(), expr.context());
}
void tst_qqmlcontext::idAsContextProperty()
@@ -451,18 +434,16 @@ void tst_qqmlcontext::idAsContextProperty()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { property variant a; a: QtObject { id: myObject } }", QUrl());
- QObject *obj = component.create();
- QVERIFY(obj);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj.get());
QVariant a = obj->property("a");
QCOMPARE(a.userType(), int(QMetaType::QObjectStar));
- QVariant ctxt = qmlContext(obj)->contextProperty("myObject");
+ QVariant ctxt = qmlContext(obj.get())->contextProperty("myObject");
QCOMPARE(ctxt.userType(), int(QMetaType::QObjectStar));
QCOMPARE(a, ctxt);
-
- delete obj;
}
// Internal contexts should be read-only
@@ -471,28 +452,26 @@ void tst_qqmlcontext::readOnlyContexts()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { id: me }", QUrl());
- QObject *obj = component.create();
- QVERIFY(obj);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj.get());
- QQmlContext *context = qmlContext(obj);
+ QQmlContext *context = qmlContext(obj.get());
QVERIFY(context);
- QCOMPARE(qvariant_cast<QObject*>(context->contextProperty("me")), obj);
- QCOMPARE(context->contextObject(), obj);
+ QCOMPARE(qvariant_cast<QObject*>(context->contextProperty("me")), obj.get());
+ QCOMPARE(context->contextObject(), obj.get());
QTest::ignoreMessage(QtWarningMsg, "QQmlContext: Cannot set property on internal context.");
context->setContextProperty("hello", 12);
QCOMPARE(context->contextProperty("hello"), QVariant());
QTest::ignoreMessage(QtWarningMsg, "QQmlContext: Cannot set property on internal context.");
- context->setContextProperty("hello", obj);
+ context->setContextProperty("hello", obj.get());
QCOMPARE(context->contextProperty("hello"), QVariant());
QTest::ignoreMessage(QtWarningMsg, "QQmlContext: Cannot set context object for internal context.");
context->setContextObject(nullptr);
- QCOMPARE(context->contextObject(), obj);
-
- delete obj;
+ QCOMPARE(context->contextObject(), obj.get());
}
void tst_qqmlcontext::objectsAndNames()
@@ -624,14 +603,12 @@ void tst_qqmlcontext::refreshExpressionsCrash()
component.setData("import QtQuick 2.0; QtObject { property var binding: deleteCommand.doCommand() }", QUrl());
QVERIFY(component.isReady());
- QObject *o1 = component.create(&ctxt);
+ std::unique_ptr<QObject> o1 { component.create(&ctxt) };
QObject *o2 = component.create(&ctxt);
command.object = o2;
QQmlContextData::get(&ctxt)->refreshExpressions();
-
- delete o1;
}
{
QQmlEngine engine;
@@ -647,13 +624,11 @@ void tst_qqmlcontext::refreshExpressionsCrash()
QVERIFY(component.isReady());
QObject *o1 = component.create(&ctxt);
- QObject *o2 = component.create(&ctxt);
+ std::unique_ptr<QObject> o2 { component.create(&ctxt) };
command.object = o1;
QQmlContextData::get(&ctxt)->refreshExpressions();
-
- delete o2;
}
}
@@ -685,19 +660,15 @@ void tst_qqmlcontext::refreshExpressions()
QQmlContext context(engine.rootContext());
QQmlContext context2(&context);
- QObject *o1 = component.create(&context);
- QObject *o2 = component.create(&context2);
- QObject *o3 = component2.create(&context);
+ std::unique_ptr<QObject> o1 { component.create(&context) };
+ std::unique_ptr<QObject> o2 { component.create(&context2) };
+ std::unique_ptr<QObject> o3 { component2.create(&context) };
QCOMPARE(command.count, 5);
QQmlContextData::get(&context)->refreshExpressions();
QCOMPARE(command.count, 10);
-
- delete o3;
- delete o2;
- delete o1;
}
// Test that updating the root context, only causes expressions in contexts with an
@@ -717,10 +688,10 @@ void tst_qqmlcontext::refreshExpressionsRootContext()
QString warning = component2.url().toString() + QLatin1String(":4: ReferenceError: unresolvedName is not defined");
- QObject *o1 = component.create(&context);
+ std::unique_ptr<QObject> o1 { component.create(&context) };
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- QObject *o2 = component2.create(&context2);
+ std::unique_ptr<QObject> o2 { component2.create(&context2) };
QCOMPARE(command.count, 3);
@@ -728,9 +699,6 @@ void tst_qqmlcontext::refreshExpressionsRootContext()
QQmlContextData::get(engine.rootContext())->refreshExpressions();
QCOMPARE(command.count, 4);
-
- delete o2;
- delete o1;
}
void tst_qqmlcontext::skipExpressionRefresh_qtbug_53431()
@@ -752,10 +720,9 @@ void tst_qqmlcontext::qtbug_22535()
QQmlComponent component(&engine, testFileUrl("qtbug_22535.qml"));
QQmlContext context(engine.rootContext());
- QObject *o = component.create(&context);
+ std::unique_ptr<QObject> o { component.create(&context) };
// Don't crash!
- delete o;
}
void tst_qqmlcontext::evalAfterInvalidate()
@@ -858,7 +825,7 @@ void tst_qqmlcontext::contextLeak()
scriptContext = scriptContextWrapper->as<QV4::QQmlContextWrapper>()->getContext();
}
- engine.collectGarbage();
+ gc(engine);
// Each time a JS file (non-pragma-shared) is imported, we create a QQmlContext(Data) for it.
// Make sure that context does not leak.
@@ -979,6 +946,66 @@ void tst_qqmlcontext::destroyContextProperty()
// TODO: Or are we?
}
+void tst_qqmlcontext::destroyContextObject()
+{
+ QQmlEngine engine;
+ QList<QQmlRefPointer<QQmlContextData>> contexts;
+ QQmlComponent component(&engine, testFileUrl("destroyContextObject.qml"));
+ QScopedPointer<QObject> root(component.create());
+
+ QPointer<QObject> a = root->property("a").value<QObject *>();
+ QVERIFY(a);
+
+ for (QQmlRefPointer<QQmlContextData> context = QQmlData::get(a)->ownContext;
+ context; context = context->parent()) {
+ contexts.append(context);
+ }
+
+ QObject *deleted = a.data();
+ root.reset();
+
+ QVERIFY(a.isNull());
+
+ for (const auto &context : contexts)
+ QVERIFY(context->contextObject() != deleted);
+}
+
+void tst_qqmlcontext::numericContextProperty()
+{
+ QQmlEngine engine;
+ auto context = engine.rootContext();
+ QTest::ignoreMessage(QtWarningMsg, "QQmlContext: Using numbers as context properties will be disallowed in a future Qt version.");
+ context->setContextProperty(QLatin1String("11"), 42);
+ QCOMPARE(context->contextProperty(QLatin1String("11")).toInt(), 42);
+}
+
+void tst_qqmlcontext::gcDeletesContextObject()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("gcDeletesContextObject.qml"));
+
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QVERIFY(!o.isNull());
+
+ QPointer<QObject> contextObject = o->property("o").value<QObject *>();
+ QVERIFY(contextObject != nullptr);
+
+ QQmlData *data = QQmlData::get(contextObject);
+ QVERIFY(data);
+ QQmlRefPointer<QQmlContextData> context = data->ownContext;
+ QVERIFY(context);
+ QCOMPARE(context->contextObject(), contextObject);
+
+ o->setProperty("o", QVariant::fromValue<QObject *>(nullptr));
+ QCOMPARE(o->property("o").value<QObject *>(), nullptr);
+ engine.collectGarbage();
+
+ QTRY_VERIFY(contextObject.isNull());
+ QCOMPARE(context->contextObject(), nullptr);
+}
+
QTEST_MAIN(tst_qqmlcontext)
#include "tst_qqmlcontext.moc"
diff --git a/tests/auto/qml/qqmlcpputils/CMakeLists.txt b/tests/auto/qml/qqmlcpputils/CMakeLists.txt
index 3eb58640c7..ee809e09b5 100644
--- a/tests/auto/qml/qqmlcpputils/CMakeLists.txt
+++ b/tests/auto/qml/qqmlcpputils/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlcpputils Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlcpputils LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlcpputils
SOURCES
tst_qqmlcpputils.cpp
diff --git a/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp b/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp
index 11d79707d0..d858fd2ff0 100644
--- a/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp
+++ b/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <qsignalspy.h>
@@ -35,13 +35,11 @@ public slots:
void tst_qqmlcpputils::fastConnect()
{
{
- MyObject *obj = new MyObject;
- qmlobject_connect(obj, MyObject, SIGNAL(signal1()), obj, MyObject, SLOT(slot1()));
+ std::unique_ptr<MyObject> obj = std::make_unique<MyObject>();
+ qmlobject_connect(obj.get(), MyObject, SIGNAL(signal1()), obj.get(), MyObject, SLOT(slot1()));
obj->signal1();
QCOMPARE(obj->slotCount, 1);
-
- delete obj;
}
{
@@ -53,27 +51,24 @@ void tst_qqmlcpputils::fastConnect()
}
{
- MyObject *obj = new MyObject;
- QSignalSpy spy(obj, SIGNAL(signal2()));
- qmlobject_connect(obj, MyObject, SIGNAL(signal1()), obj, MyObject, SIGNAL(signal2()));
+ std::unique_ptr<MyObject> obj = std::make_unique<MyObject>();
+ QSignalSpy spy(obj.get(), SIGNAL(signal2()));
+ qmlobject_connect(obj.get(), MyObject, SIGNAL(signal1()), obj.get(), MyObject, SIGNAL(signal2()));
obj->signal1();
QCOMPARE(spy.size(), 1);
-
- delete obj;
}
}
void tst_qqmlcpputils::fastCast()
{
{
- QObject *myObj = new MyObject;
- MyObject *obj = qmlobject_cast<MyObject*>(myObj);
+ std::unique_ptr<QObject> myObj = std::make_unique<MyObject>();
+ MyObject *obj = qmlobject_cast<MyObject*>(myObj.get());
QVERIFY(obj);
QCOMPARE(obj->metaObject(), myObj->metaObject());
obj->slot1();
QCOMPARE(obj->slotCount, 1);
- delete myObj;
}
{
diff --git a/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt b/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt
index 705ee6f357..8d8a90e0a7 100644
--- a/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt
+++ b/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldelegatemodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldelegatemodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml b/tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml
index a61e94ea6d..5ef502601c 100644
--- a/tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml
+++ b/tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml.Models 2.15
import QtQuick 2.15
diff --git a/tests/auto/qml/qqmldelegatemodel/data/clearCacheDuringInsertion.qml b/tests/auto/qml/qqmldelegatemodel/data/clearCacheDuringInsertion.qml
new file mode 100644
index 0000000000..37e508302e
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/clearCacheDuringInsertion.qml
@@ -0,0 +1,138 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Window
+import QtQuick.Controls
+import QtQuick.Layouts
+import QtQml.Models
+
+Window {
+ id: root
+ width: 640
+ height: 480
+ visible: true
+ color: "#111111"
+
+ Column {
+ spacing: 1
+ Repeater {
+ model: 1000
+
+ Rectangle {
+ width: 100
+ height: 100
+ color: "grey"
+ DelegateModel {
+ id: delegateModel
+ delegate: Rectangle {
+ width: 100
+ height: 20
+ color: "black"
+ Text {
+ anchors.centerIn: parent
+ text: "Name: " + model.name
+ color: "white"
+ }
+ }
+
+ property int length: 0
+ property var filterAcceptsItem: function(item) { return true; }
+
+ model: ListModel {
+ id: myModel
+
+ ListElement {
+ name: "tomato"
+ classifications: [
+ ListElement { classification: "fruit" },
+ ListElement { classification: "veg" }
+ ]
+ nutritionFacts: [
+ ListElement {
+ calories: "45"
+ }
+ ]
+ }
+
+ ListElement {
+ name: "apple"
+ classifications: [
+ ListElement { classification: "fruit" }
+ ]
+ nutritionFacts: [
+ ListElement {
+ calories: "87"
+ }
+ ]
+ }
+
+ ListElement {
+ name: "broccoli"
+ classifications: [
+ ListElement { classification: "veg" }
+ ]
+ nutritionFacts: [
+ ListElement {
+ calories: "12"
+ }
+ ]
+ }
+
+ ListElement {
+ name: "squash"
+ classifications: [
+ ListElement { classification: "veg" }
+ ]
+ nutritionFacts: [
+ ListElement {
+ calories: "112"
+ }
+ ]
+ }
+ }
+
+ groups: [
+ DelegateModelGroup { id: visibleItems; name: "visible" },
+ DelegateModelGroup { name: "veg" },
+ DelegateModelGroup { name: "fruit"; includeByDefault: true }
+ ]
+
+ function update() {
+
+ // Step 1: Filter items
+ var visible = [];
+ for (var i = 0; i < items.count; ++i) {
+ var item = items.get(i);
+ if (filterAcceptsItem(item.model)) {
+ visible.push(item);
+ }
+ }
+
+ // Step 2: Add all items to the visible group:
+ for (i = 0; i < visible.length; ++i) {
+ items.insert(visible[i], delegateModel.filterOnGroup)
+ }
+ delegateModel.length = visible.length
+ }
+
+ items.onChanged: update()
+ onFilterAcceptsItemChanged: update()
+
+ filterOnGroup: "visible"
+ Component.onCompleted: {
+ for(var i = 0; i < myModel.count; i++) {
+ var temp = 0;
+ var entry = myModel.get(i);
+
+ for (var j = 0; j < entry.classifications.count; j++) {
+ temp = entry.classifications.get(j)
+ items.insert(entry, temp.classification)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml b/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml
new file mode 100644
index 0000000000..b01b14f7b8
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml
@@ -0,0 +1,50 @@
+import QtQuick
+import QtQml.Models
+
+Item {
+ DelegateModel {
+ id: delegateModel
+ model: ListModel {
+ id: sourceModel
+
+ ListElement { title: "foo" }
+ ListElement { title: "bar" }
+
+ function clear() {
+ if (count > 0)
+ remove(0, count);
+ }
+ }
+
+ groups: [
+ DelegateModelGroup { name: "selectedItems" }
+ ]
+
+ delegate: Text {
+ height: DelegateModel.inSelectedItems ? implicitHeight * 2 : implicitHeight
+ Component.onCompleted: {
+ if (index === 0)
+ DelegateModel.inSelectedItems = true;
+ }
+ }
+
+ Component.onCompleted: {
+ items.create(0)
+ items.create(1)
+ }
+ }
+
+ ListView {
+ anchors.fill: parent
+ model: delegateModel
+ }
+
+ Timer {
+ running: true
+ interval: 10
+ onTriggered: sourceModel.clear()
+ }
+
+ property int count: delegateModel.items.count
+}
+
diff --git a/tests/auto/qml/qqmldelegatemodel/data/integerModel.qml b/tests/auto/qml/qqmldelegatemodel/data/integerModel.qml
index 42bf882fda..bcc7a2786a 100644
--- a/tests/auto/qml/qqmldelegatemodel/data/integerModel.qml
+++ b/tests/auto/qml/qqmldelegatemodel/data/integerModel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml.Models 2.15
import QtQuick 2.15
diff --git a/tests/auto/qml/qqmldelegatemodel/data/listModel.qml b/tests/auto/qml/qqmldelegatemodel/data/listModel.qml
index f74abb2e9a..b4ea7a283f 100644
--- a/tests/auto/qml/qqmldelegatemodel/data/listModel.qml
+++ b/tests/auto/qml/qqmldelegatemodel/data/listModel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml.Models 2.15
import QtQuick 2.15
diff --git a/tests/auto/qml/qqmldelegatemodel/data/modifyObjectUnderConstruction.qml b/tests/auto/qml/qqmldelegatemodel/data/modifyObjectUnderConstruction.qml
new file mode 100644
index 0000000000..f21577e395
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/modifyObjectUnderConstruction.qml
@@ -0,0 +1,18 @@
+import QtQuick
+
+Window {
+ id: window
+ width: 640
+ height: 480
+ visible: true
+ property alias testModel: repeater.model
+
+ Repeater {
+ id: repeater
+ model: 1
+ delegate: Item {
+ Component.onCompleted: repeater.model = 0
+ }
+ }
+}
+
diff --git a/tests/auto/qml/qqmldelegatemodel/data/overriddenModelData.qml b/tests/auto/qml/qqmldelegatemodel/data/overriddenModelData.qml
new file mode 100644
index 0000000000..e392b2e5c9
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/overriddenModelData.qml
@@ -0,0 +1,55 @@
+import QtQml
+
+DelegateModel {
+ id: root
+
+ property ListModel listModel: ListModel {
+ ListElement {
+ modelData: "a"
+ row: "b"
+ column: "c"
+ model: "d"
+ hasModelChildren: "e"
+ index: "f"
+ }
+ }
+
+ property var array: [{
+ modelData: "a",
+ row: "b",
+ column: "c",
+ model: "d",
+ hasModelChildren: "e",
+ index: "f"
+ }]
+
+ property QtObject object: QtObject {
+ property string modelData: "a"
+ property string row: "b"
+ property string column: "c"
+ property string model: "d"
+ property string hasModelChildren: "e"
+ property string index: "f"
+ }
+
+ property int n: -1
+
+ model: {
+ switch (n) {
+ case 0: return listModel
+ case 1: return array
+ case 2: return object
+ }
+ return undefined;
+ }
+
+ delegate: QtObject {
+ required property string modelData
+ required property string row
+ required property string column
+ required property string model
+ required property string hasModelChildren
+ required property string index
+ objectName: [modelData, row, column, model, hasModelChildren, index].join(" ")
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/persistedItemsCache.qml b/tests/auto/qml/qqmldelegatemodel/data/persistedItemsCache.qml
new file mode 100644
index 0000000000..5ae2038e1f
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/persistedItemsCache.qml
@@ -0,0 +1,62 @@
+import QtQuick
+import QtQuick.Window
+import QtQml.Models
+
+Window {
+ id: win
+ visible: true
+ width: 640
+ height: 480
+ property int destroyCount : 0;
+ property int createCount : 0;
+ property alias testListModel: mdl
+
+ DelegateModel {
+ id: visualModel
+ model: ListModel {
+ id: mdl
+ ListElement {
+ name: "a"
+ hidden: false
+ }
+ ListElement {
+ name: "b"
+ hidden: true
+ }
+ ListElement {
+ name: "c"
+ hidden: false
+ }
+ }
+
+ filterOnGroup: "selected"
+
+ groups: [
+ DelegateModelGroup {
+ name: "selected"
+ includeByDefault: true
+ }
+ ]
+
+ delegate: Text {
+ visible: DelegateModel.inSelected
+ property var idx
+ Component.onCompleted: {
+ ++createCount
+ idx = index
+ DelegateModel.inPersistedItems = true
+ DelegateModel.inSelected = !model.hidden
+ }
+ Component.onDestruction: ++destroyCount
+ text: model.name
+ }
+ }
+
+ ListView {
+ id: listView
+ model: visualModel
+ anchors.fill: parent
+ focus: true
+ }
+
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/requiredModelData.qml b/tests/auto/qml/qqmldelegatemodel/data/requiredModelData.qml
new file mode 100644
index 0000000000..467d60dff8
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/requiredModelData.qml
@@ -0,0 +1,50 @@
+import QtQml
+
+DelegateModel {
+ id: root
+
+ property ListModel singularModel: ListModel {
+ ListElement {
+ a: "a"
+ }
+ ListElement {
+ a: "a"
+ }
+ }
+
+ property ListModel listModel: ListModel {
+ ListElement {
+ a: "a"
+ b: "b"
+ }
+ ListElement {
+ a: "a"
+ b: "b"
+ }
+ }
+
+ property var array: [
+ {a: "a", b: "b"}, {a: "b", b: "b"}
+ ]
+
+ property QtObject object: QtObject {
+ property string a: "a"
+ property string b: "b"
+ }
+
+ property int n: -1
+
+ model: {
+ switch (n) {
+ case 0: return singularModel
+ case 1: return listModel
+ case 2: return array
+ case 3: return object
+ }
+ return undefined;
+ }
+
+ delegate: QtObject {
+ required property string a
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/resetModelData.qml b/tests/auto/qml/qqmldelegatemodel/data/resetModelData.qml
new file mode 100644
index 0000000000..1fe6168c79
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/resetModelData.qml
@@ -0,0 +1,16 @@
+import QtQuick
+
+ListView {
+ id: root
+ anchors.fill: parent
+ property bool success: (currentItem?.mydata ?? 0) === 42
+ height: 300
+ width: 200
+
+ delegate: Rectangle {
+ required property var model
+ implicitWidth: 100
+ implicitHeight: 50
+ property var mydata: model?.foo ?? model.bar
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/typedModelData.qml b/tests/auto/qml/qqmldelegatemodel/data/typedModelData.qml
new file mode 100644
index 0000000000..08f1c7d68e
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/typedModelData.qml
@@ -0,0 +1,64 @@
+import QtQml
+
+DelegateModel {
+ id: root
+
+ // useful object as model, int as modelData
+ property ListModel singularModel: ListModel {
+ ListElement {
+ x: 11
+ }
+ ListElement {
+ x: 12
+ }
+ }
+
+ // same, useful, object as model and modelData
+ property ListModel listModel: ListModel {
+ ListElement {
+ x: 13
+ y: 14
+ }
+ ListElement {
+ x: 15
+ y: 16
+ }
+ }
+
+ // useful but different objects as modelData and model
+ // This is how the array accessor works. We can live with it.
+ property var array: [
+ {x: 17, y: 18}, {x: 19, y: 20}
+ ]
+
+ // useful but different objects as modelData and model
+ // This is how the object accessor works. We can live with it.
+ property QtObject object: QtObject {
+ property int x: 21
+ property int y: 22
+ }
+
+ property int n: -1
+
+ model: {
+ switch (n) {
+ case 0: return singularModel
+ case 1: return listModel
+ case 2: return array
+ case 3: return object
+ }
+ return undefined;
+ }
+
+ delegate: QtObject {
+ required property point modelData
+ required property QtObject model
+
+ property real modelX: model.x
+ property real modelDataX: modelData.x
+ property point modelSelf: model
+ property point modelDataSelf: modelData
+ property point modelModelData: model.modelData
+ property point modelAnonymous: model[""]
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/universalModelData.qml b/tests/auto/qml/qqmldelegatemodel/data/universalModelData.qml
new file mode 100644
index 0000000000..f24009f873
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/universalModelData.qml
@@ -0,0 +1,72 @@
+import QtQml
+
+DelegateModel {
+ id: root
+
+ // useful object as model, string as modelData
+ property ListModel singularModel: ListModel {
+ ListElement {
+ a: "a"
+ }
+ ListElement {
+ a: "b"
+ }
+ }
+
+ // same, useful, object as model and modelData
+ property ListModel listModel: ListModel {
+ ListElement {
+ a: "a"
+ b: "a"
+ }
+ ListElement {
+ a: "b"
+ b: "b"
+ }
+ }
+
+ // useful but different objects as modelData and model
+ // This is how the array accessor works. We can live with it.
+ property var array: [
+ {a: "a", b: "a"}, {a: "b", b: "a"}
+ ]
+
+ // string as modelData
+ // object with anonymous string property as model.
+ property var stringList: ["a", "b"]
+
+ // useful but different objects as modelData and model
+ // This is how the object accessor works. We can live with it.
+ property QtObject object: QtObject {
+ property string a: "a"
+ property string b: "a"
+ }
+
+ // number as modelData
+ // object with anonymous number property as model
+ property int n: -1
+
+ model: {
+ switch (n) {
+ case 0: return singularModel
+ case 1: return listModel
+ case 2: return array
+ case 3: return stringList
+ case 4: return object
+ case 5: return n
+ }
+ return undefined;
+ }
+
+ delegate: QtObject {
+ required property var modelData
+ required property var model
+
+ property var modelA: model.a
+ property var modelDataA: modelData.a
+ property var modelSelf: model
+ property var modelDataSelf: modelData
+ property var modelModelData: model.modelData
+ property var modelAnonymous: model[""]
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/viewUpdatedOnDelegateChoiceAffectingRoleChange.qml b/tests/auto/qml/qqmldelegatemodel/data/viewUpdatedOnDelegateChoiceAffectingRoleChange.qml
new file mode 100644
index 0000000000..b2367b3a6e
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/viewUpdatedOnDelegateChoiceAffectingRoleChange.qml
@@ -0,0 +1,93 @@
+import QtQuick
+import Qt.labs.qmlmodels
+import QtQml.Models
+
+Item {
+ id: root
+ property bool triggered: false
+ onTriggeredChanged: {
+ rootLM.setProperty(1, "currentRole", "first");
+ }
+ width: 800
+ height: 680
+
+ function verify(): bool {
+ rootLV.currentIndex = 1; // needed for itemAtIndex to work
+ if (root.triggered)
+ return rootLV.itemAtIndex(0).isFirst && rootLV.itemAtIndex(1).isFirst;
+ else
+ return rootLV.itemAtIndex(0).isFirst && !rootLV.itemAtIndex(1).isFirst;
+ }
+
+ ListModel {
+ id: rootLM
+ ListElement {
+ currentRole: "first"
+ firstText: "TEXT_FIRST_1"
+ secondText: "TEXT_SECOND_1"
+ }
+ ListElement {
+ currentRole: "second"
+ firstText: "TEXT_FIRST_2"
+ secondText: "TEXT_SECOND_2"
+ }
+ }
+
+ DelegateModel {
+ id: delModel
+ model: rootLM
+ delegate: DelegateChooser {
+ id: delegateChooser
+ role: "currentRole"
+ DelegateChoice {
+ roleValue: "first"
+ Rectangle {
+ property bool isFirst: true
+ height: 30
+ width: rootLV.width
+ color: "yellow"
+ Text {
+ anchors.centerIn: parent
+ text: firstText + " " + currentRole
+ }
+ }
+ }
+ DelegateChoice {
+ roleValue: "second"
+ Rectangle {
+ property bool isFirst: false
+ height: 30
+ width: rootLV.width
+ color: "red"
+ Text {
+ anchors.centerIn: parent
+ text: secondText + " " + currentRole
+ }
+ }
+ }
+ }
+ }
+
+ TapHandler {
+ // for manual testing
+ onTapped: root.triggered = true
+ }
+
+ Rectangle {
+ width: 200
+ height: 300
+ anchors.centerIn: parent
+ border.color: "black"
+ border.width: 1
+ color: "blue"
+
+ ListView {
+ id: rootLV
+ objectName: "listview"
+ anchors.margins: 30
+ anchors.fill: parent
+ cacheBuffer: 0
+ model: delModel
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
index ca66ddb618..2cacda5513 100644
--- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
+++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
@@ -1,16 +1,21 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
+#include <QtCore/qjsonobject.h>
#include <QtCore/QConcatenateTablesProxyModel>
#include <QtGui/QStandardItemModel>
#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlapplicationengine.h>
#include <QtQmlModels/private/qqmldelegatemodel_p.h>
+#include <QtQmlModels/private/qqmllistmodel_p.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtTest/QSignalSpy>
+#include <forward_list>
+
class tst_QQmlDelegateModel : public QQmlDataTest
{
Q_OBJECT
@@ -19,6 +24,7 @@ public:
tst_QQmlDelegateModel();
private slots:
+ void resettingRolesRespected();
void valueWithoutCallingObjectFirst_data();
void valueWithoutCallingObjectFirst();
void qtbug_86017();
@@ -26,6 +32,16 @@ private slots:
void contextAccessedByHandler();
void redrawUponColumnChange();
void nestedDelegates();
+ void universalModelData();
+ void typedModelData();
+ void requiredModelData();
+ void overriddenModelData();
+ void deleteRace();
+ void persistedItemsStayInCache();
+ void unknownContainersAsModel();
+ void doNotUnrefObjectUnderConstruction();
+ void clearCacheDuringInsertion();
+ void viewUpdatedOnDelegateChoiceAffectingRoleChange();
};
class AbstractItemModel : public QAbstractItemModel
@@ -85,6 +101,61 @@ tst_QQmlDelegateModel::tst_QQmlDelegateModel()
qmlRegisterType<AbstractItemModel>("Test", 1, 0, "AbstractItemModel");
}
+class TableModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ int rowCount(const QModelIndex & = QModelIndex()) const override
+ {
+ return 1;
+ }
+
+ int columnCount(const QModelIndex & = QModelIndex()) const override
+ {
+ return 1;
+ }
+
+ QVariant data(const QModelIndex &index, int role) const override
+ {
+ switch (role) {
+ case 0:
+ return QString("foo: %1, %2").arg(index.column()).arg(index.row());
+ case 1:
+ return 42;
+ default:
+ break;
+ }
+
+ return QVariant();
+ }
+
+ Q_INVOKABLE void change() { beginResetModel(); toggle = !toggle; endResetModel(); }
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ if (toggle)
+ return { {0, "foo"} };
+ else
+ return { {1, "bar"} };
+ }
+
+ bool toggle = true;
+};
+
+void tst_QQmlDelegateModel::resettingRolesRespected()
+{
+ auto model = std::make_unique<TableModel>();
+ QQmlApplicationEngine engine;
+ engine.setInitialProperties({ {"model", QVariant::fromValue(model.get()) }} );
+ engine.load(testFileUrl("resetModelData.qml"));
+ QTRY_VERIFY(!engine.rootObjects().isEmpty());
+ QObject *root = engine.rootObjects().constFirst();
+ QVERIFY(!root->property("success").toBool());
+ model->change();
+ QTRY_VERIFY(root->property("success").toBool());
+}
+
void tst_QQmlDelegateModel::valueWithoutCallingObjectFirst_data()
{
QTest::addColumn<QUrl>("qmlFileUrl");
@@ -207,6 +278,344 @@ void tst_QQmlDelegateModel::nestedDelegates()
QFAIL("Loader not found");
}
+void tst_QQmlDelegateModel::universalModelData()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("universalModelData.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(o.data());
+ QVERIFY(delegateModel);
+
+ for (int i = 0; i < 6; ++i) {
+ delegateModel->setProperty("n", i);
+ QObject *delegate = delegateModel->object(0);
+ QObject *modelItem = delegate->property("modelSelf").value<QObject *>();
+ QVERIFY(modelItem != nullptr);
+ switch (i) {
+ case 0: {
+ // list model with 1 role
+ QCOMPARE(delegate->property("modelA"), QStringLiteral("a"));
+ QVERIFY(!delegate->property("modelDataA").isValid());
+ QCOMPARE(delegate->property("modelDataSelf"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelModelData"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelAnonymous"), QStringLiteral("a"));
+ break;
+ }
+ case 1: {
+ // list model with 2 roles
+ QCOMPARE(delegate->property("modelA"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelDataA"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelDataSelf"), QVariant::fromValue(modelItem));
+ QCOMPARE(delegate->property("modelModelData"), QVariant::fromValue(modelItem));
+ QCOMPARE(delegate->property("modelAnonymous"), QVariant::fromValue(modelItem));
+ break;
+ }
+ case 2: {
+ // JS array of objects
+ QCOMPARE(delegate->property("modelA"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelDataA"), QStringLiteral("a"));
+
+ // Do the comparison in QVariantMap. The values get converted back and forth a
+ // few times, making any JavaScript equality comparison impossible.
+ // This is only due to test setup, though.
+ const QVariantMap modelData = delegate->property("modelDataSelf").value<QVariantMap>();
+ QVERIFY(!modelData.isEmpty());
+ QCOMPARE(delegate->property("modelModelData").value<QVariantMap>(), modelData);
+ QCOMPARE(delegate->property("modelAnonymous").value<QVariantMap>(), modelData);
+ break;
+ }
+ case 3: {
+ // string list
+ QVERIFY(!delegate->property("modelA").isValid());
+ QVERIFY(!delegate->property("modelDataA").isValid());
+ QCOMPARE(delegate->property("modelDataSelf"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelModelData"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelAnonymous"), QStringLiteral("a"));
+ break;
+ }
+ case 4: {
+ // single object
+ QCOMPARE(delegate->property("modelA"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelDataA"), QStringLiteral("a"));
+ QObject *modelData = delegate->property("modelDataSelf").value<QObject *>();
+ QVERIFY(modelData != nullptr);
+ QCOMPARE(delegate->property("modelModelData"), QVariant::fromValue(modelData));
+ QCOMPARE(delegate->property("modelAnonymous"), QVariant::fromValue(modelData));
+ break;
+ }
+ case 5: {
+ // a number
+ QVERIFY(!delegate->property("modelA").isValid());
+ QVERIFY(!delegate->property("modelDataA").isValid());
+ const QVariant modelData = delegate->property("modelDataSelf");
+
+ // This is int on 32bit systems because qsizetype fits into int there.
+ // On 64bit systems it's double because qsizetype doesn't fit into int.
+ if (sizeof(qsizetype) > sizeof(int))
+ QCOMPARE(modelData.metaType(), QMetaType::fromType<double>());
+ else
+ QCOMPARE(modelData.metaType(), QMetaType::fromType<int>());
+
+ QCOMPARE(modelData.value<int>(), 0);
+ QCOMPARE(delegate->property("modelModelData"), modelData);
+ QCOMPARE(delegate->property("modelAnonymous"), modelData);
+ break;
+ }
+ default:
+ QFAIL("wrong model number");
+ break;
+ }
+ }
+
+}
+
+void tst_QQmlDelegateModel::typedModelData()
+{
+ QQmlEngine engine;
+ const QUrl url = testFileUrl("typedModelData.qml");
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(o.data());
+ QVERIFY(delegateModel);
+
+ for (int i = 0; i < 4; ++i) {
+ if (i == 0) {
+ for (int j = 0; j < 3; ++j) {
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "Could not find any constructor for value type QQmlPointFValueType "
+ "to call with value QVariant(double, 11)");
+ }
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":62:9: Unable to assign double to QPointF"));
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":61:9: Unable to assign double to QPointF"));
+ }
+
+ delegateModel->setProperty("n", i);
+ QObject *delegate = delegateModel->object(0);
+ QVERIFY(delegate);
+ const QPointF modelItem = delegate->property("modelSelf").value<QPointF>();
+ switch (i) {
+ case 0: {
+ // list model with 1 role.
+ // Does not work, for the most part, because the model is singular
+ QCOMPARE(delegate->property("modelX"), 11.0);
+ QCOMPARE(delegate->property("modelDataX"), 0.0);
+ QCOMPARE(delegate->property("modelSelf"), QPointF(11.0, 0.0));
+ QCOMPARE(delegate->property("modelDataSelf"), QPointF());
+ QCOMPARE(delegate->property("modelModelData"), QPointF());
+ QCOMPARE(delegate->property("modelAnonymous"), QPointF());
+ break;
+ }
+ case 1: {
+ // list model with 2 roles
+ QCOMPARE(delegate->property("modelX"), 13.0);
+ QCOMPARE(delegate->property("modelDataX"), 13.0);
+ QCOMPARE(delegate->property("modelSelf"), QVariant::fromValue(modelItem));
+ QCOMPARE(delegate->property("modelDataSelf"), QVariant::fromValue(modelItem));
+ QCOMPARE(delegate->property("modelModelData"), QVariant::fromValue(modelItem));
+ QCOMPARE(delegate->property("modelAnonymous"), QVariant::fromValue(modelItem));
+ break;
+ }
+ case 2: {
+ // JS array of objects
+ QCOMPARE(delegate->property("modelX"), 17.0);
+ QCOMPARE(delegate->property("modelDataX"), 17.0);
+
+ const QPointF modelData = delegate->property("modelDataSelf").value<QPointF>();
+ QCOMPARE(modelData, QPointF(17, 18));
+ QCOMPARE(delegate->property("modelSelf"), QVariant::fromValue(modelData));
+ QCOMPARE(delegate->property("modelModelData").value<QPointF>(), modelData);
+ QCOMPARE(delegate->property("modelAnonymous").value<QPointF>(), modelData);
+ break;
+ }
+ case 3: {
+ // single object
+ QCOMPARE(delegate->property("modelX"), 21);
+ QCOMPARE(delegate->property("modelDataX"), 21);
+ const QPointF modelData = delegate->property("modelDataSelf").value<QPointF>();
+ QCOMPARE(modelData, QPointF(21, 22));
+ QCOMPARE(delegate->property("modelSelf"), QVariant::fromValue(modelData));
+ QCOMPARE(delegate->property("modelModelData"), QVariant::fromValue(modelData));
+ QCOMPARE(delegate->property("modelAnonymous"), QVariant::fromValue(modelData));
+ break;
+ }
+ default:
+ QFAIL("wrong model number");
+ break;
+ }
+ }
+
+}
+
+void tst_QQmlDelegateModel::requiredModelData()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("requiredModelData.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(o.data());
+ QVERIFY(delegateModel);
+
+ for (int i = 0; i < 4; ++i) {
+ delegateModel->setProperty("n", i);
+ QObject *delegate = delegateModel->object(0);
+ QVERIFY(delegate);
+ const QVariant a = delegate->property("a");
+ QCOMPARE(a.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(a.toString(), QLatin1String("a"));
+ }
+}
+
+void tst_QQmlDelegateModel::overriddenModelData()
+{
+ QTest::failOnWarning(QRegularExpression(
+ "Final member [^ ]+ is overridden in class [^\\.]+. The override won't be used."));
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("overriddenModelData.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(o.data());
+ QVERIFY(delegateModel);
+
+ for (int i = 0; i < 3; ++i) {
+ delegateModel->setProperty("n", i);
+ QObject *delegate = delegateModel->object(0);
+ QVERIFY(delegate);
+
+ if (i == 1 || i == 2) {
+ // You can actually not override if the model is a QObject or a JavaScript array.
+ // Someone is certainly relying on this.
+ // We need to find a migration mechanism to fix it.
+ QCOMPARE(delegate->objectName(), QLatin1String(" 0 0 e 0"));
+ } else {
+ QCOMPARE(delegate->objectName(), QLatin1String("a b c d e f"));
+ }
+ }
+}
+
+void tst_QQmlDelegateModel::deleteRace()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("deleteRace.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QTRY_COMPARE(o->property("count").toInt(), 2);
+ QTRY_COMPARE(o->property("count").toInt(), 0);
+}
+
+void tst_QQmlDelegateModel::persistedItemsStayInCache()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("persistedItemsCache.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ std::unique_ptr<QObject> object(component.create());
+ QVERIFY(object);
+ const QVariant properyListModel = object->property("testListModel");
+ QQmlListModel *listModel = qvariant_cast<QQmlListModel *>(properyListModel);
+ QVERIFY(listModel);
+ QTRY_COMPARE(object->property("createCount").toInt(), 3);
+ listModel->clear();
+ QTRY_COMPARE(object->property("destroyCount").toInt(), 3);
+}
+
+Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::forward_list)
+void tst_QQmlDelegateModel::unknownContainersAsModel()
+{
+ QQmlEngine engine;
+
+ QQmlComponent modelComponent(&engine);
+ modelComponent.setData("import QtQml.Models\nDelegateModel {}\n", QUrl());
+ QCOMPARE(modelComponent.status(), QQmlComponent::Ready);
+
+ QScopedPointer<QObject> o(modelComponent.create());
+ QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel*>(o.data());
+ QVERIFY(delegateModel);
+
+ QQmlComponent delegateComponent(&engine);
+ delegateComponent.setData("import QtQml\nQtObject { objectName: modelData }\n", QUrl());
+ QCOMPARE(delegateComponent.status(), QQmlComponent::Ready);
+
+ delegateModel->setDelegate(&delegateComponent);
+
+ QList<QJsonObject> json;
+ for (int i = 0; i < 10; ++i)
+ json.append(QJsonObject({{"foo", i}}));
+
+ // Recognized as list
+ delegateModel->setModel(QVariant::fromValue(json));
+ QObject *obj = delegateModel->object(0, QQmlIncubator::Synchronous);
+ QVERIFY(obj);
+ QCOMPARE(delegateModel->count(), 10);
+ QCOMPARE(delegateModel->model().metaType(), QMetaType::fromType<QList<QJsonObject>>());
+
+ QVERIFY(qMetaTypeId<std::forward_list<int>>() > 0);
+ std::forward_list<int> mess;
+ mess.push_front(4);
+ mess.push_front(5);
+ mess.push_front(6);
+
+ // Converted into QVariantList
+ delegateModel->setModel(QVariant::fromValue(mess));
+ obj = delegateModel->object(0, QQmlIncubator::Synchronous);
+ QVERIFY(obj);
+ QCOMPARE(delegateModel->count(), 3);
+ QCOMPARE(delegateModel->model().metaType(), QMetaType::fromType<QVariantList>());
+}
+
+void tst_QQmlDelegateModel::doNotUnrefObjectUnderConstruction()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("modifyObjectUnderConstruction.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ std::unique_ptr<QObject> object(component.create());
+ QVERIFY(object);
+ QTRY_COMPARE(object->property("testModel").toInt(), 0);
+}
+
+void tst_QQmlDelegateModel::clearCacheDuringInsertion()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("clearCacheDuringInsertion.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ std::unique_ptr<QObject> object(component.create());
+ QVERIFY(object);
+ QTRY_COMPARE(object->property("testModel").toInt(), 0);
+}
+
+void tst_QQmlDelegateModel::viewUpdatedOnDelegateChoiceAffectingRoleChange()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("viewUpdatedOnDelegateChoiceAffectingRoleChange.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ std::unique_ptr<QObject> object(component.create());
+ QVERIFY(object);
+ QQuickItem *listview = object->findChild<QQuickItem *>("listview");
+ QVERIFY(listview);
+ QTRY_VERIFY(listview->property("count").toInt() > 0);
+ bool returnedValue = false;
+ QMetaObject::invokeMethod(object.get(), "verify", Q_RETURN_ARG(bool, returnedValue));
+ QVERIFY(returnedValue);
+ returnedValue = false;
+
+ object->setProperty("triggered", "true");
+ QTRY_VERIFY(listview->property("count").toInt() > 0);
+ QMetaObject::invokeMethod(object.get(), "verify", Q_RETURN_ARG(bool, returnedValue));
+ QVERIFY(returnedValue);
+}
+
QTEST_MAIN(tst_QQmlDelegateModel)
#include "tst_qqmldelegatemodel.moc"
diff --git a/tests/auto/qml/qqmldirparser/CMakeLists.txt b/tests/auto/qml/qqmldirparser/CMakeLists.txt
index 0ed28b63ee..d7738c08f8 100644
--- a/tests/auto/qml/qqmldirparser/CMakeLists.txt
+++ b/tests/auto/qml/qqmldirparser/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldirparser Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldirparser LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmldirparser/data/versioned-internal/qmldir b/tests/auto/qml/qqmldirparser/data/versioned-internal/qmldir
new file mode 100644
index 0000000000..3a3e606099
--- /dev/null
+++ b/tests/auto/qml/qqmldirparser/data/versioned-internal/qmldir
@@ -0,0 +1,3 @@
+module MyModule
+internal InternalType 1.0 InternalType.qml
+
diff --git a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp
index 55b776c6a2..4cbb7aaf47 100644
--- a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp
+++ b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QObject>
@@ -60,7 +60,7 @@ namespace {
{
QStringList rv;
- foreach (const QQmlDirParser::Plugin &p, plugins)
+ for (const QQmlDirParser::Plugin &p : plugins)
rv.append(toString(p));
return rv;
@@ -86,7 +86,8 @@ namespace {
{
QStringList rv;
- foreach (const QQmlDirParser::Component &c, components.values())
+ const auto values = components.values();
+ for (const QQmlDirParser::Component &c : values)
rv.append(toString(c));
std::sort(rv.begin(), rv.end());
@@ -97,7 +98,7 @@ namespace {
{
QStringList rv;
- foreach (const QQmlDirParser::Import &c, components)
+ for (const QQmlDirParser::Import &c : components)
rv.append(toString(c));
std::sort(rv.begin(), rv.end());
@@ -115,7 +116,7 @@ namespace {
{
QStringList rv;
- foreach (const QQmlDirParser::Script &s, scripts)
+ for (const QQmlDirParser::Script &s : scripts)
rv.append(toString(s));
return rv;
@@ -421,6 +422,17 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< QStringList()
<< false;
+
+ QTest::newRow("versioned-internal")
+ << "versioned-internal/qmldir"
+ << QString()
+ << QStringList()
+ << QStringList()
+ << QStringList()
+ << QStringList({"InternalType|InternalType.qml|1|0|true"})
+ << QStringList()
+ << QStringList()
+ << false;
}
void tst_qqmldirparser::parse()
@@ -435,7 +447,7 @@ void tst_qqmldirparser::parse()
QFETCH(bool, designerSupported);
QFile f(testFile(file));
- f.open(QIODevice::ReadOnly);
+ QVERIFY(f.open(QIODevice::ReadOnly));
QQmlDirParser p;
p.parse(f.readAll());
diff --git a/tests/auto/qml/qqmlecmascript/CMakeLists.txt b/tests/auto/qml/qqmlecmascript/CMakeLists.txt
index f4b4169c82..12cab47a36 100644
--- a/tests/auto/qml/qqmlecmascript/CMakeLists.txt
+++ b/tests/auto/qml/qqmlecmascript/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlecmascript Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlecmascript LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -24,6 +30,7 @@ qt_internal_add_test(tst_qqmlecmascript
Qt::Network
Qt::QmlPrivate
Qt::QuickTestUtilsPrivate
+ Qt::QuickPrivate
TESTDATA ${test_data}
)
diff --git a/tests/auto/qml/qqmlecmascript/data/AssignListPropertyByIndexOnGadget.qml b/tests/auto/qml/qqmlecmascript/data/AssignListPropertyByIndexOnGadget.qml
new file mode 100644
index 0000000000..f8ee283f1e
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/AssignListPropertyByIndexOnGadget.qml
@@ -0,0 +1,20 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+import Qt.test
+
+QtObject {
+ property listPropertyAssignment_Gadget gadget
+ property ListPropertyAssignment_Object object: ListPropertyAssignment_Object { }
+
+ Component.onCompleted: {
+ gadget.gadgetStringList = ["Element1", "Element2", "Element3"]
+ gadget.gadgetVariantList = [1, "foo", null, true]
+ object.qobjectStringList = ["Element1", "Element2", "Element3"]
+
+ gadget.gadgetStringList[0] = "Completely new Element"
+ gadget.gadgetVariantList[0] = "Completely new Element"
+ object.qobjectStringList[0] = "Completely new Element"
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/PropertyVarCircularComponent4.qml b/tests/auto/qml/qqmlecmascript/data/PropertyVarCircularComponent4.qml
index 9273a52f54..ff7fe4434c 100644
--- a/tests/auto/qml/qqmlecmascript/data/PropertyVarCircularComponent4.qml
+++ b/tests/auto/qml/qqmlecmascript/data/PropertyVarCircularComponent4.qml
@@ -22,7 +22,6 @@ Rectangle {
if (component.status == Component.Ready) {
text.vp = component.createObject(null); // has JavaScript ownership
}
- gc();
}
}
}
diff --git a/tests/auto/qml/qqmlecmascript/data/PropertyVarOwnershipComponent.qml b/tests/auto/qml/qqmlecmascript/data/PropertyVarOwnershipComponent.qml
index f4307081c5..4e8da872f5 100644
--- a/tests/auto/qml/qqmlecmascript/data/PropertyVarOwnershipComponent.qml
+++ b/tests/auto/qml/qqmlecmascript/data/PropertyVarOwnershipComponent.qml
@@ -25,7 +25,6 @@ Rectangle {
if (component.status == Component.Ready) {
textTwo.vp = component.createObject(null); // has JavaScript ownership
}
- gc();
}
function deassignVp() {
diff --git a/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.3.qml b/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.3.qml
deleted file mode 100644
index d611e0fe30..0000000000
--- a/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.3.qml
+++ /dev/null
@@ -1,12 +0,0 @@
-import QtQuick 2.0
-
-Item {
- property int changeCount: 0
-
- // invalid property name - we don't allow $
- property bool $nameWithDollarsign: false
-
- on$NameWithDollarsignChanged: {
- changeCount = changeCount + 4;
- }
-}
diff --git a/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.4.qml b/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.4.qml
deleted file mode 100644
index a6862517c6..0000000000
--- a/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.4.qml
+++ /dev/null
@@ -1,12 +0,0 @@
-import QtQuick 2.0
-
-Item {
- property int changeCount: 0
-
- property bool _6nameWithUnderscoreNumber: false
-
- // invalid property name - the first character after an underscore must be a letter
- on_6NameWithUnderscoreNumberChanged: {
- changeCount = changeCount + 3;
- }
-}
diff --git a/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlots.qml b/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlots.qml
index f91fb71f1f..9a3141e15a 100644
--- a/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlots.qml
+++ b/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlots.qml
@@ -6,6 +6,8 @@ Item {
property bool normalName: false
property bool _nameWithUnderscore: false
property bool ____nameWithUnderscores: false
+ property bool _6nameWithUnderscoreNumber: false
+ property bool $nameWithDollarsign: false
onNormalNameChanged: {
changeCount = changeCount + 1;
@@ -19,9 +21,20 @@ Item {
changeCount = changeCount + 3;
}
+ on$NameWithDollarsignChanged: {
+ changeCount = changeCount + 4;
+ }
+
+ on_6NameWithUnderscoreNumberChanged: {
+ changeCount = changeCount + 5;
+ }
+
Component.onCompleted: {
normalName = true;
_nameWithUnderscore = true;
____nameWithUnderscores = true;
+ $nameWithDollarsign = true;
+ _6nameWithUnderscoreNumber = true;
}
+
}
diff --git a/tests/auto/qml/qqmlecmascript/data/date.qml b/tests/auto/qml/qqmlecmascript/data/date.qml
index 8e190b1f8f..33644b604d 100644
--- a/tests/auto/qml/qqmlecmascript/data/date.qml
+++ b/tests/auto/qml/qqmlecmascript/data/date.qml
@@ -26,8 +26,12 @@ Item {
function check_value(date, tag, qdt) {
var result = true;
+ if (isNaN(date)) {
+ console.warn("Invalid Date");
+ return false;
+ }
if (date.getFullYear() != 2014) {
- console.warn("Wrong year (" + tag + "):", date.getFullYear(), "!= 2014")
+ console.warn("Wrong year (" + tag + "):", date.getFullYear(), "!= 2014");
result = false;
}
// July; JS's months are Jan 0 to 11 Dec, vs. Qt's 1 to 12.
diff --git a/tests/auto/qml/qqmlecmascript/data/frozenQObject3.qml b/tests/auto/qml/qqmlecmascript/data/frozenQObject3.qml
new file mode 100644
index 0000000000..51c321684e
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/frozenQObject3.qml
@@ -0,0 +1,30 @@
+import QtQml
+import test
+
+QtObject {
+ id: root
+
+ property FrozenObjects a: FrozenObjects { objectName: "a" }
+ property FrozenObjects b: FrozenObjects { objectName: "b" }
+
+ // Create wrappers and immediately discard them
+ objectName: a.getConst().objectName + "/" + b.getNonConst().objectName
+
+ // Create a non-const wrapper and retain it
+ property var objNonConst: a.getNonConst()
+
+ // Create a const wrapper and retain it
+ property var objConst: b.getConst()
+
+ property int gcs: 0
+
+ property Timer t: Timer {
+ interval: 1
+ running: true
+ repeat: true
+ onTriggered: {
+ gc();
+ ++root.gcs;
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/getThis.qml b/tests/auto/qml/qqmlecmascript/data/getThis.qml
index db9854e872..90c51caf4d 100644
--- a/tests/auto/qml/qqmlecmascript/data/getThis.qml
+++ b/tests/auto/qml/qqmlecmascript/data/getThis.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.12
diff --git a/tests/auto/qml/qqmlecmascript/data/lookupsDoNotBypassProxy.qml b/tests/auto/qml/qqmlecmascript/data/lookupsDoNotBypassProxy.qml
new file mode 100644
index 0000000000..321bd21ad8
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/lookupsDoNotBypassProxy.qml
@@ -0,0 +1,29 @@
+import QtQml
+
+QtObject {
+ function test_proxy() {
+ let base = {
+ id: 'baseid',
+ name: 'basename',
+ length: 42
+ };
+
+ let handler = {
+ get: function (ao, prop) {
+ return Reflect.get(ao, prop);
+ }
+ };
+
+ let r = new Proxy(base, handler);
+ let validCount = 0;
+ if (r.id === base.id)
+ ++validCount;
+ if (r.length === base.length)
+ ++validCount;
+ if (r.name === base.name)
+ ++validCount;
+ return validCount;
+ }
+
+ property int result: test_proxy()
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/methodCallOnDerivedSingleton.qml b/tests/auto/qml/qqmlecmascript/data/methodCallOnDerivedSingleton.qml
new file mode 100644
index 0000000000..9d2ee433fd
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/methodCallOnDerivedSingleton.qml
@@ -0,0 +1,6 @@
+import Qt.test
+import QtQml
+
+QtObject {
+ Component.onCompleted: SingletonInheritanceTest.trackPage("test", {x: 42})
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/propertyVar.reparent.qml b/tests/auto/qml/qqmlecmascript/data/propertyVar.reparent.qml
index 6f5094de27..5f017c4880 100644
--- a/tests/auto/qml/qqmlecmascript/data/propertyVar.reparent.qml
+++ b/tests/auto/qml/qqmlecmascript/data/propertyVar.reparent.qml
@@ -16,7 +16,6 @@ Item {
function assignVarProp() {
vp = constructGarbage();
- gc();
}
function deassignVarProp() {
diff --git a/tests/auto/qml/qqmlecmascript/data/propertyVarImplicitOwnership.qml b/tests/auto/qml/qqmlecmascript/data/propertyVarImplicitOwnership.qml
index ecc4892334..144fcc8a93 100644
--- a/tests/auto/qml/qqmlecmascript/data/propertyVarImplicitOwnership.qml
+++ b/tests/auto/qml/qqmlecmascript/data/propertyVarImplicitOwnership.qml
@@ -16,7 +16,6 @@ Item {
function assignCircular() {
vp = constructGarbage();
- gc();
}
function deassignCircular() {
diff --git a/tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs3.qml b/tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs3.qml
new file mode 100644
index 0000000000..a50c8e0f46
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs3.qml
@@ -0,0 +1,12 @@
+import QtQml
+import Qt.test.singletonWithEnum
+
+QtObject {
+ id: root
+ required property QtObject invokableObject
+
+ Component.onCompleted: {
+ root.invokableObject.method_typeWrapper(Component)
+ root.invokableObject.method_typeWrapper(SingletonWithEnum)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/qpropertyResetCorrectlyLinked.qml b/tests/auto/qml/qqmlecmascript/data/qpropertyResetCorrectlyLinked.qml
new file mode 100644
index 0000000000..490fec2dc8
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qpropertyResetCorrectlyLinked.qml
@@ -0,0 +1,8 @@
+import QtQuick
+
+Item {
+ property var val: undefined
+ property var observes: width
+ width: val
+ implicitWidth: 200
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/resetGadget.qml b/tests/auto/qml/qqmlecmascript/data/resetGadget.qml
new file mode 100644
index 0000000000..2bc196da34
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/resetGadget.qml
@@ -0,0 +1,9 @@
+import Qt.test
+
+ResettableGadgetHolder {
+ id: root
+ property bool trigger: false
+ onTriggerChanged: {
+ root.g.value = undefined
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/restoreObserverAfterReset.qml b/tests/auto/qml/qqmlecmascript/data/restoreObserverAfterReset.qml
new file mode 100644
index 0000000000..2933d9b4d5
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/restoreObserverAfterReset.qml
@@ -0,0 +1,20 @@
+import QtQuick
+
+Item {
+ height: undefined
+ implicitHeight: 30
+ property int steps: 0
+
+ Behavior on height {
+ NumberAnimation {
+ duration: 500
+ }
+ }
+
+ onHeightChanged: ++steps
+
+ Component.onCompleted: {
+ height = Qt.binding(() => implicitHeight);
+ implicitHeight = 60;
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.8.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.8.qml
new file mode 100644
index 0000000000..7d43aa6c05
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.8.qml
@@ -0,0 +1,21 @@
+import Qt.test
+import QtQuick
+
+Item {
+ id: root
+ property int count: 0
+ signal someSignal
+
+ property Item item: Item {
+ id: contextItem
+ function test() {
+ count++;
+ }
+ }
+
+ function itemDestroy() {
+ contextItem.destroy()
+ }
+
+ Component.onCompleted: root.someSignal.connect(contextItem, contextItem.test);
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.9.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.9.qml
new file mode 100644
index 0000000000..1123edf3f7
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.9.qml
@@ -0,0 +1,30 @@
+import Qt.test
+import QtQuick
+
+MyQmlObject {
+ id: root
+ property int a: 0
+
+ signal someSignal
+
+ function disconnectSignal() {
+ root.someSignal.disconnect(other.MyQmlObject, root.test)
+ }
+
+ function destroyObj() {
+ other.destroy()
+ }
+
+ function test() {
+ other.MyQmlObject.value2++
+ root.a = other.MyQmlObject.value2
+ }
+
+ property MyQmlObject obj
+ obj: MyQmlObject {
+ id: other
+ MyQmlObject.value2: 0
+ }
+
+ Component.onCompleted: root.someSignal.connect(other.MyQmlObject, root.test)
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.deletion.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.deletion.qml
new file mode 100644
index 0000000000..efbbc9fedc
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.deletion.qml
@@ -0,0 +1,36 @@
+import Qt.test
+import QtQml
+
+QtObject {
+ id: root
+
+ property int a: 0
+ property int b: 0
+
+ signal someSignal
+
+ function destroyObj() {
+ obj.destroy()
+ }
+
+ function test() {
+ ++a
+ }
+
+ component DestructionReceiver: QtObject {
+ // Has its own context and therefore can receive Component.onDestruction
+ }
+
+ property QtObject obj: QtObject {
+ property QtObject inner: DestructionReceiver {
+ Component.onDestruction: {
+ // The outer obj is already queued for deletion.
+ // We don't want to see this signal delivered.
+ root.someSignal();
+ ++root.b
+ }
+ }
+ }
+
+ Component.onCompleted: someSignal.connect(obj, test)
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnectSingleton.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnectSingleton.qml
new file mode 100644
index 0000000000..f666945b33
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/scriptConnectSingleton.qml
@@ -0,0 +1,21 @@
+import QtQuick
+import Test
+
+Item {
+ id: root
+
+ property int a: 0
+ signal mySignal
+
+ function test() {
+ MyInheritedQmlObjectSingleton.value++
+ root.a = MyInheritedQmlObjectSingleton.value
+ }
+
+ function disconnectSingleton() {
+ root.mySignal.disconnect(MyInheritedQmlObjectSingleton, root.test)
+ }
+
+ Component.onCompleted: root.mySignal.connect(MyInheritedQmlObjectSingleton,
+ root.test)
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.5.qml b/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.5.qml
new file mode 100644
index 0000000000..9d24fa85ae
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.5.qml
@@ -0,0 +1,19 @@
+import Qt.test
+import QtQuick
+
+Item {
+ id: root
+ property int count: 0
+ signal someSignal
+ signal disconnectSignal
+
+ property Item item: Item {
+ id: contextItem
+ function test() {
+ count++;
+ }
+ }
+
+ Component.onCompleted: root.someSignal.connect(contextItem, contextItem.test);
+ onDisconnectSignal: { root.someSignal.disconnect(contextItem, contextItem.test); }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/singletonTest.qml b/tests/auto/qml/qqmlecmascript/data/singletonTest.qml
index b0e951b89a..f4bdcdbed3 100644
--- a/tests/auto/qml/qqmlecmascript/data/singletonTest.qml
+++ b/tests/auto/qml/qqmlecmascript/data/singletonTest.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2013 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import Test 1.0
diff --git a/tests/auto/qml/qqmlecmascript/data/singletonTest2.qml b/tests/auto/qml/qqmlecmascript/data/singletonTest2.qml
index 5a5bad5b8c..5d6af4d67c 100644
--- a/tests/auto/qml/qqmlecmascript/data/singletonTest2.qml
+++ b/tests/auto/qml/qqmlecmascript/data/singletonTest2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2013 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import Test 1.0
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp
index 40f5e5cf5c..5f7713392b 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.cpp
+++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include "testtypes.h"
#ifndef QT_NO_WIDGETS
# include <QWidget>
@@ -8,6 +9,7 @@
#include <QQmlEngine>
#include <QJSEngine>
#include <QThread>
+#include <QtQuickTestUtils/private/qmlutils_p.h>
class BaseExtensionObject : public QObject
{
@@ -104,7 +106,7 @@ public:
void setWidth(int) { }
};
-void MyQmlObject::v8function(QQmlV4Function *function)
+void MyQmlObject::v8function(QQmlV4FunctionPtr function)
{
function->v4engine()->throwError(QStringLiteral("Exception thrown from within QObject slot"));
}
@@ -393,9 +395,7 @@ void QObjectContainer::children_append(QQmlListProperty<QObject> *prop, QObject
if (that->gcOnAppend) {
QQmlEngine *engine = qmlEngine(that);
- engine->collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(*engine);
}
}
@@ -412,7 +412,7 @@ QObject *QObjectContainer::children_at(QQmlListProperty<QObject> *prop, qsizetyp
void QObjectContainer::children_clear(QQmlListProperty<QObject> *prop)
{
QObjectContainer *that = static_cast<QObjectContainer*>(prop->object);
- foreach (QObject *c, that->dataChildren)
+ for (QObject *c : std::as_const(that->dataChildren))
QObject::disconnect(c, SIGNAL(destroyed(QObject*)), that, SLOT(childDestroyed(QObject*)));
that->dataChildren.clear();
}
@@ -436,6 +436,44 @@ void ClassWithQProperty2::callback()
// Q_UNUSED(this->value.value()); // force evaluation
}
+ListPropertyAssignment_Gadget::ListPropertyAssignment_Gadget() { }
+
+QStringList ListPropertyAssignment_Gadget::gadgetStringList() const
+{
+ return m_gadgetStringList;
+}
+
+void ListPropertyAssignment_Gadget::setGadgetStringList(const QStringList &list)
+{
+ if (m_gadgetStringList == list)
+ return;
+ m_gadgetStringList = list;
+}
+
+QVariantList ListPropertyAssignment_Gadget::gadgetVariantList() const
+{
+ return m_gadgetVariantList;
+}
+
+void ListPropertyAssignment_Gadget::setGadgetVariantList(const QVariantList &list)
+{
+ if (m_gadgetVariantList == list)
+ return;
+ m_gadgetVariantList = list;
+}
+
+ListPropertyAssignment_Object::ListPropertyAssignment_Object(QObject *parent)
+ : QObject{ parent } { }
+
+void ListPropertyAssignment_Object::setQobjectStringList(const QStringList &newList)
+{
+ if (m_qobjectStringList == newList)
+ return;
+ m_qobjectStringList = newList;
+}
+
+bool MetaCallInterceptor::didGetObjectDestroyedCallback = false;
+
void registerTypes()
{
qmlRegisterType<MyQmlObject>("Qt.test", 1,0, "MyQmlObjectAlias");
@@ -542,6 +580,15 @@ void registerTypes()
qmlRegisterType<Receiver>("Qt.test", 1,0, "Receiver");
qmlRegisterType<Sender>("Qt.test", 1,0, "Sender");
qmlRegisterTypesAndRevisions<ReadOnlyBindable>("Qt.test", 1);
+ qmlRegisterTypesAndRevisions<ResettableGadgetHolder>("Qt.test", 1);
+
+ qmlRegisterTypesAndRevisions<ListPropertyAssignment_Gadget>("Qt.test", 1);
+ qmlRegisterTypesAndRevisions<ListPropertyAssignment_Object>("Qt.test", 1);
+
+ qmlRegisterTypesAndRevisions<SingletonRegistrationWrapper>("Qt.test", 1);
+
+ qmlRegisterExtendedType<TypeWithCustomMetaObject, TypeToTriggerProxyMetaObject>(
+ "Qt.test", 1,0, "TypeWithCustomMetaObject");
}
#include "testtypes.moc"
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
index ff9dda36d1..cc20437fff 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.h
+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPES_H
#define TESTTYPES_H
@@ -31,6 +31,7 @@
#include <private/qqmlengine_p.h>
#include <private/qv4qobjectwrapper_p.h>
+#include <private/qqmlcomponentattached_p.h>
class MyQmlAttachedObject : public QObject
{
@@ -243,7 +244,7 @@ public slots:
void myinvokable(MyQmlObject *o) { myinvokableObject = o; }
void variantMethod(const QVariant &v) { m_variant = v; }
void qjsvalueMethod(const QJSValue &v) { m_qjsvalue = v; }
- void v8function(QQmlV4Function*);
+ void v8function(QQmlV4FunctionPtr);
void registeredFlagMethod(Qt::MouseButtons v) { m_buttons = v; }
QString slotWithReturnValue(const QString &arg) { return arg; }
int resetCount() { return m_resetCount; }
@@ -862,6 +863,17 @@ struct NonRegisteredType
struct CompletelyUnknown;
+class SingletonWithEnum : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(TestEnum)
+public:
+ enum TestEnum {
+ TestValue = 42,
+ TestValue_MinusOne = -1
+ };
+};
+
class MyInvokableObject : public MyInvokableBaseObject
{
Q_OBJECT
@@ -919,7 +931,7 @@ public:
Q_INVOKABLE void method_unknown(NonRegisteredType) { invoke(28); }
- Q_INVOKABLE void method_overload2(QQmlV4Function *v)
+ Q_INVOKABLE void method_overload2(QQmlV4FunctionPtr v)
{
invoke(31);
QV4::Scope scope(v->v4engine());
@@ -955,12 +967,43 @@ public:
invoke(40);
m_actuals << f;
}
+
Q_INVOKABLE void method_qobject(QObject *o)
{
invoke(41);
m_actuals << QVariant::fromValue(o);
}
+ Q_INVOKABLE QQmlComponent *someComponent() { return &m_someComponent; }
+ Q_INVOKABLE void method_component(QQmlComponent *c)
+ {
+ invoke(42);
+ m_actuals << QVariant::fromValue(c);
+ }
+
+ Q_INVOKABLE MyTypeObject *someTypeObject() { return &m_someTypeObject; }
+ Q_INVOKABLE void method_component(MyTypeObject *c)
+ {
+ invoke(43);
+ m_actuals << QVariant::fromValue(c);
+ }
+
+ Q_INVOKABLE void method_component(const QUrl &c)
+ {
+ invoke(44);
+ m_actuals << QVariant::fromValue(c);
+ }
+
+ Q_INVOKABLE void method_typeWrapper(QQmlComponentAttached *attached)
+ {
+ m_actuals << QVariant::fromValue(attached);
+ }
+
+ Q_INVOKABLE void method_typeWrapper(SingletonWithEnum *singleton)
+ {
+ m_actuals << QVariant::fromValue(singleton);
+ }
+
private:
friend class MyInvokableBaseObject;
void invoke(int idx) { if (m_invoked != -1) m_invokedError = true; m_invoked = idx;}
@@ -969,6 +1012,8 @@ private:
QVariantList m_actuals;
QFont m_someFont;
+ QQmlComponent m_someComponent;
+ MyTypeObject m_someTypeObject;
public:
Q_SIGNALS:
@@ -1807,17 +1852,6 @@ public:
QML_DECLARE_TYPEINFO(FallbackBindingsTypeObject, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPEINFO(FallbackBindingsTypeDerived, QML_HAS_ATTACHED_PROPERTIES)
-class SingletonWithEnum : public QObject
-{
- Q_OBJECT
- Q_ENUMS(TestEnum)
-public:
- enum TestEnum {
- TestValue = 42,
- TestValue_MinusOne = -1
- };
-};
-
// Like QtObject, but with default property
class QObjectContainer : public QObject
{
@@ -2000,6 +2034,161 @@ public:
QBindable<int> bindableX() const { return &_xProp; }
};
+class ResettableGadget
+{
+ Q_GADGET
+ Q_PROPERTY(qreal value READ value WRITE setValue RESET resetValue)
+
+ qreal m_value = 0;
+
+public:
+ qreal value() const { return m_value; }
+ void setValue(qreal val) { m_value = val; }
+ void resetValue() { m_value = 42; }
+};
+
+class ResettableGadgetHolder : public QObject {
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(ResettableGadget g READ g WRITE setG NOTIFY gChanged)
+ ResettableGadget m_g;
+
+signals:
+ void gChanged();
+
+public:
+ ResettableGadget g() const { return m_g; }
+ void setG(ResettableGadget newG)
+ {
+ if (m_g.value() == newG.value())
+ return;
+ m_g = newG;
+ Q_EMIT gChanged();
+ }
+};
+
+class ListPropertyAssignment_Gadget
+{
+ Q_GADGET
+ Q_PROPERTY(QStringList gadgetStringList READ gadgetStringList WRITE setGadgetStringList)
+ Q_PROPERTY(QVariantList gadgetVariantList READ gadgetVariantList WRITE setGadgetVariantList)
+ QML_VALUE_TYPE(listPropertyAssignment_Gadget)
+public:
+ ListPropertyAssignment_Gadget();
+ QStringList gadgetStringList() const;
+ void setGadgetStringList(const QStringList &list);
+
+ QVariantList gadgetVariantList() const;
+ void setGadgetVariantList(const QVariantList &list);
+
+private:
+ QStringList m_gadgetStringList;
+ QVariantList m_gadgetVariantList;
+};
+
+class ListPropertyAssignment_Object : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(QStringList qobjectStringList READ qobjectStringList WRITE setQobjectStringList)
+public:
+ explicit ListPropertyAssignment_Object(QObject *parent = nullptr);
+
+ QStringList qobjectStringList() const { return m_qobjectStringList; }
+
+ void setQobjectStringList(const QStringList &newList);
+
+private:
+ QStringList m_qobjectStringList;
+};
+
+class SingletonBase : public QObject {
+ Q_OBJECT
+
+public:
+ Q_INVOKABLE virtual void trackPage(const QString&) {}
+ Q_INVOKABLE virtual void trackPage(const QString&, const QVariantMap&) {}
+
+ bool m_okay = false;
+};
+
+class SingletonImpl : public SingletonBase {
+ Q_OBJECT
+
+public:
+ Q_INVOKABLE virtual void trackPage(const QString&) override {}
+ Q_INVOKABLE virtual void trackPage(const QString&, const QVariantMap&) override
+ {
+ m_okay = true;
+ }
+};
+
+class SingletonRegistrationWrapper {
+ Q_GADGET
+ QML_FOREIGN(SingletonBase)
+ QML_NAMED_ELEMENT(SingletonInheritanceTest)
+ QML_SINGLETON
+
+public:
+ static SingletonBase* create(QQmlEngine*, QJSEngine*) {
+ return new SingletonImpl();
+ }
+
+private:
+ SingletonRegistrationWrapper() = default;
+};
+
+class MetaCallInterceptor : public QObject, public QDynamicMetaObjectData
+{
+ Q_OBJECT
+public:
+ MetaCallInterceptor()
+ {
+ didGetObjectDestroyedCallback = false;
+ }
+
+ void objectDestroyed(QObject *object) override
+ {
+ didGetObjectDestroyedCallback = true;
+
+ // Deletes this meta object
+ QDynamicMetaObjectData::objectDestroyed(object);
+ }
+
+ QMetaObject *toDynamicMetaObject(QObject *) override
+ {
+ return const_cast<QMetaObject *>(&MetaCallInterceptor::staticMetaObject);
+ }
+
+ int metaCall(QObject *o, QMetaObject::Call call, int idx, void **argv) override
+ {
+ return o->qt_metacall(call, idx, argv);
+ }
+
+ static bool didGetObjectDestroyedCallback;
+};
+
+struct TypeToTriggerProxyMetaObject
+{
+ Q_GADGET
+};
+
+class TypeWithCustomMetaObject : public QObject
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(TypeWithCustomMetaObject)
+ QML_EXTENDED_NAMESPACE(TypeToTriggerProxyMetaObject)
+
+public:
+ TypeWithCustomMetaObject()
+ {
+ auto *p = QObjectPrivate::get(this);
+ Q_ASSERT(!p->metaObject);
+ p->metaObject = new MetaCallInterceptor;
+ }
+};
+
void registerTypes();
#endif // TESTTYPES_H
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index edb1e9ba80..2d124da279 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -1,6 +1,7 @@
// Copyright (C) 2017 Crimson AS <info@crimson.no>
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <QtTest/QtTest>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlengine.h>
@@ -27,6 +28,8 @@
#include <private/qqmlabstractbinding_p.h>
#include <private/qqmlvaluetypeproxybinding_p.h>
#include <QtCore/private/qproperty_p.h>
+#include <QtQuick/qquickwindow.h>
+#include <QtQuick/private/qquickitem_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/testhttpserver_p.h>
@@ -376,6 +379,8 @@ private slots:
void qpropertyBindingHandlesUndefinedCorrectly();
void qpropertyBindingHandlesUndefinedWithoutResetCorrectly_data();
void qpropertyBindingHandlesUndefinedWithoutResetCorrectly();
+ void qpropertyBindingRestoresObserverAfterReset();
+ void qpropertyBindingObserverCorrectlyLinkedAfterReset();
void hugeRegexpQuantifiers();
void singletonTypeWrapperLookup();
void getThisObject();
@@ -396,6 +401,7 @@ private slots:
void sequenceConversionMethod();
void proxyIteration();
void proxyHandlerTraps();
+ void lookupsDoNotBypassProxy();
void gcCrashRegressionTest();
void cmpInThrows();
void frozenQObject();
@@ -416,6 +422,13 @@ private slots:
void doNotCrashOnReadOnlyBindable();
+ void resetGadget();
+ void assignListPropertyByIndexOnGadget();
+
+ void methodCallOnDerivedSingleton();
+
+ void proxyMetaObject();
+
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
static void verifyContextLifetime(const QQmlRefPointer<QQmlContextData> &ctxt);
@@ -432,14 +445,6 @@ private:
}
};
-static void gc(QQmlEngine &engine)
-{
- engine.collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
-}
-
-
tst_qqmlecmascript::tst_qqmlecmascript()
: QQmlDataTest(QT_QMLTEST_DATADIR)
{
@@ -3127,11 +3132,14 @@ void tst_qqmlecmascript::callQtInvokables()
QCOMPARE(o->invoked(), -1);
QCOMPARE(o->actuals().size(), 0);
- o->reset();
- QVERIFY(EVALUATE_ERROR("object.method_QPointF(object)"));
- QCOMPARE(o->error(), false);
- QCOMPARE(o->invoked(), -1);
- QCOMPARE(o->actuals().size(), 0);
+ // This fails if the QtQml module is loaded but works if it's not.
+ // If QtQml is loaded, QPointF is a structured value type that can be created from any object.
+ //
+ // o->reset();
+ // QVERIFY(EVALUATE_ERROR("object.method_QPointF(object)"));
+ // QCOMPARE(o->error(), false);
+ // QCOMPARE(o->invoked(), -1);
+ // QCOMPARE(o->actuals().size(), 0);
o->reset();
QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", QV4::Primitive::undefinedValue()));
@@ -3186,6 +3194,17 @@ void tst_qqmlecmascript::callQtInvokables()
QCOMPARE(o->invoked(), -1); // no function got called due to incompatible arguments
}
+ {
+ o->reset();
+ QQmlComponent comp(&qmlengine, testFileUrl("qmlTypeWrapperArgs3.qml"));
+ QScopedPointer<QObject> root {comp.createWithInitialProperties({{"invokableObject", QVariant::fromValue(o)}}) };
+ QVERIFY(root);
+ QCOMPARE(o->error(), false);
+ QCOMPARE(o->actuals().size(), 2);
+ QCOMPARE(o->actuals().at(0).metaType(), QMetaType::fromType<QQmlComponentAttached *>());
+ QCOMPARE(o->actuals().at(1).metaType(), QMetaType::fromType<SingletonWithEnum *>());
+ }
+
o->reset();
QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", QV4::Primitive::undefinedValue()));
QCOMPARE(o->error(), false);
@@ -3517,6 +3536,27 @@ void tst_qqmlecmascript::callQtInvokables()
QCOMPARE(o->error(), false);
QCOMPARE(o->invoked(), -1);
QCOMPARE(o->actuals(), QVariantList());
+
+ o->reset();
+ QVERIFY(EVALUATE_VALUE("object.method_component(object.someComponent())",
+ QV4::Primitive::undefinedValue()));
+ QCOMPARE(o->error(), false);
+ QCOMPARE(o->invoked(), 42);
+ QCOMPARE(o->actuals(), QVariantList() << QVariant::fromValue(o->someComponent()));
+
+ o->reset();
+ QVERIFY(EVALUATE_VALUE("object.method_component(object.someTypeObject())",
+ QV4::Primitive::undefinedValue()));
+ QCOMPARE(o->error(), false);
+ QCOMPARE(o->invoked(), 43);
+ QCOMPARE(o->actuals(), QVariantList() << QVariant::fromValue(o->someTypeObject()));
+
+ o->reset();
+ QVERIFY(EVALUATE_VALUE("object.method_component('qrc:/somewhere/else')",
+ QV4::Primitive::undefinedValue()));
+ QCOMPARE(o->error(), false);
+ QCOMPARE(o->invoked(), 44);
+ QCOMPARE(o->actuals(), QVariantList() << QVariant::fromValue(QUrl("qrc:/somewhere/else")));
}
void tst_qqmlecmascript::resolveClashingProperties()
@@ -3815,6 +3855,82 @@ void tst_qqmlecmascript::scriptConnect()
QScopedPointer<QObject> root { component.create() };
QVERIFY2(root, qPrintable(component.errorString()));
}
+
+ {
+ QQmlComponent component(&engine, testFileUrl("scriptConnect.8.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj, qPrintable(component.errorString()));
+ QVERIFY(obj.data() != nullptr);
+
+ QCOMPARE(obj.data()->property("count"), 0);
+
+ QMetaObject::invokeMethod(obj.data(), "someSignal");
+ QCOMPARE(obj.data()->property("count"), 1);
+
+ QMetaObject::invokeMethod(obj.data(), "itemDestroy");
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+
+ QMetaObject::invokeMethod(obj.data(), "someSignal");
+ QCOMPARE(obj.data()->property("count"), 1);
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("scriptConnect.9.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj, qPrintable(component.errorString()));
+ QVERIFY(obj.data() != nullptr);
+
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(obj.data());
+
+ QCOMPARE(object->property("a"), 0);
+
+ QMetaObject::invokeMethod(object, "someSignal");
+ QCOMPARE(object->property("a"), 1);
+
+ QMetaObject::invokeMethod(object, "destroyObj", Qt::DirectConnection);
+ QApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+ QApplication::processEvents();
+
+ QMetaObject::invokeMethod(object, "someSignal");
+
+ QCOMPARE(object->property("a"), 1);
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("scriptConnectSingleton.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj, qPrintable(component.errorString()));
+ QVERIFY(obj.data() != nullptr);
+
+ QMetaObject::invokeMethod(obj.data(), "mySignal", Qt::DirectConnection);
+ QCOMPARE(obj.data()->property("a").toInt(), 1);
+ engine.clearSingletons();
+ QMetaObject::invokeMethod(obj.data(), "mySignal", Qt::DirectConnection);
+ QCOMPARE(obj.data()->property("a").toInt(), 1);
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("scriptConnect.deletion.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj, qPrintable(component.errorString()));
+ QVERIFY(!obj.isNull());
+
+ QCOMPARE(obj->property("a"), 0);
+
+ QMetaObject::invokeMethod(obj.data(), "someSignal");
+ QCOMPARE(obj->property("a"), 1);
+
+ QCOMPARE(obj->property("b"), 0);
+ QMetaObject::invokeMethod(obj.data(), "destroyObj", Qt::DirectConnection);
+
+ QTRY_COMPARE(obj->property("b"), 1);
+ QCOMPARE(obj->property("a"), 1);
+ }
}
void tst_qqmlecmascript::scriptDisconnect()
@@ -3895,6 +4011,60 @@ void tst_qqmlecmascript::scriptDisconnect()
emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
QCOMPARE(object->property("test").toInt(), 3);
}
+
+ {
+ QQmlComponent component(&engine, testFileUrl("scriptDisconnect.5.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj, qPrintable(component.errorString()));
+ QVERIFY(obj.data() != nullptr);
+
+ QCOMPARE(obj.data()->property("count"), 0);
+
+ QMetaObject::invokeMethod(obj.data(), "someSignal");
+ QCOMPARE(obj.data()->property("count"), 1);
+
+ QMetaObject::invokeMethod(obj.data(), "disconnectSignal");
+
+ QMetaObject::invokeMethod(obj.data(), "someSignal");
+ QCOMPARE(obj.data()->property("count"), 1);
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("scriptConnect.9.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj, qPrintable(component.errorString()));
+ QVERIFY(obj.data() != nullptr);
+
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(obj.data());
+
+ QCOMPARE(object->property("a"), 0);
+
+ QMetaObject::invokeMethod(object, "someSignal");
+ QCOMPARE(object->property("a"), 1);
+
+ QMetaObject::invokeMethod(object, "disconnectSignal", Qt::DirectConnection);
+
+ QMetaObject::invokeMethod(object, "someSignal");
+
+ QCOMPARE(object->property("a"), 1);
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("scriptConnectSingleton.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj, qPrintable(component.errorString()));
+ QVERIFY(obj.data() != nullptr);
+
+ QMetaObject::invokeMethod(obj.data(), "mySignal", Qt::DirectConnection);
+ QCOMPARE(obj.data()->property("a").toInt(), 1);
+
+ QMetaObject::invokeMethod(obj.data(), "disconnectSingleton", Qt::DirectConnection);
+ QMetaObject::invokeMethod(obj.data(), "mySignal", Qt::DirectConnection);
+ QCOMPARE(obj.data()->property("a").toInt(), 1);
+ }
}
class OwnershipObject : public QObject
@@ -3923,10 +4093,7 @@ void tst_qqmlecmascript::ownership()
QScopedPointer<QObject> object(component.create(context.data()));
- engine.collectGarbage();
-
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(engine);
QVERIFY(own.object.isNull());
}
@@ -3940,10 +4107,7 @@ void tst_qqmlecmascript::ownership()
QScopedPointer<QObject> object(component.create(context.data()));
- engine.collectGarbage();
-
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(engine);
QVERIFY(own.object != nullptr);
}
@@ -4019,9 +4183,7 @@ void tst_qqmlecmascript::ownershipCustomReturnValue()
QVERIFY(source.value != nullptr);
}
- engine.collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(engine);
QVERIFY(source.value.isNull());
}
@@ -4052,10 +4214,7 @@ void tst_qqmlecmascript::ownershipRootObject()
QScopedPointer<QObject> object(component.create(context.data()));
QVERIFY2(object, qPrintable(component.errorString()));
- engine.collectGarbage();
-
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(engine);
QVERIFY(own.object != nullptr);
}
@@ -4080,10 +4239,7 @@ void tst_qqmlecmascript::ownershipConsistency()
QScopedPointer<QObject> object(component.create(context.data()));
QVERIFY2(object, qPrintable(component.errorString()));
- engine.collectGarbage();
-
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(engine);
QVERIFY(own.object != nullptr);
}
@@ -4613,6 +4769,7 @@ void tst_qqmlecmascript::verifyContextLifetime(const QQmlRefPointer<QQmlContextD
}
ctxt->engine()->collectGarbage();
+ QTRY_VERIFY(gcDone(ctxt->engine()));
qml = scripts->get(i);
newContext = qml ? qml->getContext() : nullptr;
QCOMPARE(scriptContext.data(), newContext.data());
@@ -5257,6 +5414,7 @@ void tst_qqmlecmascript::propertyChangeSlots()
QQmlComponent component(&engine, testFileUrl("changeslots/propertyChangeSlots.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY2(object, qPrintable(component.errorString()));
+ QCOMPARE(object->property("changeCount"), 15);
// ensure that invalid property names fail properly.
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
@@ -5272,20 +5430,6 @@ void tst_qqmlecmascript::propertyChangeSlots()
QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
object.reset(e2.create());
QVERIFY(!object);
-
- QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
- QQmlComponent e3(&engine, testFileUrl("changeslots/propertyChangeSlotErrors.3.qml"));
- expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
- QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
- object.reset(e3.create());
- QVERIFY(!object);
-
- QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
- QQmlComponent e4(&engine, testFileUrl("changeslots/propertyChangeSlotErrors.4.qml"));
- expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
- QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
- object.reset(e4.create());
- QVERIFY(!object);
}
void tst_qqmlecmascript::propertyVar_data()
@@ -5453,7 +5597,9 @@ void tst_qqmlecmascript::propertyVarOwnership()
QScopedPointer<QObject> object(component.create());
QVERIFY2(object, qPrintable(component.errorString()));
QMetaObject::invokeMethod(object.data(), "createComponent");
- engine.collectGarbage();
+ // This test only works if we don't deliver the pending delete later event
+ // that collectGarbage will post before calling runTest
+ gc(engine, GCFlags::DontSendPostedEvents);
QMetaObject::invokeMethod(object.data(), "runTest");
QCOMPARE(object->property("test").toBool(), true);
}
@@ -5469,8 +5615,7 @@ void tst_qqmlecmascript::propertyVarImplicitOwnership()
QScopedPointer<QObject> object(component.create());
QVERIFY2(object, qPrintable(component.errorString()));
QMetaObject::invokeMethod(object.data(), "assignCircular");
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
- QCoreApplication::processEvents();
+ gc(engine);
QObject *rootObject = object->property("vp").value<QObject*>();
QVERIFY(rootObject != nullptr);
QObject *childObject = rootObject->findChild<QObject*>("text");
@@ -5479,6 +5624,8 @@ void tst_qqmlecmascript::propertyVarImplicitOwnership()
QCOMPARE(childObject->property("textCanary").toInt(), 10);
// Creates a reference to a constructed QObject:
QMetaObject::invokeMethod(childObject, "constructQObject");
+ // Don't send delete later events yet, we do it manually later
+ gc(engine, GCFlags::DontSendPostedEvents);
QPointer<QObject> qobjectGuard(childObject->property("vp").value<QObject*>()); // get the pointer prior to processing deleteLater events.
QVERIFY(!qobjectGuard.isNull());
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
@@ -5497,8 +5644,7 @@ void tst_qqmlecmascript::propertyVarReparent()
QScopedPointer<QObject> object(component.create());
QVERIFY2(object, qPrintable(component.errorString()));
QMetaObject::invokeMethod(object.data(), "assignVarProp");
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
- QCoreApplication::processEvents();
+ gc(engine);
QObject *rect = object->property("vp").value<QObject*>();
QObject *text = rect->findChild<QObject*>("textOne");
QObject *text2 = rect->findChild<QObject*>("textTwo");
@@ -5512,6 +5658,7 @@ void tst_qqmlecmascript::propertyVarReparent()
QCOMPARE(text2->property("textCanary").toInt(), 12);
// now construct an image which we will reparent.
QMetaObject::invokeMethod(text2, "constructQObject");
+ gc(engine, GCFlags::DontSendPostedEvents);
QObject *image = text2->property("vp").value<QObject*>();
QPointer<QObject> imageGuard(image);
QVERIFY(!imageGuard.isNull());
@@ -5539,8 +5686,7 @@ void tst_qqmlecmascript::propertyVarReparentNullContext()
QScopedPointer<QObject> object(component.create());
QVERIFY2(object, qPrintable(component.errorString()));
QMetaObject::invokeMethod(object.data(), "assignVarProp");
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
- QCoreApplication::processEvents();
+ gc(engine);
QObject *rect = object->property("vp").value<QObject*>();
QObject *text = rect->findChild<QObject*>("textOne");
QObject *text2 = rect->findChild<QObject*>("textTwo");
@@ -5554,6 +5700,7 @@ void tst_qqmlecmascript::propertyVarReparentNullContext()
QCOMPARE(text2->property("textCanary").toInt(), 12);
// now construct an image which we will reparent.
QMetaObject::invokeMethod(text2, "constructQObject");
+ gc(engine);
QObject *image = text2->property("vp").value<QObject*>();
QPointer<QObject> imageGuard(image);
QVERIFY(!imageGuard.isNull());
@@ -5780,9 +5927,7 @@ void tst_qqmlecmascript::handleReferenceManagement()
gc(hrmEngine);
QCOMPARE(dtorCount, 0); // second has JS ownership, kept alive by first's reference
object.reset();
- hrmEngine.collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(hrmEngine);
QCOMPARE(dtorCount, 3);
}
@@ -5799,9 +5944,7 @@ void tst_qqmlecmascript::handleReferenceManagement()
gc(hrmEngine);
QCOMPARE(dtorCount, 2); // both should be cleaned up, since circular references shouldn't keep alive.
object.reset();
- hrmEngine.collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(hrmEngine);
QCOMPARE(dtorCount, 3);
}
@@ -7892,7 +8035,7 @@ public:
void init(QV4::ExecutionEngine *v4, QV4::WeakValue *weakRef, bool *resultPtr)
{
- QV4::QObjectWrapper::wrap(v4, this);
+ (void) QV4::QObjectWrapper::wrap(v4, this); // Intentionally drop the wrapper
QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
this->resultPtr = resultPtr;
@@ -7980,12 +8123,9 @@ void tst_qqmlecmascript::onDestructionViaGC()
v4->memoryManager->allocate<QV4::WeakReferenceSentinel>(weakRef.data(), &sentinelResult);
}
gc(engine);
-
+ QVERIFY2(weakRef->isNullOrUndefined(), "The weak value was not cleared");
QVERIFY2(mutatorResult, "We failed to re-assign the weak reference a new value during GC");
- QVERIFY2(!sentinelResult, "The weak value was cleared on first GC run");
- QVERIFY2(!weakRef->isNullOrUndefined(), "The weak value was cleared on first GC run");
- gc(engine);
- QVERIFY2(weakRef->isNullOrUndefined(), "The weak value was not cleared on second gc run");
+ QVERIFY2(sentinelResult, "The weak reference was not cleared properly");
}
struct EventProcessor : public QObject
@@ -8078,7 +8218,9 @@ void tst_qqmlecmascript::qqmldataDestroyed()
QVERIFY2(object, qPrintable(c.errorString()));
// now gc causing the collection of the dynamically constructed object.
engine.collectGarbage();
+ QTRY_VERIFY(gcDone(&engine));
engine.collectGarbage();
+ QTRY_VERIFY(gcDone(&engine));
// now process events to allow deletion (calling qqmldata::destroyed())
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
QCoreApplication::processEvents();
@@ -9389,6 +9531,32 @@ void tst_qqmlecmascript::qpropertyBindingHandlesUndefinedWithoutResetCorrectly()
QCOMPARE(root->property("value2").toInt(), 2);
}
+void tst_qqmlecmascript::qpropertyBindingRestoresObserverAfterReset()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("restoreObserverAfterReset.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QTRY_COMPARE(o->property("height").toDouble(), 60.0);
+ QVERIFY(o->property("steps").toInt() > 3);
+}
+
+void tst_qqmlecmascript::qpropertyBindingObserverCorrectlyLinkedAfterReset()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("qpropertyResetCorrectlyLinked.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ std::unique_ptr<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("width"), 200);
+ auto item = qobject_cast<QQuickItem *>(o.get());
+ auto itemPriv = QQuickItemPrivate::get(item);
+ QBindingStorage *storage = qGetBindingStorage(itemPriv);
+ QPropertyBindingDataPointer ptr { storage->bindingData(&itemPriv->width) };
+ QCOMPARE(ptr.observerCount(), 1);
+}
+
void tst_qqmlecmascript::hugeRegexpQuantifiers()
{
QJSEngine engine;
@@ -9987,6 +10155,17 @@ void tst_qqmlecmascript::proxyHandlerTraps()
QVERIFY(value.isString() && value.toString() == QStringLiteral("SUCCESS"));
}
+void tst_qqmlecmascript::lookupsDoNotBypassProxy()
+{
+ QQmlEngine engine;
+ // we need a component to have a proper compilation to byte code;
+ // otherwise, we don't actually end up with lookups
+ QQmlComponent comp(&engine, testFileUrl("lookupsDoNotBypassProxy.qml"));
+ QVERIFY(comp.isReady());
+ std::unique_ptr<QObject> obj { comp.create() };
+ QCOMPARE(obj->property("result").toInt(), 3);
+}
+
void tst_qqmlecmascript::cmpInThrows()
{
QJSEngine engine;
@@ -10027,6 +10206,9 @@ public:
Q_INVOKABLE void triggerSignal() { emit fooMember2Emitted(&m_fooMember2); }
+ Q_INVOKABLE const FrozenFoo *getConst() { return createFloating(); }
+ Q_INVOKABLE FrozenFoo *getNonConst() { return createFloating(); }
+
FrozenFoo *fooMember() { return &m_fooMember; }
FrozenFoo *fooMember2() { return &m_fooMember2; }
@@ -10036,6 +10218,16 @@ signals:
private:
const FrozenFoo *fooMemberConst() const { return &m_fooMember; }
+ FrozenFoo *createFloating()
+ {
+ if (!m_floating) {
+ m_floating = new FrozenFoo;
+ m_floating->setObjectName(objectName());
+ }
+ return m_floating;
+ }
+
+ FrozenFoo *m_floating = nullptr;
FrozenFoo m_fooMember;
FrozenFoo m_fooMember2;
};
@@ -10058,6 +10250,17 @@ void tst_qqmlecmascript::frozenQObject()
QVERIFY(frozenObjects->property("caughtSignal").toBool());
QCOMPARE(frozenObjects->fooMember()->name(), QStringLiteral("Jane"));
QCOMPARE(frozenObjects->fooMember2()->name(), QStringLiteral("Jane"));
+
+ QQmlComponent component3(&engine, testFileUrl("frozenQObject3.qml"));
+ QScopedPointer<QObject> root3(component3.create());
+ QCOMPARE(root3->objectName(), QLatin1String("a/b"));
+ QVERIFY(root3->property("objConst").value<QObject *>());
+ QVERIFY(root3->property("objNonConst").value<QObject *>());
+
+ QTRY_VERIFY(root3->property("gcs").toInt() > 8);
+
+ QVERIFY(root3->property("objConst").value<QObject *>());
+ QVERIFY(root3->property("objNonConst").value<QObject *>());
}
struct ConstPointer : QObject
@@ -10373,6 +10576,80 @@ void tst_qqmlecmascript::doNotCrashOnReadOnlyBindable()
QCOMPARE(o->property("x").toInt(), 7);
}
+void tst_qqmlecmascript::resetGadget()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("resetGadget.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ auto resettableGadgetHolder = qobject_cast<ResettableGadgetHolder *>(o.get());
+ QVERIFY(resettableGadgetHolder);
+ QCOMPARE(resettableGadgetHolder->g().value(), 0);
+ resettableGadgetHolder->setProperty("trigger", QVariant::fromValue(true));
+ QCOMPARE(resettableGadgetHolder->g().value(), 42);
+}
+
+void tst_qqmlecmascript::assignListPropertyByIndexOnGadget()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFile("AssignListPropertyByIndexOnGadget.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+
+ const auto &gadget = o->property("gadget").value<ListPropertyAssignment_Gadget>();
+ const auto *object = o->property("object").value<ListPropertyAssignment_Object *>();
+ QVERIFY(object);
+
+ QStringList expected{ "Completely new Element", "Element2", "Element3" };
+ QVariantList variants {
+ u"Completely new Element"_s,
+ u"foo"_s,
+ QVariant::fromValue<std::nullptr_t>(nullptr),
+ QVariant::fromValue<bool>(true)
+ };
+
+ QCOMPARE(gadget.gadgetStringList(), expected);
+ QCOMPARE(gadget.gadgetVariantList(), variants);
+ QCOMPARE(object->qobjectStringList(), expected);
+}
+
+void tst_qqmlecmascript::methodCallOnDerivedSingleton()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFile("methodCallOnDerivedSingleton.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ auto singleton = engine.singletonInstance<SingletonBase *>("Qt.test", "SingletonInheritanceTest");
+ QVERIFY(singleton);
+ QVERIFY(singleton->m_okay);
+}
+
+void tst_qqmlecmascript::proxyMetaObject()
+{
+ // Verify that TypeWithCustomMetaObject, that extends another type,
+ // thereby triggering a QQmlProxyMetaObject, is still proxied the
+ // QDynamicMetaObjectData::objectDestroyed callback.
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(R"(
+ import QtQuick
+ import QtQml
+ import Qt.test
+ Rectangle {
+ TypeWithCustomMetaObject {}
+ }
+ )", QUrl("testData"));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(o);
+ QVERIFY(!MetaCallInterceptor::didGetObjectDestroyedCallback);
+ o.reset(nullptr);
+ QVERIFY(MetaCallInterceptor::didGetObjectDestroyedCallback);
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmlengine/CMakeLists.txt b/tests/auto/qml/qqmlengine/CMakeLists.txt
index 0869fe7ccc..9745f31bdb 100644
--- a/tests/auto/qml/qqmlengine/CMakeLists.txt
+++ b/tests/auto/qml/qqmlengine/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlengine Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlengine LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -34,6 +40,7 @@ qt_add_qml_module(tst_qqmlengine_qml
SOURCES
"declarativelyregistered.h"
"declarativelyregistered.cpp"
+ "variantlistQJsonConversion.h"
RESOURCE_PREFIX
"/"
OUTPUT_DIRECTORY
diff --git a/tests/auto/qml/qqmlengine/data/bindingInstallUseAfterFree.qml b/tests/auto/qml/qqmlengine/data/bindingInstallUseAfterFree.qml
new file mode 100644
index 0000000000..596ab10ee7
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/bindingInstallUseAfterFree.qml
@@ -0,0 +1,19 @@
+import QtQuick
+
+Item {
+ visible: false
+
+ property int test: 1
+
+ Component {
+ id: comp
+ Item {
+ width: { width = test * 100 }
+ }
+ }
+
+ Loader {
+ sourceComponent: comp
+ width: 100
+ }
+}
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/Main.qml b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/Main.qml
new file mode 100644
index 0000000000..3be706ee29
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/Main.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property string s: SingletonA.name
+}
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonA.qml b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonA.qml
new file mode 100644
index 0000000000..dc3bfd23fd
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonA.qml
@@ -0,0 +1,11 @@
+pragma Singleton
+import QtQuick
+
+Item {
+ readonly property string name: "SingletonA"
+
+ readonly property TestItem itemA: TestItem{}
+
+ property TestItem crossRef: SingletonB.itemB
+ property int testItemInt: crossRef.i
+}
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonB.qml b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonB.qml
new file mode 100644
index 0000000000..7f0335ee89
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonB.qml
@@ -0,0 +1,11 @@
+pragma Singleton
+import QtQuick
+
+Item {
+ readonly property string name: "SingletonB"
+
+ readonly property TestItem itemB: TestItem{}
+
+ property TestItem crossRef: SingletonA.itemA
+ property int testItemInt: crossRef.i
+}
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/TestItem.qml b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/TestItem.qml
new file mode 100644
index 0000000000..81d931f14c
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/TestItem.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int i: 3
+}
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/qmldir b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/qmldir
new file mode 100644
index 0000000000..8bf691d10d
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/qmldir
@@ -0,0 +1,3 @@
+module Module
+singleton SingletonA 1.0 SingletonA.qml
+singleton SingletonB 1.0 SingletonB.qml
diff --git a/tests/auto/qml/qqmlengine/data/markCurrentFunctionAsTranslationBinding.qml b/tests/auto/qml/qqmlengine/data/markCurrentFunctionAsTranslationBinding.qml
new file mode 100644
index 0000000000..a16e9c483f
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/markCurrentFunctionAsTranslationBinding.qml
@@ -0,0 +1,7 @@
+import QtQml
+import i18ntest
+
+QtObject {
+ property I18nAware aware: I18nAware {}
+ property string result: aware.text
+}
diff --git a/tests/auto/qml/qqmlengine/data/nativeModuleImport.mjs b/tests/auto/qml/qqmlengine/data/nativeModuleImport.mjs
index fd1080fccb..8f5bdde82a 100644
--- a/tests/auto/qml/qqmlengine/data/nativeModuleImport.mjs
+++ b/tests/auto/qml/qqmlengine/data/nativeModuleImport.mjs
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import { name } from "info.mjs";
diff --git a/tests/auto/qml/qqmlengine/data/nativeModuleImport.qml b/tests/auto/qml/qqmlengine/data/nativeModuleImport.qml
index ae51210944..ffcb0e42ce 100644
--- a/tests/auto/qml/qqmlengine/data/nativeModuleImport.qml
+++ b/tests/auto/qml/qqmlengine/data/nativeModuleImport.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
diff --git a/tests/auto/qml/qqmlengine/data/variantListQJsonConversion.qml b/tests/auto/qml/qqmlengine/data/variantListQJsonConversion.qml
new file mode 100644
index 0000000000..fd0820a3c5
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/variantListQJsonConversion.qml
@@ -0,0 +1,18 @@
+import QtQuick
+import OnlyDeclarative
+
+Item {
+
+ MiscUtils {
+ id: miscUtils
+ }
+
+ Component.onCompleted: {
+ const varlist = miscUtils.createVariantList();
+ const obj = { test: varlist };
+ const listProperty = miscUtils.createQmlListProperty();
+ miscUtils.logArray(varlist);
+ miscUtils.logObject(obj);
+ miscUtils.logArray(listProperty);
+ }
+}
diff --git a/tests/auto/qml/qqmlengine/declarativelyregistered.cpp b/tests/auto/qml/qqmlengine/declarativelyregistered.cpp
index 9893fa0311..4a469c4795 100644
--- a/tests/auto/qml/qqmlengine/declarativelyregistered.cpp
+++ b/tests/auto/qml/qqmlengine/declarativelyregistered.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "declarativelyregistered.h"
diff --git a/tests/auto/qml/qqmlengine/declarativelyregistered.h b/tests/auto/qml/qqmlengine/declarativelyregistered.h
index 98f7250d76..edb783e3aa 100644
--- a/tests/auto/qml/qqmlengine/declarativelyregistered.h
+++ b/tests/auto/qml/qqmlengine/declarativelyregistered.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DECLARATIVELYREGISTERED_H
#define DECLARATIVELYREGISTERED_H
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index 895513d822..3c25d29dfb 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QQmlEngine>
#include <QQmlContext>
@@ -36,8 +36,10 @@ public:
private slots:
void initTestCase() override;
void rootContext();
+#if QT_CONFIG(qml_network)
void networkAccessManager();
void synchronousNetworkAccessManager();
+#endif
void baseUrl();
void contextForObject();
void offlineStoragePath();
@@ -67,6 +69,7 @@ private slots:
void cachedGetterLookup_qtbug_75335();
void createComponentOnSingletonDestruction();
void uiLanguage();
+ void markCurrentFunctionAsTranslationBinding();
void executeRuntimeFunction();
void captureQProperty();
void listWrapperAsListReference();
@@ -77,6 +80,9 @@ private slots:
void qtNamespaceInQtObject();
void nativeModuleImport();
void lockedRootObject();
+ void crossReferencingSingletonsDeletion();
+ void bindingInstallUseAfterFree();
+ void variantListQJsonConversion();
public slots:
QObject *createAQObjectForOwnershipTest ()
@@ -149,6 +155,7 @@ void tst_qqmlengine::rootContext()
QVERIFY(!engine.rootContext()->parentContext());
}
+#if QT_CONFIG(qml_network)
class NetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory
{
public:
@@ -164,21 +171,19 @@ public:
void tst_qqmlengine::networkAccessManager()
{
- QQmlEngine *engine = new QQmlEngine;
+ std::unique_ptr<QQmlEngine> engine = std::make_unique<QQmlEngine>();
// Test QQmlEngine created manager
QPointer<QNetworkAccessManager> manager = engine->networkAccessManager();
QVERIFY(manager != nullptr);
- delete engine;
// Test factory created manager
- engine = new QQmlEngine;
+ engine.reset(new QQmlEngine);
NetworkAccessManagerFactory factory;
engine->setNetworkAccessManagerFactory(&factory);
QCOMPARE(engine->networkAccessManagerFactory(), &factory);
QNetworkAccessManager *engineNam = engine->networkAccessManager(); // calls NetworkAccessManagerFactory::create()
QCOMPARE(engineNam, factory.manager);
- delete engine;
}
class ImmediateReply : public QNetworkReply {
@@ -226,7 +231,7 @@ void tst_qqmlengine::synchronousNetworkAccessManager()
// reply is finished, so should not be in loading state.
QVERIFY(!c.isLoading());
}
-
+#endif
void tst_qqmlengine::baseUrl()
{
@@ -267,7 +272,7 @@ void tst_qqmlengine::baseUrl()
void tst_qqmlengine::contextForObject()
{
- QQmlEngine *engine = new QQmlEngine;
+ std::unique_ptr<QQmlEngine> engine = std::make_unique<QQmlEngine>();
// Test null-object
QVERIFY(!QQmlEngine::contextForObject(nullptr));
@@ -294,7 +299,7 @@ void tst_qqmlengine::contextForObject()
QCOMPARE(QQmlEngine::contextForObject(&object), engine->rootContext());
// Delete context
- delete engine; engine = nullptr;
+ engine.reset();
QVERIFY(!QQmlEngine::contextForObject(&object));
}
@@ -372,10 +377,9 @@ void tst_qqmlengine::clearComponentCache()
// Test "test" property
{
QQmlComponent component(&engine, fileUrl);
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj.get() != nullptr);
QCOMPARE(obj->property("test").toInt(), 10);
- delete obj;
}
// Modify qml file
@@ -395,10 +399,9 @@ void tst_qqmlengine::clearComponentCache()
// Test cache hit
{
QQmlComponent component(&engine, fileUrl);
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj.get() != nullptr);
QCOMPARE(obj->property("test").toInt(), 10);
- delete obj;
}
// Clear cache
@@ -407,10 +410,9 @@ void tst_qqmlengine::clearComponentCache()
// Test cache refresh
{
QQmlComponent component(&engine, fileUrl);
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj.get() != nullptr);
QCOMPARE(obj->property("test").toInt(), 11);
- delete obj;
}
// Regular Synchronous loading will leave us with an event posted
@@ -437,7 +439,7 @@ public:
// There might be JS function objects around that hold a last ref to the compilation unit that's
// keeping the type compilation data (CompilationUnit) around. Let's collect them as well so that
// trim works well.
- engine->collectGarbage();
+ gc(*engine);
engine->trimComponentCache();
}
@@ -496,22 +498,25 @@ void tst_qqmlengine::trimComponentCache_data()
// empty apart from their inherited elements, and those that define new properties.
// For each there are five types of composition: extension, aggregation,
// aggregation via component, property and object-created-via-transient-component.
- foreach (const QString &test, (QStringList() << "EmptyComponent"
- << "VMEComponent"
- << "EmptyExtendEmptyComponent"
- << "VMEExtendEmptyComponent"
- << "EmptyExtendVMEComponent"
- << "VMEExtendVMEComponent"
- << "EmptyAggregateEmptyComponent"
- << "VMEAggregateEmptyComponent"
- << "EmptyAggregateVMEComponent"
- << "VMEAggregateVMEComponent"
- << "EmptyPropertyEmptyComponent"
- << "VMEPropertyEmptyComponent"
- << "EmptyPropertyVMEComponent"
- << "VMEPropertyVMEComponent"
- << "VMETransientEmptyComponent"
- << "VMETransientVMEComponent")) {
+ const QStringList components = {
+ "EmptyComponent",
+ "VMEComponent",
+ "EmptyExtendEmptyComponent",
+ "VMEExtendEmptyComponent",
+ "EmptyExtendVMEComponent",
+ "VMEExtendVMEComponent",
+ "EmptyAggregateEmptyComponent",
+ "VMEAggregateEmptyComponent",
+ "EmptyAggregateVMEComponent",
+ "VMEAggregateVMEComponent",
+ "EmptyPropertyEmptyComponent",
+ "VMEPropertyEmptyComponent",
+ "EmptyPropertyVMEComponent",
+ "VMEPropertyVMEComponent",
+ "VMETransientEmptyComponent",
+ "VMETransientVMEComponent",
+ };
+ for (const QString &test : components) {
// For these cases, we first test that the component instance keeps the components
// referenced, and then that the instantiated object keeps the components referenced
for (int i = 1; i <= 2; ++i) {
@@ -903,7 +908,7 @@ void tst_qqmlengine::qtqmlModule()
QFETCH(QString, expectedError);
QFETCH(QStringList, expectedWarnings);
- foreach (const QString &w, expectedWarnings)
+ for (const QString &w : std::as_const(expectedWarnings))
QTest::ignoreMessage(QtWarningMsg, qPrintable(w));
QQmlEngine e;
@@ -1272,9 +1277,9 @@ void tst_qqmlengine::singletonInstance()
{
// deleted object
- auto dayfly = new Dayfly{};
- auto id = qmlRegisterSingletonInstance("Vanity", 1, 0, "Dayfly", dayfly);
- delete dayfly;
+ auto dayfly = std::make_unique<Dayfly>();
+ auto id = qmlRegisterSingletonInstance("Vanity", 1, 0, "Dayfly", dayfly.get());
+ dayfly.reset();
QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: The registered singleton has already been deleted. Ensure that it outlives the engine.");
QObject *instance = engine.singletonInstance<QObject*>(id);
QVERIFY(!instance);
@@ -1378,6 +1383,35 @@ void tst_qqmlengine::uiLanguage()
}
}
+class I18nAwareClass : public QObject {
+ Q_OBJECT
+ QML_NAMED_ELEMENT(I18nAware)
+
+ Q_PROPERTY(QString text READ text NOTIFY textChanged)
+signals:
+ void textChanged();
+public:
+ int counter = 0;
+
+ QString text()
+ {
+ if (auto engine = qmlEngine(this))
+ engine->markCurrentFunctionAsTranslationBinding();
+ return QLatin1String("Hello, %1").arg(QString::number(counter++));
+ }
+};
+
+void tst_qqmlengine::markCurrentFunctionAsTranslationBinding()
+{
+ QQmlEngine engine;
+ qmlRegisterTypesAndRevisions<I18nAwareClass>("i18ntest", 1);
+ QQmlComponent comp(&engine, testFileUrl("markCurrentFunctionAsTranslationBinding.qml"));
+ std::unique_ptr<QObject> root { comp.create() };
+ QCOMPARE(root->property("result"), "Hello, 0");
+ engine.retranslate();
+ QCOMPARE(root->property("result"), "Hello, 1");
+}
+
void tst_qqmlengine::executeRuntimeFunction()
{
QQmlEngine engine;
@@ -1683,6 +1717,42 @@ void tst_qqmlengine::lockedRootObject()
QCOMPARE(o->property("defineProperty2").toBool(), false);
}
+void tst_qqmlengine::crossReferencingSingletonsDeletion()
+{
+ QQmlEngine engine;
+ engine.addImportPath(testFileUrl("crossReferencingSingletonsDeletion").url());
+ QQmlComponent c(&engine, testFileUrl("crossReferencingSingletonsDeletion/Module/Main.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ std::unique_ptr<QObject> o{ c.create() };
+ QVERIFY(o);
+ QCOMPARE(o->property("s").toString(), "SingletonA");
+}
+
+void tst_qqmlengine::bindingInstallUseAfterFree()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("bindingInstallUseAfterFree.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ std::unique_ptr<QObject> o{ c.create() };
+ QVERIFY(o);
+}
+
+void tst_qqmlengine::variantListQJsonConversion()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("variantListQJsonConversion.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg, R"(["cpp","variant","list"])");
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg, R"({"test":["cpp","variant","list"]})");
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg,
+ R"([{"objectName":"o0"},{"objectName":"o1"},{"objectName":"o2"}])");
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+}
+
QTEST_MAIN(tst_qqmlengine)
#include "tst_qqmlengine.moc"
diff --git a/tests/auto/qml/qqmlengine/variantlistQJsonConversion.h b/tests/auto/qml/qqmlengine/variantlistQJsonConversion.h
new file mode 100644
index 0000000000..edf2174a18
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/variantlistQJsonConversion.h
@@ -0,0 +1,53 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef VARIANTLIST_QJSON_CONVERSION_HPP
+#define VARIANTLIST_QJSON_CONVERSION_HPP
+
+#include "qqmlintegration.h"
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QObject>
+#include <QJsonDocument>
+#include <QDebug>
+#include <private/qjsvalue_p.h>
+#include <private/qqmllistwrapper_p.h>
+#include <private/qv4engine_p.h>
+#include <private/qv4jsonobject_p.h>
+
+class MiscUtils : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+public:
+ Q_INVOKABLE QVariantList createVariantList() const
+ {
+ return { QString("cpp"), QString("variant"), QString("list") };
+ }
+
+ Q_INVOKABLE QQmlListProperty<QObject> createQmlListProperty()
+ {
+ QV4::ExecutionEngine engine(qmlEngine(this));
+ static QObject objects[] = { QObject{}, QObject{}, QObject{} };
+ objects[0].setObjectName("o0");
+ objects[1].setObjectName("o1");
+ objects[2].setObjectName("o2");
+ static QList<QObject *> list{ &objects[0], &objects[1], &objects[2] };
+ return QQmlListProperty<QObject>(this, &list);
+ }
+
+ Q_INVOKABLE void logArray(const QJsonArray &arr) const
+ {
+ const auto str = QString(QJsonDocument(arr).toJson(QJsonDocument::Compact));
+ qDebug().noquote() << str;
+ }
+
+ Q_INVOKABLE void logObject(const QJsonObject &obj) const
+ {
+ const auto str = QString(QJsonDocument(obj).toJson(QJsonDocument::Compact));
+ qDebug().noquote() << str;
+ }
+};
+
+#endif // VARIANTLIST_QJSON_CONVERSION_HPP
diff --git a/tests/auto/qml/qqmlenginecleanup/CMakeLists.txt b/tests/auto/qml/qqmlenginecleanup/CMakeLists.txt
index d91fc98f8a..87b0874774 100644
--- a/tests/auto/qml/qqmlenginecleanup/CMakeLists.txt
+++ b/tests/auto/qml/qqmlenginecleanup/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlenginecleanup Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlenginecleanup LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/ModuleType.qml b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/ModuleType.qml
index 6dfe0d52e8..083e8f2e7c 100644
--- a/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/ModuleType.qml
+++ b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/ModuleType.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.12
diff --git a/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.cpp b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.cpp
index c53f9e674b..52ab367d10 100644
--- a/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.cpp
+++ b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqmlengine.h>
diff --git a/tests/auto/qml/qqmlenginecleanup/data/TestType.qml b/tests/auto/qml/qqmlenginecleanup/data/TestType.qml
index 9f98ec971f..0699ac894f 100644
--- a/tests/auto/qml/qqmlenginecleanup/data/TestType.qml
+++ b/tests/auto/qml/qqmlenginecleanup/data/TestType.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Research In Motion.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.0
QtObject{property int notJustAStandardQtObject: 10 }
diff --git a/tests/auto/qml/qqmlenginecleanup/data/testFile1.qml b/tests/auto/qml/qqmlenginecleanup/data/testFile1.qml
index 5298dea961..233684633f 100644
--- a/tests/auto/qml/qqmlenginecleanup/data/testFile1.qml
+++ b/tests/auto/qml/qqmlenginecleanup/data/testFile1.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlenginecleanup/data/testFile2.qml b/tests/auto/qml/qqmlenginecleanup/data/testFile2.qml
index 0bd2c54e16..02d231d375 100644
--- a/tests/auto/qml/qqmlenginecleanup/data/testFile2.qml
+++ b/tests/auto/qml/qqmlenginecleanup/data/testFile2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlenginecleanup/data/testFile3.qml b/tests/auto/qml/qqmlenginecleanup/data/testFile3.qml
index be95e2ff74..10e2b2888a 100644
--- a/tests/auto/qml/qqmlenginecleanup/data/testFile3.qml
+++ b/tests/auto/qml/qqmlenginecleanup/data/testFile3.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlenginecleanup/data/types.qml b/tests/auto/qml/qqmlenginecleanup/data/types.qml
index f726a37404..4de1e6e43d 100644
--- a/tests/auto/qml/qqmlenginecleanup/data/types.qml
+++ b/tests/auto/qml/qqmlenginecleanup/data/types.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Research In Motion.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.0
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp b/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp
index c9049c7ca4..04e8389c87 100644
--- a/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp
+++ b/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Research In Motion.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QObject>
#include <QtQml/qqml.h>
@@ -47,8 +47,8 @@ public:
void tst_qqmlenginecleanup::test_qmlClearTypeRegistrations()
{
//Test for preventing memory leaks is in tests/manual/qmltypememory
- QQmlEngine* engine;
- CleanlyLoadingComponent* component;
+ std::unique_ptr<QQmlEngine> engine;
+ std::unique_ptr<CleanlyLoadingComponent> component;
QUrl testFile = testFileUrl("types.qml");
const auto qmlTypeForTestType = []() {
@@ -60,12 +60,12 @@ void tst_qqmlenginecleanup::test_qmlClearTypeRegistrations()
qmlRegisterType<QObject>("Test", 2, 0, "TestTypeCpp");
QVERIFY(qmlTypeForTestType().isValid());
- engine = new QQmlEngine;
- component = new CleanlyLoadingComponent(engine, testFile);
+ engine = std::make_unique<QQmlEngine>();
+ component = std::make_unique<CleanlyLoadingComponent>(engine.get(), testFile);
QVERIFY(component->isReady());
- delete component;
- delete engine;
+ component.reset();
+ engine.reset();
{
auto cppType = qmlTypeForTestType();
@@ -81,24 +81,21 @@ void tst_qqmlenginecleanup::test_qmlClearTypeRegistrations()
//2nd run verifies that types can reload after a qmlClearTypeRegistrations
qmlRegisterType<QObject>("Test", 2, 0, "TestTypeCpp");
QVERIFY(qmlTypeForTestType().isValid());
- engine = new QQmlEngine;
- component = new CleanlyLoadingComponent(engine, testFile);
+ engine = std::make_unique<QQmlEngine>();
+ component = std::make_unique<CleanlyLoadingComponent>(engine.get(), testFile);
QVERIFY(component->isReady());
- delete component;
- delete engine;
+ component.reset();
+ engine.reset();
qmlClearTypeRegistrations();
QVERIFY(!qmlTypeForTestType().isValid());
//3nd run verifies that TestTypeCpp is no longer registered
- engine = new QQmlEngine;
- component = new CleanlyLoadingComponent(engine, testFile);
+ engine = std::make_unique<QQmlEngine>();
+ component = std::make_unique<CleanlyLoadingComponent>(engine.get(), testFile);
QVERIFY(component->isError());
QCOMPARE(component->errorString(),
testFile.toString() +":8 module \"Test\" is not installed\n");
-
- delete component;
- delete engine;
}
static void cleanState(QQmlEngine **e)
diff --git a/tests/auto/qml/qqmlerror/CMakeLists.txt b/tests/auto/qml/qqmlerror/CMakeLists.txt
index be85347051..11b084e88d 100644
--- a/tests/auto/qml/qqmlerror/CMakeLists.txt
+++ b/tests/auto/qml/qqmlerror/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlerror Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlerror LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp b/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp
index b0e8846e59..d4d483fb27 100644
--- a/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp
+++ b/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlError>
diff --git a/tests/auto/qml/qqmlexpression/CMakeLists.txt b/tests/auto/qml/qqmlexpression/CMakeLists.txt
index 79dccd484d..6adb01b3b1 100644
--- a/tests/auto/qml/qqmlexpression/CMakeLists.txt
+++ b/tests/auto/qml/qqmlexpression/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlexpression Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlexpression LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp b/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp
index 71c186f3e4..59023391cd 100644
--- a/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp
+++ b/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp
@@ -1,11 +1,12 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
-#include <QtQml/qqmlengine.h>
-#include <QtQml/qqmlfile.h>
#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlexpression.h>
+#include <QtQml/qqmlfile.h>
#include <QtQml/qqmlscriptstring.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -20,6 +21,7 @@ private slots:
void syntaxError();
void exception();
void expressionFromDataComponent();
+ void emptyScriptString();
};
class TestObject : public QObject
@@ -121,6 +123,36 @@ void tst_qqmlexpression::expressionFromDataComponent()
QCOMPARE(result.toString(), QStringLiteral("success"));
}
+void tst_qqmlexpression::emptyScriptString()
+{
+ QQmlEngine engine;
+ QQmlContext *context = engine.rootContext();
+ QVERIFY(context);
+ QVERIFY(context->isValid());
+
+ QQmlScriptString empty;
+ QVERIFY(empty.isEmpty());
+
+ QQmlExpression expression(empty, context, this);
+ QCOMPARE(expression.context(), context);
+ QCOMPARE(expression.scopeObject(), this);
+ QCOMPARE(expression.expression(), QString());
+
+ const QVariant result = expression.evaluate();
+ QVERIFY(!result.isValid());
+
+ QQmlComponent c(&engine, testFileUrl("scriptString.qml"));
+ std::unique_ptr<QObject> root { c.create() };
+ TestObject *testObj = qobject_cast<TestObject*>(root.get());
+ QVERIFY(testObj != nullptr);
+
+ QQmlScriptString script = testObj->scriptString();
+ QVERIFY(!script.isEmpty());
+
+ // verify that comparing against an empty script string does not crash
+ QVERIFY(script != empty);
+}
+
QTEST_MAIN(tst_qqmlexpression)
#include "tst_qqmlexpression.moc"
diff --git a/tests/auto/qml/qqmlextensionplugin/CMakeLists.txt b/tests/auto/qml/qqmlextensionplugin/CMakeLists.txt
index de108af085..4a32e3a0e4 100644
--- a/tests/auto/qml/qqmlextensionplugin/CMakeLists.txt
+++ b/tests/auto/qml/qqmlextensionplugin/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlextensionplugin Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlextensionplugin LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlextensionplugin
SOURCES
tst_qqmlextensionplugin.cpp
diff --git a/tests/auto/qml/qqmlextensionplugin/data/dummy.qml b/tests/auto/qml/qqmlextensionplugin/data/dummy.qml
index f8169bd6aa..e555405535 100644
--- a/tests/auto/qml/qqmlextensionplugin/data/dummy.qml
+++ b/tests/auto/qml/qqmlextensionplugin/data/dummy.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp b/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp
index b8e0b01f6d..5f299f7b91 100644
--- a/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp
+++ b/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore>
#include <QtTest>
@@ -75,7 +75,7 @@ void tst_qqmlextensionplugin::iidCheck_data()
files = removeDuplicates(std::move(files));
QTest::addColumn<QString>("filePath");
- foreach (const QString &file, files) {
+ for (const QString &file: std::as_const(files)) {
QFileInfo fileInfo(file);
QTest::newRow(fileInfo.baseName().toLatin1().data()) << fileInfo.absoluteFilePath();
}
diff --git a/tests/auto/qml/qqmlfile/CMakeLists.txt b/tests/auto/qml/qqmlfile/CMakeLists.txt
index c573b53b1a..d8e23f410c 100644
--- a/tests/auto/qml/qqmlfile/CMakeLists.txt
+++ b/tests/auto/qml/qqmlfile/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlfile Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlfile LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlfile
SOURCES
tst_qqmlfile.cpp
diff --git a/tests/auto/qml/qqmlfile/tst_qqmlfile.cpp b/tests/auto/qml/qqmlfile/tst_qqmlfile.cpp
index 3f75a14bf6..3ce87ce048 100644
--- a/tests/auto/qml/qqmlfile/tst_qqmlfile.cpp
+++ b/tests/auto/qml/qqmlfile/tst_qqmlfile.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore>
#include <QtTest>
diff --git a/tests/auto/qml/qqmlfileselector/CMakeLists.txt b/tests/auto/qml/qqmlfileselector/CMakeLists.txt
index d169ffc607..b3dec0ff3d 100644
--- a/tests/auto/qml/qqmlfileselector/CMakeLists.txt
+++ b/tests/auto/qml/qqmlfileselector/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlfileselector Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlfileselector LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/main.qml b/tests/auto/qml/qqmlfileselector/data/qmldirtest/main.qml
index d6dd2c9b90..4e09798a84 100644
--- a/tests/auto/qml/qqmlfileselector/data/qmldirtest/main.qml
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/main.qml
@@ -1,10 +1,8 @@
import QtQuick
import qmldirtest
-Window {
- width: 640
- height: 480
- visible: true
+Item {
+ objectName: Name.name
property color color: mybutton.color
MyButton {
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+linux/Name.js b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+linux/Name.js
new file mode 100644
index 0000000000..91ca4f129d
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+linux/Name.js
@@ -0,0 +1 @@
+var name = "linux"
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+macos/Name.js b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+macos/Name.js
new file mode 100644
index 0000000000..12e5058285
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+macos/Name.js
@@ -0,0 +1 @@
+var name = "macos"
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/Name.js b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/Name.js
new file mode 100644
index 0000000000..916a232eb4
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/Name.js
@@ -0,0 +1 @@
+var name = "base"
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/qmldir b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qmldir
index ac68d9097d..a2efdbf27d 100644
--- a/tests/auto/qml/qqmlfileselector/data/qmldirtest/qmldir
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qmldir
@@ -2,4 +2,7 @@ module qmldirtest
MyButton 1.0 qml/MyButton.qml
MyButton 1.0 qml/+linux/MyButton.qml
MyButton 1.0 qml/+macos/MyButton.qml
+Name 1.0 qml/Name.js
+Name 1.0 qml/+linux/Name.js
+Name 1.0 qml/+macos/Name.js
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/MyButton.qml b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/MyButton.qml
new file mode 100644
index 0000000000..5bf632c48d
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/MyButton.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Rectangle {
+ width: 300
+ height: 50
+ color: "yellow"
+}
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/Name.js b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/Name.js
new file mode 100644
index 0000000000..8591795d37
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/Name.js
@@ -0,0 +1 @@
+var name = "bar"
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/MyButton.qml b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/MyButton.qml
new file mode 100644
index 0000000000..cc6eb967da
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/MyButton.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Rectangle {
+ width: 300
+ height: 50
+ color: "blue"
+}
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/Name.js b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/Name.js
new file mode 100644
index 0000000000..b224ed15ec
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/Name.js
@@ -0,0 +1 @@
+var name = "foo"
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/MyButton.qml b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/MyButton.qml
new file mode 100644
index 0000000000..32db428c4f
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/MyButton.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Rectangle {
+ width: 300
+ height: 50
+ color: "green"
+}
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/Name.js b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/Name.js
new file mode 100644
index 0000000000..916a232eb4
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/Name.js
@@ -0,0 +1 @@
+var name = "base"
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/main.qml b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/main.qml
new file mode 100644
index 0000000000..5fb8afc660
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/main.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+Item {
+ objectName: Name.name
+ property color color: mybutton.color
+ MyButton {
+ id: mybutton
+ }
+}
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/qmldir b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/qmldir
new file mode 100644
index 0000000000..92fefb9806
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/qmldir
@@ -0,0 +1,5 @@
+module qmldirtest2
+MyButton 1.0 +foo/MyButton.qml
+MyButton 1.0 MyButton.qml
+MyButton 1.0 +bar/MyButton.qml
+Name 1.0 Name.js
diff --git a/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp b/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp
index 46df20378c..98774ffe64 100644
--- a/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp
+++ b/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 BlackBerry Limited. All rights reserved.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -32,11 +32,9 @@ void tst_qqmlfileselector::basicTest()
selector.setExtraSelectors(QStringList() << "basic");
QQmlComponent component(&engine, testFileUrl("basicTest.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
QCOMPARE(object->property("value").toString(), QString("selected"));
-
- delete object;
}
void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message)
@@ -72,19 +70,38 @@ void tst_qqmlfileselector::applicationEngineTest()
void tst_qqmlfileselector::qmldirCompatibility()
{
- QQmlApplicationEngine engine;
- engine.addImportPath(dataDirectory());
- engine.load(testFileUrl("qmldirtest/main.qml"));
- QVERIFY(!engine.rootObjects().isEmpty());
- QObject *object = engine.rootObjects().at(0);
- auto color = object->property("color").value<QColor>();
+ {
+ // No error for multiple files with different selectors, and the matching one is chosen
+ // for +macos and +linux selectors.
+ QQmlApplicationEngine engine;
+ engine.addImportPath(dataDirectory());
+ engine.load(testFileUrl("qmldirtest/main.qml"));
+ QVERIFY(!engine.rootObjects().isEmpty());
+ QObject *object = engine.rootObjects().at(0);
+ auto color = object->property("color").value<QColor>();
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
- QCOMPARE(color, QColorConstants::Svg::blue);
+ QCOMPARE(object->objectName(), "linux");
+ QCOMPARE(color, QColorConstants::Svg::blue);
#elif defined(Q_OS_DARWIN)
- QCOMPARE(color, QColorConstants::Svg::yellow);
+ QCOMPARE(object->objectName(), "macos");
+ QCOMPARE(color, QColorConstants::Svg::yellow);
#else
- QCOMPARE(color, QColorConstants::Svg::green);
+ QCOMPARE(object->objectName(), "base");
+ QCOMPARE(color, QColorConstants::Svg::green);
#endif
+ }
+
+ {
+ // If nothing matches, the _base_ file is chosen, not the first or the last one.
+ // This also holds when using the implicit import.
+ QQmlApplicationEngine engine;
+ engine.addImportPath(dataDirectory());
+ engine.load(testFileUrl("qmldirtest2/main.qml"));
+ QVERIFY(!engine.rootObjects().isEmpty());
+ QObject *object = engine.rootObjects().at(0);
+ QCOMPARE(object->property("color").value<QColor>(), QColorConstants::Svg::green);
+ QCOMPARE(object->objectName(), "base");
+ }
}
QTEST_MAIN(tst_qqmlfileselector)
diff --git a/tests/auto/qml/qqmlglobal/CMakeLists.txt b/tests/auto/qml/qqmlglobal/CMakeLists.txt
index ff57005dc3..ce600c7607 100644
--- a/tests/auto/qml/qqmlglobal/CMakeLists.txt
+++ b/tests/auto/qml/qqmlglobal/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlglobal Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlglobal LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlglobal
SOURCES
tst_qqmlglobal.cpp
diff --git a/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp b/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp
index 81d61976a3..884ea180a9 100644
--- a/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp
+++ b/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <qqml.h>
diff --git a/tests/auto/qml/qqmlimport/CMakeLists.txt b/tests/auto/qml/qqmlimport/CMakeLists.txt
index 32aeec0966..b8b720f5dc 100644
--- a/tests/auto/qml/qqmlimport/CMakeLists.txt
+++ b/tests/auto/qml/qqmlimport/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlimport Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlimport LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -29,6 +35,7 @@ qt_internal_add_test(tst_qqmlimport
SOURCES
tst_qqmlimport.cpp
LIBRARIES
+ Qt::CorePrivate
Qt::Gui
Qt::Qml
Qt::QmlPrivate
@@ -44,6 +51,21 @@ qt_internal_add_resource(tst_qqmlimport "preferred"
"Preferred.qml"
)
+qt_internal_add_resource(tst_qqmlimport "preferred2"
+ PREFIX
+ "/qqmlimport/ModuleWithPrefer2/"
+ FILES
+ "Preferred.qml"
+ "qmldir"
+)
+
+qt_internal_add_resource(tst_qqmlimport "qtconf"
+ PREFIX
+ "/"
+ FILES
+ "qmlimports.qt.conf"
+)
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qqmlimport/MyPluginSupported/MyItem.qml b/tests/auto/qml/qqmlimport/MyPluginSupported/MyItem.qml
index 943ce3309f..960b9b474b 100644
--- a/tests/auto/qml/qqmlimport/MyPluginSupported/MyItem.qml
+++ b/tests/auto/qml/qqmlimport/MyPluginSupported/MyItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlimport/MyPluginUnsupported/MyItem.qml b/tests/auto/qml/qqmlimport/MyPluginUnsupported/MyItem.qml
index 943ce3309f..960b9b474b 100644
--- a/tests/auto/qml/qqmlimport/MyPluginUnsupported/MyItem.qml
+++ b/tests/auto/qml/qqmlimport/MyPluginUnsupported/MyItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/Preferred.qml b/tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/Preferred.qml
new file mode 100644
index 0000000000..a4af255b56
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/Preferred.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ objectName: "wrong"
+}
diff --git a/tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/qmldir b/tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/qmldir
new file mode 100644
index 0000000000..6b04c0eb5f
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/qmldir
@@ -0,0 +1,3 @@
+module ModuleWithPrefer2
+prefer :/qqmlimport/ModuleWithPrefer2/
+Preferred 1.0 Preferred.qml
diff --git a/tests/auto/qml/qqmlimport/data/MyModuleName/Font.js b/tests/auto/qml/qqmlimport/data/MyModuleName/Font.js
new file mode 100644
index 0000000000..7036c0a739
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/MyModuleName/Font.js
@@ -0,0 +1,4 @@
+.pragma library
+.import QtQuick as QtQuick
+
+var exampleVar = 12;
diff --git a/tests/auto/qml/qqmlimport/data/MyModuleName/qmldir b/tests/auto/qml/qqmlimport/data/MyModuleName/qmldir
new file mode 100644
index 0000000000..43add34163
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/MyModuleName/qmldir
@@ -0,0 +1,2 @@
+module MyModuleName
+Font 0.1 Font.js
diff --git a/tests/auto/qml/qqmlimport/data/fileDotSlashImport.qml b/tests/auto/qml/qqmlimport/data/fileDotSlashImport.qml
new file mode 100644
index 0000000000..83dbd566f3
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/fileDotSlashImport.qml
@@ -0,0 +1,6 @@
+import QtQml
+import 'file://./MyModuleName' as MyModuleName
+
+QtObject {
+ objectName: MyModuleName.Font.exampleVar
+}
diff --git a/tests/auto/qml/qqmlimport/data/noimport/Main.qml b/tests/auto/qml/qqmlimport/data/noimport/Main.qml
new file mode 100644
index 0000000000..d473b43d7b
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/noimport/Main.qml
@@ -0,0 +1,5 @@
+pragma Strict
+
+TheThing {
+ width: 640
+}
diff --git a/tests/auto/qml/qqmlimport/data/noimport/qmldir b/tests/auto/qml/qqmlimport/data/noimport/qmldir
new file mode 100644
index 0000000000..3034edba51
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/noimport/qmldir
@@ -0,0 +1,3 @@
+module noimport
+Main 1.0 Main.qml
+
diff --git a/tests/auto/qml/qqmlimport/data/prefer2.qml b/tests/auto/qml/qqmlimport/data/prefer2.qml
new file mode 100644
index 0000000000..c0727dc13d
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/prefer2.qml
@@ -0,0 +1,3 @@
+import ModuleWithPrefer2
+
+Pickles {}
diff --git a/tests/auto/qml/qqmlimport/data/qualifiedScriptImport.qml b/tests/auto/qml/qqmlimport/data/qualifiedScriptImport.qml
new file mode 100644
index 0000000000..de4b02afbb
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/qualifiedScriptImport.qml
@@ -0,0 +1,8 @@
+import QtQuick
+import 'MyModuleName' as MyModuleName
+
+Item {
+ property var a: MyModuleName.Font.exampleVar
+ property var b: Font.SmallCaps
+ property var c: Font.exampleVar
+}
diff --git a/tests/auto/qml/qqmlimport/data/testfile_supported.qml b/tests/auto/qml/qqmlimport/data/testfile_supported.qml
index eb4995bacf..dc20a91d06 100644
--- a/tests/auto/qml/qqmlimport/data/testfile_supported.qml
+++ b/tests/auto/qml/qqmlimport/data/testfile_supported.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import MyPluginSupported 1.0
diff --git a/tests/auto/qml/qqmlimport/data/testfile_unsupported.qml b/tests/auto/qml/qqmlimport/data/testfile_unsupported.qml
index 81156f1624..38ad7ad258 100644
--- a/tests/auto/qml/qqmlimport/data/testfile_unsupported.qml
+++ b/tests/auto/qml/qqmlimport/data/testfile_unsupported.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import MyPluginUnsupported 1.0
diff --git a/tests/auto/qml/qqmlimport/qmldir b/tests/auto/qml/qqmlimport/qmldir
new file mode 100644
index 0000000000..ca29b16cfb
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/qmldir
@@ -0,0 +1,2 @@
+module ModuleWithPrefer2
+Pickles 1.0 Preferred.qml
diff --git a/tests/auto/qml/qqmlimport/qmlimports.qt.conf b/tests/auto/qml/qqmlimport/qmlimports.qt.conf
new file mode 100644
index 0000000000..3a63cc797f
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/qmlimports.qt.conf
@@ -0,0 +1,3 @@
+[Paths]
+Prefix = ""
+QmlImports = ":/a/path", ":/another/path", ":/even/more/path"
diff --git a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
index 38970a3b99..fe14281387 100644
--- a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
+++ b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
@@ -1,23 +1,50 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <private/qmlutils_p.h>
+#include <private/qqmlengine_p.h>
+#include <private/qqmlimport_p.h>
-#include <QtCore/qscopeguard.h>
-#include <QtTest/QtTest>
-#include <QQmlApplicationEngine>
-#include <QQmlAbstractUrlInterceptor>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
-#include <private/qqmlimport_p.h>
-#include <private/qqmlengine_p.h>
-#include <QtQuickTestUtils/private/qmlutils_p.h>
-#include <QQmlComponent>
+
+#include <QtTest/qsignalspy.h>
+
+#include <QtQml/qqmlabstracturlinterceptor.h>
+#include <QtQml/qqmlapplicationengine.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlmoduleregistration.h>
+
+#include <QtCore/qscopeguard.h>
+#include <QtCore/qlibraryinfo.h>
+#include <QtCore/private/qlibraryinfo_p.h>
+
+class TheThing : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(int width MEMBER m_width FINAL)
+
+public:
+ int m_width = 12;
+};
+
+void qml_register_types_noimport()
+{
+ qmlRegisterTypesAndRevisions<TheThing>("noimport", 1);
+ qmlRegisterModule("noimport", 1, 0);
+}
class tst_QQmlImport : public QQmlDataTest
{
Q_OBJECT
public:
- tst_QQmlImport();
+ tst_QQmlImport()
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
+ , noimportRegistration("noimport", qml_register_types_noimport)
+ {
+ }
private slots:
void importPathOrder();
@@ -34,10 +61,18 @@ private slots:
void importDependenciesPrecedence();
void cleanup();
void envResourceImportPath();
+ void preferResourcePath_data();
void preferResourcePath();
void invalidFileImport_data();
void invalidFileImport();
void implicitWithDependencies();
+ void qualifiedScriptImport();
+ void invalidImportUrl();
+ void registerTypesFromImplicitImport();
+ void containsAllQtConfEntries();
+
+private:
+ QQmlModuleRegistration noimportRegistration;
};
void tst_QQmlImport::cleanup()
@@ -72,12 +107,21 @@ void tst_QQmlImport::envResourceImportPath()
QVERIFY((importPaths.contains(path.startsWith(u':') ? QLatin1String("qrc") + path : path)));
}
+void tst_QQmlImport::preferResourcePath_data()
+{
+ QTest::addColumn<QUrl>("file");
+ QTest::addRow("without qmldir") << testFileUrl("prefer.qml");
+ QTest::addRow("with qmldir") << testFileUrl("prefer2.qml");
+}
+
void tst_QQmlImport::preferResourcePath()
{
+ QFETCH(QUrl, file);
+
QQmlEngine engine;
engine.addImportPath(dataDirectory());
- QQmlComponent component(&engine, testFileUrl("prefer.qml"));
+ QQmlComponent component(&engine, file);
QVERIFY2(component.isReady(), component.errorString().toUtf8());
QScopedPointer<QObject> o(component.create());
QCOMPARE(o->objectName(), "right");
@@ -123,9 +167,62 @@ void tst_QQmlImport::implicitWithDependencies()
QCOMPARE(o->objectName(), QStringLiteral("notARectangle"));
}
+void tst_QQmlImport::qualifiedScriptImport()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("qualifiedScriptImport.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("a"), QVariant::fromValue<double>(12));
+ QCOMPARE(o->property("b"), QVariant::fromValue<int>(3));
+ QCOMPARE(o->property("c"), QVariant());
+}
+
+void tst_QQmlImport::invalidImportUrl()
+{
+ QQmlEngine engine;
+ const QUrl url = testFileUrl("fileDotSlashImport.qml");
+ QQmlComponent component(&engine, url);
+ QVERIFY(component.isError());
+ QCOMPARE(
+ component.errorString(),
+ url.toString() + QLatin1String(
+ ":2 Cannot resolve URL for import \"file://./MyModuleName\"\n"));
+}
+
+void tst_QQmlImport::registerTypesFromImplicitImport()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("noimport/Main.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ TheThing *t = qobject_cast<TheThing *>(o.data());
+ QVERIFY(t);
+ QCOMPARE(t->m_width, 640);
+}
+
+void tst_QQmlImport::containsAllQtConfEntries()
+{
+ QString qtConfPath(u":/qmlimports.qt.conf");
+ QLibraryInfoPrivate::setQtconfManualPath(&qtConfPath);
+ QLibraryInfoPrivate::reload();
+ auto cleanup = qScopeGuard([](){
+ QLibraryInfoPrivate::setQtconfManualPath(nullptr);
+ QLibraryInfoPrivate::reload();
+ });
+ QQmlEngine engine;
+ auto importPaths = engine.importPathList();
+ QVERIFY(importPaths.contains(u"qrc:/a/path"));
+ QVERIFY(importPaths.contains(u"qrc:/another/path"));
+ QVERIFY(importPaths.contains(u"qrc:/even/more/path"));
+}
+
void tst_QQmlImport::testDesignerSupported()
{
- QQuickView *window = new QQuickView();
+ std::unique_ptr<QQuickView> window = std::make_unique<QQuickView>();
window->engine()->addImportPath(directory());
window->setSource(testFileUrl("testfile_supported.qml"));
@@ -137,8 +234,7 @@ void tst_QQmlImport::testDesignerSupported()
QQmlImports::setDesignerSupportRequired(true);
//imports are cached so we create a new window
- delete window;
- window = new QQuickView();
+ window = std::make_unique<QQuickView>();
window->engine()->addImportPath(directory());
window->engine()->clearComponentCache();
@@ -154,21 +250,19 @@ void tst_QQmlImport::testDesignerSupported()
QTest::ignoreMessage(QtWarningMsg, warningString.toLocal8Bit());
window->setSource(testFileUrl("testfile_unsupported.qml"));
QVERIFY(!window->errors().isEmpty());
-
- delete window;
}
void tst_QQmlImport::uiFormatLoading()
{
int size = 0;
- QQmlApplicationEngine *test = new QQmlApplicationEngine(testFileUrl("TestForm.ui.qml"));
+ std::unique_ptr<QQmlApplicationEngine> test = std::make_unique<QQmlApplicationEngine>(testFileUrl("TestForm.ui.qml"));
test->addImportPath(directory());
QCOMPARE(test->rootObjects().size(), ++size);
QVERIFY(test->rootObjects()[size -1]);
QVERIFY(test->rootObjects()[size -1]->property("success").toBool());
- QSignalSpy objectCreated(test, SIGNAL(objectCreated(QObject*,QUrl)));
+ QSignalSpy objectCreated(test.get(), SIGNAL(objectCreated(QObject*,QUrl)));
test->load(testFileUrl("TestForm.ui.qml"));
QCOMPARE(objectCreated.size(), size);//one less than rootObjects().size() because we missed the first one
QCOMPARE(test->rootObjects().size(), ++size);
@@ -193,13 +287,6 @@ void tst_QQmlImport::uiFormatLoading()
QCOMPARE(test->rootObjects().size(), ++size);
QVERIFY(test->rootObjects()[size -1]);
QVERIFY(test->rootObjects()[size -1]->property("success").toBool());
-
- delete test;
-}
-
-tst_QQmlImport::tst_QQmlImport()
- : QQmlDataTest(QT_QMLTEST_DATADIR)
-{
}
void tst_QQmlImport::importPathOrder()
@@ -503,6 +590,25 @@ void tst_QQmlImport::registerModuleImport()
qmlUnregisterModuleImport("MyPluginSupported", 2, "QtQuick", 2);
qmlUnregisterModuleImport("MyPluginSupported", 2, "ShadowQuick", 1);
+
+ qmlRegisterTypesAndRevisions<NotItem>("NoQmldir", 2);
+ qmlRegisterModuleImport("NoQmldir", QQmlModuleImportModuleAny, "QtQml", QQmlModuleImportAuto);
+
+ {
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(R"(
+ import NoQmldir 2.0
+ QtObject {
+ property Item item: Item {}
+ }
+ )", QUrl::fromLocalFile(""));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
+ NotItem *item = object->property("item").value<NotItem *>();
+ QVERIFY(item);
+ }
}
void tst_QQmlImport::importDependenciesPrecedence()
diff --git a/tests/auto/qml/qqmlincubator/CMakeLists.txt b/tests/auto/qml/qqmlincubator/CMakeLists.txt
index 230609bb1d..3a38868e76 100644
--- a/tests/auto/qml/qqmlincubator/CMakeLists.txt
+++ b/tests/auto/qml/qqmlincubator/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlincubator Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlincubator LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlincubator/data/garbageCollection2.qml b/tests/auto/qml/qqmlincubator/data/garbageCollection2.qml
new file mode 100644
index 0000000000..b5ba531ede
--- /dev/null
+++ b/tests/auto/qml/qqmlincubator/data/garbageCollection2.qml
@@ -0,0 +1,12 @@
+import QtQml
+QtObject {
+ property Component comp: Component {
+ QtObject {}
+ }
+
+ property QtObject incubated: {
+ var i = comp.incubateObject(null, {}, Qt.Synchronous);
+ gc();
+ return i.object
+ }
+}
diff --git a/tests/auto/qml/qqmlincubator/testtypes.cpp b/tests/auto/qml/qqmlincubator/testtypes.cpp
index c94ef73c20..4e449a1b5a 100644
--- a/tests/auto/qml/qqmlincubator/testtypes.cpp
+++ b/tests/auto/qml/qqmlincubator/testtypes.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testtypes.h"
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlincubator/testtypes.h b/tests/auto/qml/qqmlincubator/testtypes.h
index e4c48d9d13..4942957986 100644
--- a/tests/auto/qml/qqmlincubator/testtypes.h
+++ b/tests/auto/qml/qqmlincubator/testtypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPES_H
#define TESTTYPES_H
diff --git a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
index 1baf61574e..948dc66e71 100644
--- a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
+++ b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testtypes.h"
#include <QUrl>
@@ -1148,7 +1148,7 @@ void tst_qqmlincubator::garbageCollection()
QQmlComponent component(&engine, testFileUrl("garbageCollection.qml"));
QScopedPointer<QObject> obj(component.create());
- engine.collectGarbage();
+ gc(engine);
std::atomic<bool> b{true};
controller.incubateWhile(&b);
@@ -1166,8 +1166,14 @@ void tst_qqmlincubator::garbageCollection()
incubatorVariant.clear();
// verify incubator is correctly collected now that incubation is complete and all references are gone
- engine.collectGarbage();
+ gc(engine);
QVERIFY(weakIncubatorRef.isNullOrUndefined());
+
+ QQmlComponent component2(&engine, testFileUrl("garbageCollection2.qml"));
+ QVERIFY2(component2.isReady(), qPrintable(component2.errorString()));
+ QScopedPointer<QObject> obj2(component2.create());
+ QVERIFY(!obj2.isNull());
+ QVERIFY(obj2->property("incubated").value<QObject *>() != nullptr);
}
void tst_qqmlincubator::requiredProperties()
diff --git a/tests/auto/qml/qqmlinfo/CMakeLists.txt b/tests/auto/qml/qqmlinfo/CMakeLists.txt
index 32e6c5ebd9..db00af9ea8 100644
--- a/tests/auto/qml/qqmlinfo/CMakeLists.txt
+++ b/tests/auto/qml/qqmlinfo/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlinfo Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlinfo LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlinfo/attached.cpp b/tests/auto/qml/qqmlinfo/attached.cpp
index 5ced27f3c9..88ad5d88dd 100644
--- a/tests/auto/qml/qqmlinfo/attached.cpp
+++ b/tests/auto/qml/qqmlinfo/attached.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "attached.h"
diff --git a/tests/auto/qml/qqmlinfo/attached.h b/tests/auto/qml/qqmlinfo/attached.h
index c719da8bcc..8d4018f88d 100644
--- a/tests/auto/qml/qqmlinfo/attached.h
+++ b/tests/auto/qml/qqmlinfo/attached.h
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp b/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp
index 4908ca210b..ebe1416c7d 100644
--- a/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp
+++ b/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtTest/qsignalspy.h>
@@ -213,7 +213,7 @@ void tst_qqmlinfo::attachedObject()
{
QQmlComponent component(&engine, testFileUrl("AttachedObject.qml"));
- QSignalSpy warningSpy(&engine, SIGNAL(warnings(const QList<QQmlError> &)));
+ QSignalSpy warningSpy(&engine, SIGNAL(warnings(QList<QQmlError>)));
QVERIFY(warningSpy.isValid());
const QString qmlBindingLoopMessage = "QML Rectangle: Binding loop detected for property \"width\"";
diff --git a/tests/auto/qml/qqmlinstantiator/CMakeLists.txt b/tests/auto/qml/qqmlinstantiator/CMakeLists.txt
index 59280f8c7d..7e453b9671 100644
--- a/tests/auto/qml/qqmlinstantiator/CMakeLists.txt
+++ b/tests/auto/qml/qqmlinstantiator/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlinstantiator Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlinstantiator LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlinstantiator/data/listDataDestruction.qml b/tests/auto/qml/qqmlinstantiator/data/listDataDestruction.qml
new file mode 100644
index 0000000000..82d707af37
--- /dev/null
+++ b/tests/auto/qml/qqmlinstantiator/data/listDataDestruction.qml
@@ -0,0 +1,20 @@
+import QtQml
+
+QtObject {
+ id: menu
+
+ Component.onCompleted: dt = new Date();
+ property date dt
+ property Instantiator i: Instantiator {
+ model: {
+ var model = [];
+ var d = menu.dt;
+ model.push({text: "A"});
+ return model;
+ }
+ delegate: QtObject {
+ objectName: modelData.text
+ Component.onCompleted: menu.objectName = objectName
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlinstantiator/data/removeDuringModelChange.qml b/tests/auto/qml/qqmlinstantiator/data/removeDuringModelChange.qml
new file mode 100644
index 0000000000..079e376549
--- /dev/null
+++ b/tests/auto/qml/qqmlinstantiator/data/removeDuringModelChange.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.15
+import QtQml.Models 2.15
+
+Instantiator {
+ delegate: QtObject {
+ function deactivate() {
+ model.active = false;
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlinstantiator/stringmodel.h b/tests/auto/qml/qqmlinstantiator/stringmodel.h
index d9676b9460..2b0c725e05 100644
--- a/tests/auto/qml/qqmlinstantiator/stringmodel.h
+++ b/tests/auto/qml/qqmlinstantiator/stringmodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Dmitrii Kosarev aka Kakadu <kakadu.hafanana@gmail.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef STRINGMODEL_H
#define STRINGMODEL_H
diff --git a/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp b/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp
index 1097c65f02..de7c6645a9 100644
--- a/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp
+++ b/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp
@@ -1,7 +1,8 @@
// Copyright (C) 2016 Research In Motion.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QSignalSpy>
+#include <QSortFilterProxyModel>
#include <QDebug>
#include <QtQml/qqmlengine.h>
@@ -28,12 +29,15 @@ private slots:
void activeModelChangeInteraction();
void intModelChange();
void createAndRemove();
+ void removeDuringModelChange();
void asynchronous_data();
void asynchronous();
void handlerWithParent();
void boundDelegateComponent();
+
+ void listDataDestruction();
};
tst_qqmlinstantiator::tst_qqmlinstantiator()
@@ -306,6 +310,103 @@ void tst_qqmlinstantiator::boundDelegateComponent()
QCOMPARE(b->objectAt(2)->objectName(), QStringLiteral("root3"));
}
+void tst_qqmlinstantiator::listDataDestruction()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("listDataDestruction.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), QLatin1String("A"));
+}
+
+class SingleBoolItemModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ SingleBoolItemModel(QObject *parent = nullptr) : QAbstractListModel(parent) {}
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override
+ {
+ if (parent.isValid())
+ return 0;
+ return 1;
+ }
+
+ QVariant data(const QModelIndex &index, int role) const override
+ {
+ if (index.parent().isValid() || index.row() != 0 || index.column() != 0
+ || role != Qt::UserRole)
+ return QVariant();
+
+ return m_active;
+ }
+
+ bool setData(const QModelIndex &index, const QVariant &value,
+ int role) override {
+ if (index.parent().isValid() || index.row() != 0 || index.column() != 0
+ || role != Qt::UserRole || m_active == value.toBool())
+ return false;
+
+ m_active = value.toBool();
+ Q_EMIT dataChanged(index, index, QList<int>{Qt::UserRole});
+ return true;
+ }
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return { {Qt::UserRole, "active"} };
+ }
+
+private:
+ bool m_active = true;
+};
+
+class FilterBoolRoleProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+public:
+ FilterBoolRoleProxyModel(QObject *parent = nullptr)
+ : QSortFilterProxyModel(parent) {}
+
+ bool filterAcceptsRow(int source_row,
+ const QModelIndex &source_parent) const override
+ {
+ return sourceModel()->index(source_row, 0, source_parent).data(Qt::UserRole).toBool();
+ }
+};
+
+void tst_qqmlinstantiator::removeDuringModelChange()
+{
+ SingleBoolItemModel model;
+
+ FilterBoolRoleProxyModel proxyModel;
+ proxyModel.setSourceModel(&model);
+ proxyModel.setFilterRole(Qt::UserRole);
+ QCOMPARE(proxyModel.rowCount(), 1);
+
+ QQmlEngine engine;
+ const QUrl url(testFileUrl("removeDuringModelChange.qml"));
+ QQmlComponent component(&engine, url);
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY2(!o.isNull(), qPrintable(component.errorString()));
+
+ QQmlInstantiator *instantiator = qobject_cast<QQmlInstantiator *>(o.data());
+
+ instantiator->setModel(QVariant::fromValue(&proxyModel));
+
+ QSignalSpy removedSpy(instantiator, &QQmlInstantiator::objectRemoved);
+ QMetaObject::invokeMethod(instantiator->object(), "deactivate");
+
+ // We should still be alive at this point.
+ QCOMPARE(removedSpy.size(), 1);
+ QCOMPARE(proxyModel.rowCount(), 0);
+}
+
QTEST_MAIN(tst_qqmlinstantiator)
#include "tst_qqmlinstantiator.moc"
diff --git a/tests/auto/qml/qqmlitemmodels/CMakeLists.txt b/tests/auto/qml/qqmlitemmodels/CMakeLists.txt
index 632e98206b..80f210f668 100644
--- a/tests/auto/qml/qqmlitemmodels/CMakeLists.txt
+++ b/tests/auto/qml/qqmlitemmodels/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlitemmodels Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlitemmodels LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlitemmodels/data/modelindex.qml b/tests/auto/qml/qqmlitemmodels/data/modelindex.qml
index 2756f04120..7bf8bfb5a2 100644
--- a/tests/auto/qml/qqmlitemmodels/data/modelindex.qml
+++ b/tests/auto/qml/qqmlitemmodels/data/modelindex.qml
@@ -8,6 +8,7 @@ ItemModelsTest {
property var parent: modelIndex.parent
property var model: modelIndex.model
property var internalId: modelIndex.internalId
+ property var displayData: modelIndex.data(Qt.DisplayRole)
onSignalWithModelIndex: {
isValid = index.valid
@@ -16,5 +17,6 @@ ItemModelsTest {
parent = index.parent
model = index.model
internalId = index.internalId
+ displayData = index.data(Qt.DisplayRole)
}
}
diff --git a/tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml b/tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml
index 85987bdcac..aa43252100 100644
--- a/tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml
+++ b/tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml
@@ -8,6 +8,7 @@ ItemModelsTest {
property var parent: persistentModelIndex.parent
property var model: persistentModelIndex.model
property var internalId: persistentModelIndex.internalId
+ property var displayData: persistentModelIndex.data(Qt.DisplayRole)
property var pmi
@@ -18,6 +19,7 @@ ItemModelsTest {
parent = index.parent
model = index.model
internalId = index.internalId
+ displayData = index.data(Qt.DisplayRole)
pmi = createPersistentModelIndex(model.index(0, 0))
}
diff --git a/tests/auto/qml/qqmlitemmodels/qtestmodel.h b/tests/auto/qml/qqmlitemmodels/qtestmodel.h
index 6cbec533b1..6c442b06b7 100644
--- a/tests/auto/qml/qqmlitemmodels/qtestmodel.h
+++ b/tests/auto/qml/qqmlitemmodels/qtestmodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef Q_TEST_MODEL_H
#define Q_TEST_MODEL_H
@@ -251,6 +251,8 @@ public:
mutable bool wrongIndex;
struct Node {
+ Q_DISABLE_COPY_MOVE(Node)
+
Node *parent;
QVector<Node *> children;
@@ -261,8 +263,7 @@ public:
~Node()
{
- foreach (Node *n, children)
- delete n;
+ qDeleteAll(children);
}
void addRows(int row, int count)
diff --git a/tests/auto/qml/qqmlitemmodels/testtypes.h b/tests/auto/qml/qqmlitemmodels/testtypes.h
index 57ac9c12d1..3bbd566cd1 100644
--- a/tests/auto/qml/qqmlitemmodels/testtypes.h
+++ b/tests/auto/qml/qqmlitemmodels/testtypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPES_H
#define TESTTYPES_H
diff --git a/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp b/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp
index 339a61f996..1182759519 100644
--- a/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp
+++ b/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -55,6 +55,7 @@ void tst_qqmlitemmodels::modelIndex()
QCOMPARE(object->property("parent").toModelIndex(), index.parent());
QCOMPARE(object->property("model").value<QAbstractItemModel *>(), index.model());
QCOMPARE(object->property("internalId").toULongLong(), index.internalId());
+ QCOMPARE(object->property("displayData"), index.data(Qt::DisplayRole));
if (i < 3) {
index = model.index(2 + i, 4 - i, index);
@@ -79,6 +80,7 @@ void tst_qqmlitemmodels::persistentModelIndex()
QCOMPARE(object->property("parent").toModelIndex(), index.parent());
QCOMPARE(object->property("model").value<QAbstractItemModel *>(), index.model());
QCOMPARE(object->property("internalId").toULongLong(), index.internalId());
+ QCOMPARE(object->property("displayData"), index.data(Qt::DisplayRole));
if (i < 2) {
index = model.index(2 + i, 4 - i, index);
diff --git a/tests/auto/qml/qqmljsscope/CMakeLists.txt b/tests/auto/qml/qqmljsscope/CMakeLists.txt
index 542d217d8d..be8e136fc8 100644
--- a/tests/auto/qml/qqmljsscope/CMakeLists.txt
+++ b/tests/auto/qml/qqmljsscope/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmljsscope LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/CMakeLists.txt b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/CMakeLists.txt
index 3431398f47..5215159373 100644
--- a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/CMakeLists.txt
+++ b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/CMakeLists.txt
@@ -8,9 +8,10 @@ qt_autogen_tools_initial_setup(qqmljsscope_test_module)
target_include_directories(qqmljsscope_test_module PUBLIC cpptypes/)
target_link_libraries(qqmljsscope_test_module PUBLIC Qt::Core Qt::Qml Qt::Gui)
+qt_policy(SET QTP0001 NEW)
+
qt6_add_qml_module(qqmljsscope_test_module
URI QQmlJSScopeTests
- AUTO_RESOURCE_PREFIX
SOURCES
singleton.h singleton.cpp
extensiontypes.h
diff --git a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/extensiontypes.h b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/extensiontypes.h
index f5fbde1b27..82fc3b58d2 100644
--- a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/extensiontypes.h
+++ b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/extensiontypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef EXTENSIONTYPES_H
#define EXTENSIONTYPES_H
@@ -18,6 +18,17 @@ public:
Extension(QObject *parent = nullptr) : QObject(parent) { }
int getCount() const { return 42; }
void setCount(int) { }
+
+ enum EnumFromExtension {
+ ThisIsTheEnumFromExtension,
+ };
+ Q_ENUM(EnumFromExtension)
+ enum FlagFromExtension {
+ ThisIsTheFlagFromExtension,
+ };
+ Q_DECLARE_FLAGS(FlagsFromExtension, FlagFromExtension)
+ Q_FLAG(FlagsFromExtension)
+
Q_SIGNALS:
void countChanged();
};
@@ -41,6 +52,16 @@ public:
Extended(QObject *parent = nullptr) : QObject(parent) { }
double getCount() const { return 0.0; }
void setCount(double) { }
+
+ enum EnumFromExtended {
+ ThisIsTheEnumFromExtended,
+ };
+ Q_ENUM(EnumFromExtended)
+ enum FlagFromExtended {
+ ThisIsTheFlagFromExtended,
+ };
+ Q_DECLARE_FLAGS(FlagsFromExtended, FlagFromExtended)
+ Q_FLAG(FlagsFromExtended)
Q_SIGNALS:
void countChanged();
};
diff --git a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.cpp b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.cpp
index 280ff6163e..56efc324d3 100644
--- a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.cpp
+++ b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "singleton.h"
diff --git a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.h b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.h
index 78aa6466d7..a78b85e1d9 100644
--- a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.h
+++ b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef SINGLETON_H
#define SINGLETON_H
diff --git a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/typewithproperties.h b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/typewithproperties.h
index 2c812a6d9d..9126cf8f69 100644
--- a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/typewithproperties.h
+++ b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/typewithproperties.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPEWITHPROPERTIES_H
#define TYPEWITHPROPERTIES_H
diff --git a/tests/auto/qml/qqmljsscope/QualifiedNamesTests/testtypes.h b/tests/auto/qml/qqmljsscope/QualifiedNamesTests/testtypes.h
index c323645f73..514a98881d 100644
--- a/tests/auto/qml/qqmljsscope/QualifiedNamesTests/testtypes.h
+++ b/tests/auto/qml/qqmljsscope/QualifiedNamesTests/testtypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPES_H
#define TESTTYPES_H
diff --git a/tests/auto/qml/qqmljsscope/data/attachedTypeResolution.qml b/tests/auto/qml/qqmljsscope/data/attachedTypeResolution.qml
new file mode 100644
index 0000000000..d6062be1f6
--- /dev/null
+++ b/tests/auto/qml/qqmljsscope/data/attachedTypeResolution.qml
@@ -0,0 +1,6 @@
+import QtQml
+import QtQuick
+
+Window {
+
+}
diff --git a/tests/auto/qml/qqmljsscope/data/methodAndSignalSourceLocation.qml b/tests/auto/qml/qqmljsscope/data/methodAndSignalSourceLocation.qml
new file mode 100644
index 0000000000..52841e323c
--- /dev/null
+++ b/tests/auto/qml/qqmljsscope/data/methodAndSignalSourceLocation.qml
@@ -0,0 +1,16 @@
+import QtQml
+
+QtObject {
+ function f1() { }
+ function f2(a) { }
+ function f3(a: int) { }
+ function f4(a, b) { }
+ function f5(a, b): void { }
+ function f6(a, b, c): void {
+ // Nothing
+ }
+
+ signal s1()
+ signal s2(a: int)
+ signal s3(a: int, b: string)
+}
diff --git a/tests/auto/qml/qqmljsscope/data/ownModuleName.qml b/tests/auto/qml/qqmljsscope/data/ownModuleName.qml
new file mode 100644
index 0000000000..6e43ce6b05
--- /dev/null
+++ b/tests/auto/qml/qqmljsscope/data/ownModuleName.qml
@@ -0,0 +1,10 @@
+import QtQuick
+
+Item {
+ Item { id: child }
+ component IC: Item {
+ Item {
+ id: childInIC
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmljsscope/data/requiredAlias.qml b/tests/auto/qml/qqmljsscope/data/requiredAlias.qml
new file mode 100644
index 0000000000..77f70dea2b
--- /dev/null
+++ b/tests/auto/qml/qqmljsscope/data/requiredAlias.qml
@@ -0,0 +1,20 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ id: self
+
+ property int nonRequired
+ property alias sameScopeAlias: self.nonRequired
+ required sameScopeAlias
+
+ property alias innerScopeAlias: inner.nonRequiredInner
+ required innerScopeAlias
+
+ Item {
+ id: inner
+ property int nonRequiredInner
+ }
+}
diff --git a/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp b/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp
index 09c6601858..05e0b2870a 100644
--- a/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp
+++ b/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -35,9 +35,9 @@ class tst_qqmljsscope : public QQmlDataTest
{
const QFileInfo fi(url);
QFile f(fi.absoluteFilePath());
- f.open(QIODevice::ReadOnly);
- QByteArray data(fi.size(), Qt::Uninitialized);
- f.read(data.data(), data.size());
+ if (!f.open(QIODevice::ReadOnly))
+ qFatal("Could not open file %s", qPrintable(url));
+ QByteArray data = f.readAll();
return QString::fromUtf8(data);
}
@@ -71,6 +71,7 @@ class tst_qqmljsscope : public QQmlDataTest
logger.setCode(sourceCode);
logger.setSilent(expectErrorsOrWarnings);
QQmlJSScope::Ptr target = QQmlJSScope::create();
+ target->setOwnModuleName(u"HelloModule"_s);
QQmlJSImportVisitor visitor(target, &m_importer, &logger, dataDirectory());
QQmlJSTypeResolver typeResolver { &m_importer };
typeResolver.init(&visitor, document->program);
@@ -92,6 +93,7 @@ private Q_SLOTS:
void signalCreationDifferences();
void allTypesAvailable();
void shadowing();
+ void requiredAlias();
#ifdef LABS_QML_MODELS_PRESENT
void componentWrappedObjects();
@@ -106,9 +108,15 @@ private Q_SLOTS:
void scriptIndices();
void extensions();
void emptyBlockBinding();
- void qualifiedName();
+ void hasOwnEnumerationKeys();
+ void ownModuleName();
void resolvedNonUniqueScopes();
void compilationUnitsAreCompatible();
+ void attachedTypeResolution_data();
+ void attachedTypeResolution();
+ void builtinTypeResolution_data();
+ void builtinTypeResolution();
+ void methodAndSignalSourceLocation();
public:
tst_qqmljsscope()
@@ -160,14 +168,14 @@ void tst_qqmljsscope::orderedBindings()
QCOMPARE(std::distance(pBindingsBegin, pBindingsEnd), 2);
// check that the bindings are properly ordered
- QCOMPARE(pBindingsBegin->bindingType(), QQmlJSMetaPropertyBinding::Object);
- QCOMPARE(std::next(pBindingsBegin)->bindingType(), QQmlJSMetaPropertyBinding::Interceptor);
+ QCOMPARE(pBindingsBegin->bindingType(), QQmlSA::BindingType::Object);
+ QCOMPARE(std::next(pBindingsBegin)->bindingType(), QQmlSA::BindingType::Interceptor);
auto [itemsBindingsBegin, itemsBindingsEnd] = root->ownPropertyBindings(u"items"_s);
QCOMPARE(std::distance(itemsBindingsBegin, itemsBindingsEnd), 2);
- QCOMPARE(itemsBindingsBegin->bindingType(), QQmlJSMetaPropertyBinding::Object);
- QCOMPARE(std::next(itemsBindingsBegin)->bindingType(), QQmlJSMetaPropertyBinding::Object);
+ QCOMPARE(itemsBindingsBegin->bindingType(), QQmlSA::BindingType::Object);
+ QCOMPARE(std::next(itemsBindingsBegin)->bindingType(), QQmlSA::BindingType::Object);
QCOMPARE(itemsBindingsBegin->objectType()->baseTypeName(), u"Item"_s);
QCOMPARE(std::next(itemsBindingsBegin)->objectType()->baseTypeName(), u"Text"_s);
@@ -184,8 +192,8 @@ void tst_qqmljsscope::signalCreationDifferences()
const auto conflicting = root->ownMethods(u"conflictingPropertyChanged"_s);
QCOMPARE(conflicting.size(), 2);
- QCOMPARE(conflicting[0].methodType(), QQmlJSMetaMethod::Signal);
- QCOMPARE(conflicting[1].methodType(), QQmlJSMetaMethod::Signal);
+ QCOMPARE(conflicting[0].methodType(), QQmlJSMetaMethodType::Signal);
+ QCOMPARE(conflicting[1].methodType(), QQmlJSMetaMethodType::Signal);
const QQmlJSMetaMethod *explicitMethod = nullptr;
if (conflicting[0].isImplicitQmlPropertyChangeSignal())
@@ -204,7 +212,7 @@ void tst_qqmljsscope::allTypesAvailable()
QQmlJSImporter importer { importPaths, /* resource file mapper */ nullptr };
const auto imported = importer.importModule(u"QtQml"_s);
- QCOMPARE(imported.context(), QQmlJSScope::ContextualTypes::QML);
+ QCOMPARE(imported.context(), QQmlJS::ContextualTypes::QML);
const auto types = imported.types();
QVERIFY(types.contains(u"$internal$.QObject"_s));
QVERIFY(types.contains(u"QtObject"_s));
@@ -235,6 +243,16 @@ void tst_qqmljsscope::shadowing()
QCOMPARE(methods[u"method_shadowed"_s].parameterNames().size(), 0);
}
+void tst_qqmljsscope::requiredAlias()
+{
+ QQmlJSScope::ConstPtr root = run(u"requiredAlias.qml"_s);
+ QVERIFY(root);
+
+ // Check whether aliases marked as required are required
+ QVERIFY(root->isPropertyRequired("sameScopeAlias"));
+ QVERIFY(root->isPropertyRequired("innerScopeAlias"));
+}
+
#ifdef LABS_QML_MODELS_PRESENT
void tst_qqmljsscope::componentWrappedObjects()
{
@@ -302,7 +320,7 @@ void tst_qqmljsscope::groupedProperties()
const auto getBindingsWithinGroup =
[&](QMultiHash<QString, QQmlJSMetaPropertyBinding> *bindings, qsizetype index) -> void {
const auto &binding = anchorBindings[index];
- QCOMPARE(binding.bindingType(), QQmlJSMetaPropertyBinding::GroupProperty);
+ QCOMPARE(binding.bindingType(), QQmlSA::BindingType::GroupProperty);
auto anchorScope = binding.groupType();
QVERIFY(anchorScope);
*bindings = anchorScope->ownPropertyBindings();
@@ -316,14 +334,14 @@ void tst_qqmljsscope::groupedProperties()
QMultiHash<QString, QQmlJSMetaPropertyBinding> bindingsOfType;
getBindingsWithinGroup(&bindingsOfType, 0);
QCOMPARE(bindingsOfType.size(), 2);
- QCOMPARE(value(bindingsOfType, u"left"_s).bindingType(), QQmlJSMetaPropertyBinding::Script);
+ QCOMPARE(value(bindingsOfType, u"left"_s).bindingType(), QQmlSA::BindingType::Script);
QCOMPARE(value(bindingsOfType, u"leftMargin"_s).bindingType(),
- QQmlJSMetaPropertyBinding::NumberLiteral);
+ QQmlSA::BindingType::NumberLiteral);
QMultiHash<QString, QQmlJSMetaPropertyBinding> bindingsOfBaseType;
getBindingsWithinGroup(&bindingsOfBaseType, 1);
QCOMPARE(bindingsOfBaseType.size(), 1);
- QCOMPARE(value(bindingsOfBaseType, u"top"_s).bindingType(), QQmlJSMetaPropertyBinding::Script);
+ QCOMPARE(value(bindingsOfBaseType, u"top"_s).bindingType(), QQmlSA::BindingType::Script);
}
void tst_qqmljsscope::descriptiveNameOfNull()
@@ -337,8 +355,10 @@ void tst_qqmljsscope::descriptiveNameOfNull()
property.setPropertyName(u"foo"_s);
property.setTypeName(u"baz"_s);
QQmlJSRegisterContent unscoped = QQmlJSRegisterContent::create(
- stored, property, QQmlJSRegisterContent::ScopeProperty, QQmlJSScope::ConstPtr());
- QCOMPARE(unscoped.descriptiveName(), u"bar of (invalid type)::foo with type baz"_s);
+ property, QQmlJSRegisterContent::InvalidLookupIndex,
+ QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::ScopeProperty,
+ QQmlJSScope::ConstPtr()).storedIn(stored);
+ QCOMPARE(unscoped.descriptiveName(), u"(invalid type)::foo with type baz (stored as bar)"_s);
}
void tst_qqmljsscope::groupedPropertiesConsistency()
@@ -363,8 +383,8 @@ void tst_qqmljsscope::groupedPropertiesConsistency()
// The binding order in QQmlJSScope case is "reversed": first come
// bindings on the leaf type, followed by the bindings on the base type
- QCOMPARE(fontBindings[0].bindingType(), QQmlJSMetaPropertyBinding::GroupProperty);
- QCOMPARE(fontBindings[1].bindingType(), QQmlJSMetaPropertyBinding::Script);
+ QCOMPARE(fontBindings[0].bindingType(), QQmlSA::BindingType::GroupProperty);
+ QCOMPARE(fontBindings[1].bindingType(), QQmlSA::BindingType::Script);
}
}
@@ -378,7 +398,7 @@ void tst_qqmljsscope::groupedPropertySyntax()
// The binding order in QQmlJSScope case is "reversed": first come
// bindings on the leaf type, followed by the bindings on the base type
- QCOMPARE(fontBindings[0].bindingType(), QQmlJSMetaPropertyBinding::GroupProperty);
+ QCOMPARE(fontBindings[0].bindingType(), QQmlSA::BindingType::GroupProperty);
auto fontScope = fontBindings[0].groupType();
QVERIFY(fontScope);
QCOMPARE(fontScope->accessSemantics(), QQmlJSScope::AccessSemantics::Value);
@@ -390,9 +410,8 @@ void tst_qqmljsscope::groupedPropertySyntax()
return bindings.value(key, QQmlJSMetaPropertyBinding(QQmlJS::SourceLocation {}));
};
- QCOMPARE(value(subbindings, u"pixelSize"_s).bindingType(),
- QQmlJSMetaPropertyBinding::NumberLiteral);
- QCOMPARE(value(subbindings, u"bold"_s).bindingType(), QQmlJSMetaPropertyBinding::BoolLiteral);
+ QCOMPARE(value(subbindings, u"pixelSize"_s).bindingType(), QQmlSA::BindingType::NumberLiteral);
+ QCOMPARE(value(subbindings, u"bold"_s).bindingType(), QQmlSA::BindingType::BoolLiteral);
}
void tst_qqmljsscope::attachedProperties()
@@ -407,7 +426,7 @@ void tst_qqmljsscope::attachedProperties()
const auto getBindingsWithinAttached =
[&](QMultiHash<QString, QQmlJSMetaPropertyBinding> *bindings, qsizetype index) -> void {
const auto &binding = keysBindings[index];
- QCOMPARE(binding.bindingType(), QQmlJSMetaPropertyBinding::AttachedProperty);
+ QCOMPARE(binding.bindingType(), QQmlSA::BindingType::AttachedProperty);
auto keysScope = binding.attachingType();
QVERIFY(keysScope);
QCOMPARE(keysScope->accessSemantics(), QQmlJSScope::AccessSemantics::Reference);
@@ -422,23 +441,21 @@ void tst_qqmljsscope::attachedProperties()
QMultiHash<QString, QQmlJSMetaPropertyBinding> bindingsOfType;
getBindingsWithinAttached(&bindingsOfType, 0);
QCOMPARE(bindingsOfType.size(), 2);
- QCOMPARE(value(bindingsOfType, u"enabled"_s).bindingType(),
- QQmlJSMetaPropertyBinding::BoolLiteral);
- QCOMPARE(value(bindingsOfType, u"forwardTo"_s).bindingType(),
- QQmlJSMetaPropertyBinding::Script);
+ QCOMPARE(value(bindingsOfType, u"enabled"_s).bindingType(), QQmlSA::BindingType::BoolLiteral);
+ QCOMPARE(value(bindingsOfType, u"forwardTo"_s).bindingType(), QQmlSA::BindingType::Script);
QMultiHash<QString, QQmlJSMetaPropertyBinding> bindingsOfBaseType;
getBindingsWithinAttached(&bindingsOfBaseType, 1);
QCOMPARE(bindingsOfBaseType.size(), 1);
- QCOMPARE(value(bindingsOfBaseType, u"priority"_s).bindingType(),
- QQmlJSMetaPropertyBinding::Script);
+ QCOMPARE(value(bindingsOfBaseType, u"priority"_s).bindingType(), QQmlSA::BindingType::Script);
}
inline QString getScopeName(const QQmlJSScope::ConstPtr &scope)
{
Q_ASSERT(scope);
QQmlJSScope::ScopeType type = scope->scopeType();
- if (type == QQmlJSScope::GroupedPropertyScope || type == QQmlJSScope::AttachedPropertyScope)
+ if (type == QQmlSA::ScopeType::GroupedPropertyScope
+ || type == QQmlSA::ScopeType::AttachedPropertyScope)
return scope->internalName();
return scope->baseTypeName();
}
@@ -507,7 +524,7 @@ void tst_qqmljsscope::scriptIndices()
QmlIR::Document document(false); // we need QmlIR information here
QQmlJSScope::ConstPtr root = run(u"functionAndBindingIndices.qml"_s, &document);
QVERIFY(root);
- QVERIFY(document.javaScriptCompilationUnit.unitData());
+ QVERIFY(document.javaScriptCompilationUnit->unitData());
// compare QQmlJSScope and QmlIR:
@@ -537,8 +554,9 @@ void tst_qqmljsscope::scriptIndices()
const auto suitableScope = [](const QQmlJSScope::ConstPtr &scope) {
const auto type = scope->scopeType();
- return type == QQmlJSScope::QMLScope || type == QQmlJSScope::GroupedPropertyScope
- || type == QQmlJSScope::AttachedPropertyScope;
+ return type == QQmlSA::ScopeType::QMLScope
+ || type == QQmlSA::ScopeType::GroupedPropertyScope
+ || type == QQmlSA::ScopeType::AttachedPropertyScope;
};
QList<QQmlJSScope::ConstPtr> queue;
@@ -550,7 +568,7 @@ void tst_qqmljsscope::scriptIndices()
if (suitableScope(current)) {
const auto methods = current->ownMethods();
for (const auto &method : methods) {
- if (method.methodType() == QQmlJSMetaMethod::Signal)
+ if (method.methodType() == QQmlJSMetaMethodType::Signal)
continue;
QString name = method.methodName();
auto relativeIndex = method.jsFunctionIndex();
@@ -563,7 +581,7 @@ void tst_qqmljsscope::scriptIndices()
const auto bindings = current->ownPropertyBindings();
for (const auto &binding : bindings) {
- if (binding.bindingType() != QQmlJSMetaPropertyBinding::Script)
+ if (binding.bindingType() != QQmlSA::BindingType::Script)
continue;
QString name = binding.propertyName();
auto relativeIndex = binding.scriptIndex();
@@ -674,28 +692,50 @@ void tst_qqmljsscope::emptyBlockBinding()
QVERIFY(root->hasOwnPropertyBindings(u"y"_s));
}
-void tst_qqmljsscope::qualifiedName()
+void tst_qqmljsscope::hasOwnEnumerationKeys()
{
- QQmlJSScope::ConstPtr root = run(u"qualifiedName.qml"_s);
+ QQmlJSScope::ConstPtr root = run(u"extensions.qml"_s);
QVERIFY(root);
+ QQmlJSScope::ConstPtr extendedDerived = root->childScopes().front();
+ QVERIFY(extendedDerived);
+ // test that enumeration keys from base cannot be found
+ QVERIFY(!extendedDerived->hasOwnEnumerationKey(u"ThisIsTheEnumFromExtended"_s));
+ QVERIFY(!extendedDerived->hasOwnEnumerationKey(u"ThisIsTheFlagFromExtended"_s));
+
+ QQmlJSScope::ConstPtr extended = extendedDerived->baseType();
+ QVERIFY(extended);
+
+ QVERIFY(extended->hasOwnEnumerationKey(u"ThisIsTheEnumFromExtended"_s));
+ QVERIFY(extended->hasOwnEnumerationKey(u"ThisIsTheFlagFromExtended"_s));
+ QVERIFY(!extended->hasOwnEnumerationKey(u"ThisIsTheEnumFromExtension"_s));
+ QVERIFY(!extended->hasOwnEnumerationKey(u"ThisIsTheFlagFromExtension"_s));
+}
- auto qualifiedNameOf = [](const QQmlJSScope::ConstPtr &ptr) -> QString {
- if (ptr->baseType())
- return ptr->baseType()->qualifiedName();
- else
- return u""_s;
- };
-
- QCOMPARE(root->childScopes().size(), 4);
- QQmlJSScope::ConstPtr b = root->childScopes()[0];
- QQmlJSScope::ConstPtr d = root->childScopes()[1];
- QQmlJSScope::ConstPtr qualifiedA = root->childScopes()[2];
- QQmlJSScope::ConstPtr qualifiedB = root->childScopes()[3];
-
- QCOMPARE(qualifiedNameOf(b), "QualifiedNamesTests/B 5.0-6.0");
- QCOMPARE(qualifiedNameOf(d), "QualifiedNamesTests/D 6.0");
- QCOMPARE(qualifiedNameOf(qualifiedA), "QualifiedNamesTests/A 5.0");
- QCOMPARE(qualifiedNameOf(qualifiedB), "QualifiedNamesTests/B 5.0-6.0");
+void tst_qqmljsscope::ownModuleName()
+{
+ const QString moduleName = u"HelloModule"_s;
+ QQmlJSScope::ConstPtr root = run(u"ownModuleName.qml"_s);
+ QVERIFY(root);
+ QCOMPARE(root->moduleName(), moduleName);
+ QCOMPARE(root->ownModuleName(), moduleName);
+
+ QCOMPARE(root->childScopes().size(), 2);
+ QQmlJSScope::ConstPtr child = root->childScopes().front();
+ QVERIFY(child);
+ // only root and inline components have own module names, but the child should be able to query
+ // its component's module Name via moduleName()
+ QCOMPARE(child->ownModuleName(), QString());
+ QCOMPARE(child->moduleName(), moduleName);
+
+ QQmlJSScope::ConstPtr ic = root->childScopes()[1];
+ QVERIFY(ic);
+ QCOMPARE(ic->ownModuleName(), moduleName);
+ QCOMPARE(ic->moduleName(), moduleName);
+
+ QQmlJSScope::ConstPtr icChild = ic->childScopes().front();
+ QVERIFY(icChild);
+ QCOMPARE(icChild->ownModuleName(), QString());
+ QCOMPARE(icChild->moduleName(), moduleName);
}
void tst_qqmljsscope::resolvedNonUniqueScopes()
@@ -711,32 +751,32 @@ void tst_qqmljsscope::resolvedNonUniqueScopes()
{
auto topLevelBindings = root->propertyBindings(u"Component"_s);
QCOMPARE(topLevelBindings.size(), 1);
- QCOMPARE(topLevelBindings[0].bindingType(), QQmlJSMetaPropertyBinding::AttachedProperty);
+ QCOMPARE(topLevelBindings[0].bindingType(), QQmlSA::BindingType::AttachedProperty);
auto componentScope = topLevelBindings[0].attachingType();
auto componentBindings = componentScope->ownPropertyBindings();
QCOMPARE(componentBindings.size(), 2);
auto onCompletedBinding = value(componentBindings, u"onCompleted"_s);
QVERIFY(onCompletedBinding.isValid());
- QCOMPARE(onCompletedBinding.bindingType(), QQmlJSMetaPropertyBinding::Script);
- QCOMPARE(onCompletedBinding.scriptKind(), QQmlJSMetaPropertyBinding::Script_SignalHandler);
+ QCOMPARE(onCompletedBinding.bindingType(), QQmlSA::BindingType::Script);
+ QCOMPARE(onCompletedBinding.scriptKind(), QQmlSA::ScriptBindingKind::SignalHandler);
auto onDestructionBinding = value(componentBindings, u"onDestruction"_s);
QVERIFY(onDestructionBinding.isValid());
- QCOMPARE(onDestructionBinding.bindingType(), QQmlJSMetaPropertyBinding::Script);
+ QCOMPARE(onDestructionBinding.bindingType(), QQmlSA::BindingType::Script);
QCOMPARE(onDestructionBinding.scriptKind(),
- QQmlJSMetaPropertyBinding::Script_SignalHandler);
+ QQmlSA::ScriptBindingKind::SignalHandler);
}
{
auto topLevelBindings = root->propertyBindings(u"p"_s);
QCOMPARE(topLevelBindings.size(), 1);
- QCOMPARE(topLevelBindings[0].bindingType(), QQmlJSMetaPropertyBinding::GroupProperty);
+ QCOMPARE(topLevelBindings[0].bindingType(), QQmlSA::BindingType::GroupProperty);
auto pScope = topLevelBindings[0].groupType();
auto pBindings = pScope->ownPropertyBindings();
QCOMPARE(pBindings.size(), 1);
auto onXChangedBinding = value(pBindings, u"onXChanged"_s);
QVERIFY(onXChangedBinding.isValid());
- QCOMPARE(onXChangedBinding.bindingType(), QQmlJSMetaPropertyBinding::Script);
- QCOMPARE(onXChangedBinding.scriptKind(), QQmlJSMetaPropertyBinding::Script_SignalHandler);
+ QCOMPARE(onXChangedBinding.bindingType(), QQmlSA::BindingType::Script);
+ QCOMPARE(onXChangedBinding.scriptKind(), QQmlSA::ScriptBindingKind::SignalHandler);
}
}
@@ -777,8 +817,8 @@ void tst_qqmljsscope::compilationUnitsAreCompatible()
QmlIR::Document document(false); // we need QmlIR information here
QVERIFY(run(url, &document));
- QVERIFY(document.javaScriptCompilationUnit.unitData());
- getRuntimeInfoFromCompilationUnit(document.javaScriptCompilationUnit.unitData(),
+ QVERIFY(document.javaScriptCompilationUnit->unitData());
+ getRuntimeInfoFromCompilationUnit(document.javaScriptCompilationUnit->unitData(),
cachegenFunctions);
if (QTest::currentTestFailed())
return;
@@ -791,5 +831,162 @@ void tst_qqmljsscope::compilationUnitsAreCompatible()
QCOMPARE(uint(cachegenFunctions[i]->nameIndex), uint(componentFunctions[i]->nameIndex));
}
+void tst_qqmljsscope::attachedTypeResolution_data()
+{
+ QTest::addColumn<bool>("creatable");
+ QTest::addColumn<QString>("moduleName");
+ QTest::addColumn<QString>("typeName");
+ QTest::addColumn<QString>("attachedTypeName");
+ QTest::addColumn<QString>("propertyOnSelf");
+ QTest::addColumn<QString>("propertyOnAttached");
+
+ QTest::addRow("ListView") << true
+ << "QtQuick"
+ << "ListView"
+ << "QQuickListViewAttached"
+ << "orientation"
+ << "";
+ QTest::addRow("Keys") << false
+ << "QtQuick"
+ << "Keys"
+ << "QQuickKeysAttached"
+ << "priority"
+ << "priority";
+}
+
+class TestPass : public QQmlSA::ElementPass
+{
+public:
+ TestPass(QQmlSA::PassManager *manager) : QQmlSA::ElementPass(manager) { }
+ bool shouldRun(const QQmlSA::Element &) override { return true; }
+ void run(const QQmlSA::Element &) override { }
+};
+
+using PassManagerPtr = std::unique_ptr<
+ QQmlSA::PassManager, decltype(&QQmlSA::PassManagerPrivate::deletePassManager)>;
+
+void tst_qqmljsscope::attachedTypeResolution()
+{
+ QFETCH(bool, creatable);
+ QFETCH(QString, moduleName);
+ QFETCH(QString, typeName);
+ QFETCH(QString, attachedTypeName);
+ QFETCH(QString, propertyOnSelf);
+ QFETCH(QString, propertyOnAttached);
+
+ std::unique_ptr<QQmlJSLogger> logger = std::make_unique<QQmlJSLogger>();
+ QFile qmlFile("data/attachedTypeResolution.qml");
+ if (!qmlFile.open(QIODevice::ReadOnly | QIODevice::Text))
+ QSKIP("Unable to open qml file");
+
+ logger->setCode(qmlFile.readAll());
+ logger->setFileName(QString(qmlFile.filesystemFileName().string().c_str()));
+ QQmlJSImporter importer{ { "data" }, nullptr, true };
+ QStringList defaultImportPaths =
+ QStringList{ QLibraryInfo::path(QLibraryInfo::QmlImportsPath) };
+ importer.setImportPaths(defaultImportPaths);
+ QQmlJSTypeResolver resolver(&importer);
+ const auto &implicitImportDirectory = QQmlJSImportVisitor::implicitImportDirectory(
+ logger->fileName(), importer.resourceFileMapper());
+ QQmlJSImportVisitor v{
+ QQmlJSScope::create(), &importer, logger.get(), implicitImportDirectory, {}
+ };
+
+ PassManagerPtr manager(
+ QQmlSA::PassManagerPrivate::createPassManager(&v, &resolver),
+ &QQmlSA::PassManagerPrivate::deletePassManager);
+
+ TestPass pass{ manager.get() };
+ const auto &resolved = pass.resolveType(moduleName, typeName);
+
+ QVERIFY(!resolved.isNull());
+ const auto &attachedType = pass.resolveAttached(moduleName, typeName);
+ QVERIFY(!attachedType.isNull());
+ QCOMPARE(attachedType.name(), attachedTypeName);
+
+ if (propertyOnAttached != "") {
+ QEXPECT_FAIL("Keys", "Keys and QQuickKeysAttached have the same properties", Continue);
+ QVERIFY(!resolved.hasProperty(propertyOnAttached));
+ QVERIFY(attachedType.hasProperty(propertyOnAttached));
+ }
+ if (propertyOnSelf != "") {
+ QEXPECT_FAIL("Keys", "Keys and QQuickKeysAttached have the same properties", Continue);
+ QVERIFY(!attachedType.hasProperty(propertyOnSelf));
+ }
+
+ if (creatable)
+ QVERIFY(resolved.hasProperty(propertyOnSelf));
+}
+
+
+
+void tst_qqmljsscope::builtinTypeResolution_data()
+{
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<QString>("typeName");
+
+ QTest::addRow("global_QtObject") << true << "Qt";
+ QTest::addRow("function") << true << "function";
+ QTest::addRow("Array") << true << "Array";
+ QTest::addRow("invalid") << false << "foobar";
+ QTest::addRow("Number") << true << "Number";
+ QTest::addRow("bool") << true << "bool";
+ QTest::addRow("QString") << true << "QString";
+}
+
+void tst_qqmljsscope::builtinTypeResolution()
+{
+ QFETCH(bool, valid);
+ QFETCH(QString, typeName);
+
+ QQmlJSImporter importer{ { "data" }, nullptr, true };
+ QStringList defaultImportPaths =
+ QStringList{ QLibraryInfo::path(QLibraryInfo::QmlImportsPath) };
+ importer.setImportPaths(defaultImportPaths);
+ QQmlJSTypeResolver resolver(&importer);
+ const auto &implicitImportDirectory = QQmlJSImportVisitor::implicitImportDirectory({}, nullptr);
+ QQmlJSLogger logger;
+ QQmlJSImportVisitor v{
+ QQmlJSScope::create(), &importer, &logger, implicitImportDirectory, {}
+ };
+
+ PassManagerPtr manager(
+ QQmlSA::PassManagerPrivate::createPassManager(&v, &resolver),
+ &QQmlSA::PassManagerPrivate::deletePassManager);
+
+ TestPass pass{ manager.get() };
+ auto element = pass.resolveBuiltinType(typeName);
+ QCOMPARE(element.isNull(), !valid);
+}
+
+void tst_qqmljsscope::methodAndSignalSourceLocation()
+{
+ QmlIR::Document document(false);
+ auto jsscope = run(u"methodAndSignalSourceLocation.qml"_s, false);
+
+ std::array<std::array<int, 9>, 2> offsetsByLineEnding = {
+ std::array{ 29, 51, 74, 102, 128, 160, 219, 235, 257 }, // 1 char line endings
+ std::array{ 32, 55, 79, 108, 135, 168, 231, 248, 271 } // 2 char line endinds
+ };
+
+ // Try to detect the size of line endings as they lead to different source locations
+ auto offset1 = jsscope->methods("f1")[0].sourceLocation().offset;
+ QVERIFY(offset1 == 29 || offset1 == 32);
+ bool oneCharEndings = offset1 == 29;
+ std::array<int, 9> &offsets = oneCharEndings ? offsetsByLineEnding[0] : offsetsByLineEnding[1];
+
+ using namespace QQmlJS;
+ QCOMPARE(jsscope->methods("f1")[0].sourceLocation(), SourceLocation(offsets[0], 17, 4, 5));
+ QCOMPARE(jsscope->methods("f2")[0].sourceLocation(), SourceLocation(offsets[1], 18, 5, 5));
+ QCOMPARE(jsscope->methods("f3")[0].sourceLocation(), SourceLocation(offsets[2], 23, 6, 5));
+ QCOMPARE(jsscope->methods("f4")[0].sourceLocation(), SourceLocation(offsets[3], 21, 7, 5));
+ QCOMPARE(jsscope->methods("f5")[0].sourceLocation(), SourceLocation(offsets[4], 27, 8, 5));
+ QCOMPARE(jsscope->methods("f6")[0].sourceLocation(), SourceLocation(offsets[5], oneCharEndings ? 53 : 55, 9, 5));
+
+ QCOMPARE(jsscope->methods("s1")[0].sourceLocation(), SourceLocation(offsets[6], 11, 13, 5));
+ QCOMPARE(jsscope->methods("s2")[0].sourceLocation(), SourceLocation(offsets[7], 17, 14, 5));
+ QCOMPARE(jsscope->methods("s3")[0].sourceLocation(), SourceLocation(offsets[8], 28, 15, 5));
+}
+
QTEST_MAIN(tst_qqmljsscope)
#include "tst_qqmljsscope.moc"
diff --git a/tests/auto/qml/qqmllanguage/CMakeLists.txt b/tests/auto/qml/qqmllanguage/CMakeLists.txt
index e07f741bf6..9fff8f2118 100644
--- a/tests/auto/qml/qqmllanguage/CMakeLists.txt
+++ b/tests/auto/qml/qqmllanguage/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmllanguage Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmllanguage LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -27,6 +33,8 @@ qt_internal_add_test(tst_qqmllanguage
TESTDATA ${test_data}
)
+add_subdirectory(testhelper)
+
#### Keys ignored in scope 1:.:.:qqmllanguage.pro:<TRUE>:
# OTHER_FILES = "data/readonlyObjectProperty.qml"
# QML_IMPORT_NAME = "StaticTest"
diff --git a/tests/auto/qml/qqmllanguage/data/AliasHolder.qml b/tests/auto/qml/qqmllanguage/data/AliasHolder.qml
new file mode 100644
index 0000000000..42aed6ed26
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/AliasHolder.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ property alias strokeStyle: path.restoreMode
+ property Binding p: Binding { id: path }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnumSelfReference.qml b/tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnumSelfReference.qml
new file mode 100644
index 0000000000..0ec43bf7aa
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnumSelfReference.qml
@@ -0,0 +1,8 @@
+import QtQml
+import Test
+
+QtObject {
+ enum A { B, C, D }
+ property int e: CompositeTypeWithEnumSelfReference.C
+ property int f: CompositeTypeWithEnumSelfReference.A.D
+}
diff --git a/tests/auto/qml/qqmllanguage/data/Comps/IconPropertiesGroup.qml b/tests/auto/qml/qqmllanguage/data/Comps/IconPropertiesGroup.qml
new file mode 100644
index 0000000000..232c755bfb
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/Comps/IconPropertiesGroup.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+QtObject {
+ function dothing() { console.log("do") }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/Comps/OverlayDrawer.qml b/tests/auto/qml/qqmllanguage/data/Comps/OverlayDrawer.qml
new file mode 100644
index 0000000000..713c760a04
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/Comps/OverlayDrawer.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property IconPropertiesGroup handleOpenIcon: IconPropertiesGroup {}
+}
diff --git a/tests/auto/qml/qqmllanguage/data/Comps/qmldir b/tests/auto/qml/qqmllanguage/data/Comps/qmldir
new file mode 100644
index 0000000000..0a68a376f6
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/Comps/qmldir
@@ -0,0 +1,4 @@
+module Comps
+OverlayDrawer 254.0 OverlayDrawer.qml
+IconPropertiesGroup 254.0 IconPropertiesGroup.qml
+
diff --git a/tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml b/tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml
new file mode 100644
index 0000000000..134eacf913
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml
@@ -0,0 +1,27 @@
+import QtQml
+
+QtObject {
+ id: root
+ objectName: "theRoot"
+
+ component ObjectWithColor: QtObject {
+ property string color
+ property var varvar
+ }
+
+ property ObjectWithColor border: ObjectWithColor {
+ objectName: root.objectName
+ color: root.trueBorderColor
+ varvar: root.trueBorderVarvar
+ }
+
+ readonly property rect readonlyRect: ({x: 12, y: 13, width: 14, height: 15})
+
+ property alias borderObjectName: root.border.objectName
+ property alias borderColor: root.border.color
+ property alias borderVarvar: root.border.varvar
+ property alias readonlyRectX: root.readonlyRect.x
+
+ property string trueBorderColor: "green"
+ property var trueBorderVarvar: 1234
+}
diff --git a/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired1.qml b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired1.qml
new file mode 100644
index 0000000000..f549e851a3
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired1.qml
@@ -0,0 +1,6 @@
+pragma Singleton
+import QtQml
+
+QtObject {
+ required property int i
+}
diff --git a/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired2.qml b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired2.qml
new file mode 100644
index 0000000000..1f9e7e3a42
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired2.qml
@@ -0,0 +1,8 @@
+pragma Singleton
+import QtQml
+
+QtObject {
+ property QtObject o: QtObject {
+ required property int i
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/qmldir b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/qmldir
new file mode 100644
index 0000000000..46e397ca76
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/qmldir
@@ -0,0 +1,4 @@
+module SingletonWithRequiredProperties
+
+singleton SingletonWithRequired1 1.0 SingletonWithRequired1.qml
+singleton SingletonWithRequired2 1.0 SingletonWithRequired2.qml
diff --git a/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle1.qml b/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle1.qml
new file mode 100644
index 0000000000..6186faa00b
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle1.qml
@@ -0,0 +1,15 @@
+import QtQml
+
+QtObject {
+ id: self
+ property QtObject b
+ property Component c
+ function a() : TypeAnnotationCycle2 { return c.createObject() as TypeAnnotationCycle2 }
+
+ Component.onCompleted: {
+ c = Qt.createComponent("TypeAnnotationCycle2.qml");
+ let v = a();
+ v.addTypeAnnotationCycle1(self as TypeAnnotationCycle1);
+ b = v.b;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle2.qml b/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle2.qml
new file mode 100644
index 0000000000..9e3ffa86d2
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle2.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ property QtObject b
+ function addTypeAnnotationCycle1(c: TypeAnnotationCycle1) { b = c; }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/UIToolBar.qml b/tests/auto/qml/qqmllanguage/data/UIToolBar.qml
new file mode 100644
index 0000000000..08a22d2492
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/UIToolBar.qml
@@ -0,0 +1,10 @@
+import QtQml
+
+QtObject {
+ id: root
+ signal doneClicked()
+ signal foo()
+
+ onObjectNameChanged: foo()
+ Component.onCompleted: root.foo.connect(root.doneClicked)
+}
diff --git a/tests/auto/qml/qqmllanguage/data/alias.16.qml b/tests/auto/qml/qqmllanguage/data/alias.16.qml
index 4637aec58f..335d240003 100644
--- a/tests/auto/qml/qqmllanguage/data/alias.16.qml
+++ b/tests/auto/qml/qqmllanguage/data/alias.16.qml
@@ -2,7 +2,7 @@ import QtQuick 2.0
import QtQuick.Window 2.0
Window {
- visible: true
+ visible: false
property alias list: repeater.model
diff --git a/tests/auto/qml/qqmllanguage/data/aliasWriter.qml b/tests/auto/qml/qqmllanguage/data/aliasWriter.qml
new file mode 100644
index 0000000000..4001c2af34
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/aliasWriter.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+AliasHolder {
+ strokeStyle: 1
+}
diff --git a/tests/auto/qml/qqmllanguage/data/ambiguousComponents.qml b/tests/auto/qml/qqmllanguage/data/ambiguousComponents.qml
new file mode 100644
index 0000000000..64c31b46d6
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/ambiguousComponents.qml
@@ -0,0 +1,16 @@
+import QtQuick
+import Comps as Comps
+
+Comps.OverlayDrawer {
+ id: self
+
+ property var dothing
+
+ Component.onCompleted: dothing = handleOpenIcon.dothing
+
+ function dodo() { dothing() }
+
+ function testInstanceOf() : bool {
+ return self instanceof Comps.OverlayDrawer
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/asCastToInlineComponent.qml b/tests/auto/qml/qqmllanguage/data/asCastToInlineComponent.qml
new file mode 100644
index 0000000000..428ccd5eef
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/asCastToInlineComponent.qml
@@ -0,0 +1,16 @@
+import QtQml
+
+QtObject {
+ id: root
+
+ component MyItem: QtObject {
+ property int value: 10
+ onValueChanged: root.objectName = "value: " + value
+ }
+
+ property Instantiator i: Instantiator {
+ id: loader
+ delegate: MyItem {}
+ onObjectChanged: (loader.object as MyItem).value = 20
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/asValueType.qml b/tests/auto/qml/qqmllanguage/data/asValueType.qml
new file mode 100644
index 0000000000..b51dc9c6ec
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/asValueType.qml
@@ -0,0 +1,20 @@
+pragma ValueTypeBehavior: Addressable
+import QtQml
+import StaticTest
+
+QtObject {
+ property var a
+ property rect b: a as rect
+ property bool c: a instanceof rect
+ property bool d: ({x: 10, y: 20}) instanceof point
+ property var e: ({x: 10, y: 20}) as point
+ property var f: "red" as withString
+ property var g: "green" as string
+ property rect bb
+ property var p: bb as size;
+ property var q: this as size;
+ property var r: ({}) as size;
+ property var s: 11 as size;
+ property var t: Component as size;
+ property var u: Qt as size;
+}
diff --git a/tests/auto/qml/qqmllanguage/data/asValueTypeGood.qml b/tests/auto/qml/qqmllanguage/data/asValueTypeGood.qml
new file mode 100644
index 0000000000..777ada3848
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/asValueTypeGood.qml
@@ -0,0 +1,35 @@
+pragma ValueTypeBehavior: Assertable
+import QtQml as Q
+import StaticTest as S
+
+Q.QtObject {
+ property var a
+ property rect b: a as Q.rect
+ property bool c: a instanceof Q.rect
+ property bool d: ({x: 10, y: 20}) instanceof Q.point
+ property var e: ({x: 10, y: 20}) as Q.point
+ property var f: "red" as S.withString
+ property var g: "green" as Q.string
+
+ property var h: new S.withString("red")
+ property var i: {
+ let p = new Q.point;
+ p.x = 10
+ p.y = 20
+ return p
+ }
+
+ property var j: 4.0 as Q.int
+ property var k: (4.5 / 1.5) as Q.int
+ property var l: 5 as Q.double
+ property var m: "something" as Q.var
+ property var n: 1 as Q.bool
+ property var o: Infinity as Q.int
+
+ property var p: b as Q.size;
+ property var q: this as Q.size;
+ property var r: ({}) as Q.size;
+ property var s: 11 as Q.size;
+ property var t: Q.Component as Q.size;
+ property var u: Q.Qt as Q.size;
+}
diff --git a/tests/auto/qml/qqmllanguage/data/badICAnnotation.qml b/tests/auto/qml/qqmllanguage/data/badICAnnotation.qml
new file mode 100644
index 0000000000..6f0db53f2a
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/badICAnnotation.qml
@@ -0,0 +1,25 @@
+import QtQml
+
+QtObject {
+ id: self
+
+ function doStuff(status: Binding.NotAnInlineComponent) : int {
+ return status
+ }
+
+ function doStuff2(status: InlineComponentBase.IC) : QtObject {
+ return status
+ }
+
+ function doStuff3(status: InlineComponentBase.NotIC) : QtObject {
+ return status
+ }
+
+ property InlineComponentBase.IC ic: InlineComponentBase.IC {}
+
+ property int a: doStuff(5)
+ property QtObject b: doStuff2(ic)
+ property QtObject c: doStuff3(ic)
+ property QtObject d: doStuff2(self)
+}
+
diff --git a/tests/auto/qml/qqmllanguage/data/SingletonTest.qml b/tests/auto/qml/qqmllanguage/data/badSingleton/SingletonTest.qml
index 70e1671754..70e1671754 100644
--- a/tests/auto/qml/qqmllanguage/data/SingletonTest.qml
+++ b/tests/auto/qml/qqmllanguage/data/badSingleton/SingletonTest.qml
diff --git a/tests/auto/qml/qqmllanguage/data/qmldir b/tests/auto/qml/qqmllanguage/data/badSingleton/qmldir
index c946de657c..c946de657c 100644
--- a/tests/auto/qml/qqmllanguage/data/qmldir
+++ b/tests/auto/qml/qqmllanguage/data/badSingleton/qmldir
diff --git a/tests/auto/qml/qqmllanguage/data/qtbug_85932.qml b/tests/auto/qml/qqmllanguage/data/badSingleton/qtbug_85932.qml
index aa21558220..aa21558220 100644
--- a/tests/auto/qml/qqmllanguage/data/qtbug_85932.qml
+++ b/tests/auto/qml/qqmllanguage/data/badSingleton/qtbug_85932.qml
diff --git a/tests/auto/qml/qqmllanguage/data/corpseInQmlList.qml b/tests/auto/qml/qqmllanguage/data/corpseInQmlList.qml
new file mode 100644
index 0000000000..dc0e145064
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/corpseInQmlList.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+QtObject {
+ property var b;
+
+ function returnList(a: QtObject) : list<QtObject> {
+ return [a]
+ }
+
+ function setB(a: QtObject) {
+ b = { b: returnList(a) }
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml b/tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml
new file mode 100644
index 0000000000..50eaa7c3e2
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml
@@ -0,0 +1,9 @@
+import QtQml
+
+DeepAliasOnIC {
+ borderObjectName: "theLeaf"
+ borderColor: "black"
+ borderVarvar: "mauve"
+}
+
+
diff --git a/tests/auto/qml/qqmllanguage/data/deepAliasOnReadonly.qml b/tests/auto/qml/qqmllanguage/data/deepAliasOnReadonly.qml
new file mode 100644
index 0000000000..f5ae62406b
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/deepAliasOnReadonly.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+DeepAliasOnIC {
+ readonlyRectX: 55
+}
diff --git a/tests/auto/qml/qqmllanguage/data/derivedFromUnexposedBase.qml b/tests/auto/qml/qqmllanguage/data/derivedFromUnexposedBase.qml
new file mode 100644
index 0000000000..b508474a36
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/derivedFromUnexposedBase.qml
@@ -0,0 +1,6 @@
+import Test
+
+DerivedFromUnexposedBase {
+ group.value: 42
+ groupGadget.value: 42
+}
diff --git a/tests/auto/qml/qqmllanguage/data/dynamicGroupPropertyRejected.qml b/tests/auto/qml/qqmllanguage/data/dynamicGroupPropertyRejected.qml
new file mode 100644
index 0000000000..2fffea25c6
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/dynamicGroupPropertyRejected.qml
@@ -0,0 +1,5 @@
+import Test
+
+DerivedFromUnexposedBase {
+ dynamic.value: "This should fail"
+}
diff --git a/tests/auto/qml/qqmllanguage/data/enumPropsManyUnderlyingTypes.qml b/tests/auto/qml/qqmllanguage/data/enumPropsManyUnderlyingTypes.qml
new file mode 100644
index 0000000000..b713d2aa24
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/enumPropsManyUnderlyingTypes.qml
@@ -0,0 +1,10 @@
+import Test
+
+EnumPropsManyUnderlyingTypes {
+ si8prop: EnumPropsManyUnderlyingTypes.ResolvedValue
+ ui8prop: EnumPropsManyUnderlyingTypes.ResolvedValue
+ si16prop: EnumPropsManyUnderlyingTypes.ResolvedValue
+ ui16prop: EnumPropsManyUnderlyingTypes.ResolvedValue
+ si64prop: EnumPropsManyUnderlyingTypes.ResolvedValue
+ ui64prop: EnumPropsManyUnderlyingTypes.ResolvedValue
+}
diff --git a/tests/auto/qml/qqmllanguage/data/enumScopes.qml b/tests/auto/qml/qqmllanguage/data/enumScopes.qml
new file mode 100644
index 0000000000..c71872387f
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/enumScopes.qml
@@ -0,0 +1,16 @@
+import QtQml 2.15
+import EnumScopeTest 1.0
+
+QtObject {
+ property NonSingleton n: NonSingleton {
+ id: nonSingleton
+ }
+
+ property bool singletonUnscoped: Singleton.enumProperty === Singleton.EnumValue2
+ property bool singletonScoped: Singleton.enumProperty === Singleton.EnumType.EnumValue2
+ property bool nonSingletonUnscoped: nonSingleton.enumProperty === NonSingleton.EnumValue2
+ property bool nonSingletonScoped: nonSingleton.enumProperty === NonSingleton.EnumType.EnumValue2
+
+ property int singletonScopedValue: EnumProviderSingleton.Expected.Value
+ property int singletonUnscopedValue: EnumProviderSingleton.Value
+}
diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentWithImplicitComponent.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentWithImplicitComponent.qml
new file mode 100644
index 0000000000..902dfb501d
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/inlineComponentWithImplicitComponent.qml
@@ -0,0 +1,27 @@
+import QtQml
+
+QtObject {
+ component C1: QtObject {
+ property Component comp: null
+ }
+
+ component C2: C1 {
+ comp: QtObject {
+ objectName: "green"
+ }
+ }
+
+ component C3: C1 {
+ comp: Component {
+ QtObject {
+ objectName: "blue"
+ }
+ }
+ }
+
+ property QtObject c1: C1 {}
+ property QtObject c2: C2 {}
+ property QtObject c3: C3 {}
+
+ objectName: c2.comp.createObject().objectName + " " + c3.comp.createObject().objectName
+}
diff --git a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.errors.txt b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.errors.txt
index d76f18ba89..5ddb8a2e6d 100644
--- a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.errors.txt
@@ -1 +1 @@
-5:5:Invalid grouped property access: Property "o" with type "QVariant", which is not a value type
+5:7:Cannot assign to non-existent property "blah"
diff --git a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.3.errors.txt b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.3.errors.txt
index 9a0422753f..ced96fba83 100644
--- a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.3.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.3.errors.txt
@@ -1 +1 @@
-4:5:Invalid grouped property access: Property "customType" with type "MyCustomVariantType", which is not a value type
+4:5:Invalid grouped property access: Property "customType" with type "MyCustomVariantType", which is neither a value nor an object type
diff --git a/tests/auto/qml/qqmllanguage/data/invokableCtors.qml b/tests/auto/qml/qqmllanguage/data/invokableCtors.qml
new file mode 100644
index 0000000000..35a8d7bf08
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/invokableCtors.qml
@@ -0,0 +1,12 @@
+import QtQml as QQ
+import Test as VV
+
+QQ.QtObject {
+ property QQ.QtObject oo: new QQ.QtObject()
+ property QQ.QtObject pp: new QQ.QtObject(oo)
+ property VV.vv v: new VV.vv("green")
+
+ property VV.InvokableSingleton i: new VV.InvokableSingleton(5, oo)
+ property VV.InvokableExtended k: new VV.InvokableExtended()
+ property VV.InvokableUncreatable l: new VV.InvokableUncreatable()
+}
diff --git a/tests/auto/qml/qqmllanguage/data/isNullOrUndefined_interpreter.qml b/tests/auto/qml/qqmllanguage/data/isNullOrUndefined_interpreter.qml
new file mode 100644
index 0000000000..460d4667f8
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/isNullOrUndefined_interpreter.qml
@@ -0,0 +1,22 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ id: self
+ property int a: 3
+ property var result
+ Component.onCompleted: {
+ var sum = 0
+ let f = function() {
+ return self.notthere ?? self.a
+ }
+
+ // Not enough times for the jit to kick in (should run on the interpreter)
+ for (let i = 0; i < 1; i++) {
+ sum = sum + f()
+ }
+ result = sum
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/isNullOrUndefined_jit.qml b/tests/auto/qml/qqmllanguage/data/isNullOrUndefined_jit.qml
new file mode 100644
index 0000000000..43c82f436c
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/isNullOrUndefined_jit.qml
@@ -0,0 +1,22 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ id: self
+ property int a: 3
+ property int result
+ Component.onCompleted: {
+ var sum = 0
+ let f = function() {
+ return self.notthere ?? self.a
+ }
+
+ // Enough times for the jit to kick in (should run on the jit)
+ for (let i = 0; i < 50; i++) {
+ sum = sum + f()
+ }
+ result = sum
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/jitExceptions.qml b/tests/auto/qml/qqmllanguage/data/jitExceptions.qml
new file mode 100644
index 0000000000..c5e11af31d
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/jitExceptions.qml
@@ -0,0 +1,16 @@
+import QtQml
+
+QtObject {
+ function burn() {
+ return control.font
+ }
+
+ Component.onCompleted: {
+ for (var a = 0; a < 10; ++a) {
+ try { burn() } catch(e) {}
+ }
+
+ burn();
+ }
+
+}
diff --git a/tests/auto/qml/qqmllanguage/data/jsonArrayProperty.qml b/tests/auto/qml/qqmllanguage/data/jsonArrayProperty.qml
new file mode 100644
index 0000000000..5bd563a288
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/jsonArrayProperty.qml
@@ -0,0 +1,191 @@
+import QtQml
+import TypeWithQJsonArrayProperty
+
+TypeWithQJsonArrayProperty {
+ function jsArray() { return [1, 2, 3] }
+
+ jsonArray: jsArray()
+
+ property list<int> concatenatedJsonArray: jsonArray.concat([4, 5, 6])
+ property list<int> concatenatedJsArray: jsArray().concat([4, 5, 6])
+
+ property bool entriesMatch: {
+ var iterator = jsonArray.entries();
+ for (var [index, element] of jsArray().entries()) {
+ var v = iterator.next().value;
+ if (index !== v[0] || element !== v[1]) {
+ console.log(index, v[0], element, v[1]);
+ return false;
+ }
+ }
+
+ var iterator = jsArray().entries();
+ for (var [index, element] of jsonArray.entries()) {
+ var v = iterator.next().value;
+ if (index !== v[0] || element !== v[1]) {
+ console.log(index, v[0], element, v[1]);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ property bool jsonArrayEvery: jsonArray.every(element => element != 0)
+ property bool jsArrayEvery: jsArray().every(element => element != 0)
+
+ property list<int> jsonArrayFiltered: jsonArray.filter(element => element > 2)
+ property list<int> jsArrayFiltered: jsArray().filter(element => element > 2)
+
+ property int jsonArrayFind: jsonArray.find(element => element === 2)
+ property int jsArrayFind: jsArray().find(element => element === 2)
+
+ property int jsonArrayFindIndex: jsonArray.findIndex(element => element === 1)
+ property int jsArrayFindIndex: jsArray().findIndex(element => element === 1)
+
+ property string jsonArrayForEach
+ property string jsArrayForEach
+
+ property bool jsonArrayIncludes: jsonArray.includes(3)
+ property bool jsArrayIncludes: jsArray().includes(3)
+
+ property int jsonArrayIndexOf: jsonArray.indexOf(2)
+ property int jsArrayIndexOf: jsArray().indexOf(2)
+
+ property string jsonArrayJoin: jsonArray.join()
+ property string jsArrayJoin: jsArray().join()
+
+ property bool keysMatch: {
+ var iterator = jsonArray.keys();
+ for (var index of jsArray().keys()) {
+ var v = iterator.next().value;
+ if (index !== v) {
+ console.log(index, v);
+ return false;
+ }
+ }
+
+ var iterator = jsArray().keys();
+ for (var index of jsonArray.keys()) {
+ var v = iterator.next().value;
+ if (index !== v) {
+ console.log(index, v);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ property int jsonArrayLastIndexOf: jsonArray.lastIndexOf(1)
+ property int jsArrayLastIndexOf: jsArray().lastIndexOf(1)
+
+ property list<string> jsonArrayMap: jsonArray.map(element => element.toString())
+ property list<string> jsArrayMap: jsArray().map(element => element.toString())
+
+ property int jsonArrayReduce: jsonArray.reduce((acc, element) => acc - element, 40)
+ property int jsArrayReduce: jsArray().reduce((acc, element) => acc - element, 40)
+
+ property string jsonArrayReduceRight: jsonArray.reduceRight((acc, element) => acc + element.toString(), "")
+ property string jsArrayReduceRight: jsArray().reduceRight((acc, element) => acc + element.toString(), "")
+
+ property list<int> jsonArraySlice: jsonArray.slice(0, 1)
+ property list<int> jsArraySlice: jsArray().slice(0, 1)
+
+ property bool jsonArraySome: jsonArray.some(element => element === 1)
+ property bool jsArraySome: jsArray().some(element => element === 1)
+
+ property string stringifiedLocaleJsonArray: jsonArray.toLocaleString()
+ property string stringifiedLocaleJsArray: jsArray().toLocaleString()
+
+ property string stringifiedJsonArray: jsonArray.toString()
+ property string stringifiedJsArray: jsArray().toString()
+
+ property bool valuesMatch: {
+ var iterator = jsonArray.values();
+ for (var obj of jsArray().values()) {
+ var v = iterator.next().value;
+ if (obj !== v) {
+ console.log(obj, v);
+ return false;
+ }
+ }
+
+ var iterator = jsArray().values();
+ for (var obj of jsonArray.values()) {
+ var v = iterator.next().value;
+ if (obj !== v) {
+ console.log(obj, v);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // In-place mutation methods.
+ // Set by onCompleted if mutating jsonArray and then accessing it
+ // respects the mutation and the mutation behaves as for an array.
+ property bool jsonArrayWasCopiedWithin: false
+ property bool jsonArrayWasFilled: false
+ property bool jsonArrayWasPopped: false
+ property bool jsonArrayWasPushed: false
+ property bool jsonArrayWasReversed: false
+ property bool jsonArrayWasShifted: false
+ property bool jsonArrayWasSpliced: false
+ property bool jsonArrayWasUnshifted: false
+ property bool jsonArrayWasSorted: false
+
+ Component.onCompleted: {
+ function equals(lhs, rhs) {
+ return lhs.toString() === rhs.toString()
+ }
+
+ jsonArray.forEach(element => jsonArrayForEach += "-" + element + "-");
+ jsArray().forEach(element => jsArrayForEach += "-" + element + "-");
+
+ var array = jsArray()
+
+ jsonArray.copyWithin(1, 0, 1)
+ array.copyWithin(1, 0, 1)
+ jsonArrayWasCopiedWithin = equals(jsonArray, array)
+
+ jsonArray.fill(7, 0, 1)
+ array.fill(7, 0, 1)
+ jsonArrayWasFilled = equals(jsonArray, array)
+
+ jsonArray.pop()
+ array.pop()
+ jsonArrayWasPopped = equals(jsonArray, array)
+
+ jsonArray.push(23)
+ jsonArray.push(11)
+ jsonArray.push(54)
+ jsonArray.push(42)
+ array.push(23)
+ array.push(11)
+ array.push(54)
+ array.push(42)
+ jsonArrayWasPushed = equals(jsonArray, array)
+
+ jsonArray.reverse()
+ array.reverse()
+ jsonArrayWasReversed = equals(jsonArray, array)
+
+ jsonArray.shift()
+ array.shift()
+ jsonArrayWasShifted = equals(jsonArray, array)
+
+ jsonArray.splice(2, 1, [1, 2], 7, [1, 5])
+ array.splice(2, 1, [1, 2], 7, [1, 5])
+ jsonArrayWasSpliced = equals(jsonArray, array)
+
+ jsonArray.unshift(4, 71)
+ array.unshift(4, 71)
+ jsonArrayWasUnshifted = equals(jsonArray, array)
+
+ jsonArray.sort()
+ array.sort()
+ jsonArrayWasSorted = equals(jsonArray, array)
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/longConversion.qml b/tests/auto/qml/qqmllanguage/data/longConversion.qml
new file mode 100644
index 0000000000..fd9a9518ee
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/longConversion.qml
@@ -0,0 +1,28 @@
+import QtQml
+import Test
+
+QtObject {
+ property bool testProp: GetterObject.getFalse()
+ property bool testQProp: GetterObject.getQFalse()
+
+ property bool fromLocal
+ property bool fromQLocal
+
+ property bool fromBoolean
+ property bool fromQBoolean
+
+ Component.onCompleted: {
+ let l = GetterObject.getFalse();
+ fromLocal = l;
+
+ let b = Boolean(l);
+ fromBoolean = b;
+
+ let ql = GetterObject.getQFalse();
+ fromQLocal = ql;
+
+
+ let qb = Boolean(ql);
+ fromQBoolean = qb;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/manuallyCallSignalHandler.qml b/tests/auto/qml/qqmllanguage/data/manuallyCallSignalHandler.qml
new file mode 100644
index 0000000000..1ee71e5fd2
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/manuallyCallSignalHandler.qml
@@ -0,0 +1,11 @@
+import QtQml
+
+QtObject {
+ Component.onDestruction: {
+ console.log("evil!");
+ }
+
+ Component.onCompleted: {
+ Component.onDestruction()
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/nestedVectors.qml b/tests/auto/qml/qqmllanguage/data/nestedVectors.qml
new file mode 100644
index 0000000000..0bcea52133
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nestedVectors.qml
@@ -0,0 +1,27 @@
+import Test
+import QtQml
+
+NestedVectors {
+ id: self
+
+ property var list1
+
+ Component.onCompleted: {
+ list1 = self.getList()
+
+ let list2 = []
+ let data1 = []
+ data1.push(2)
+ data1.push(3)
+ data1.push(4)
+
+ let data2 = []
+ data2.push(5)
+ data2.push(6)
+
+ list2.push(data1)
+ list2.push(data2)
+
+ self.setList(list2)
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.1.qml b/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.1.qml
index acd5463a3c..ac5622f9fb 100644
--- a/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.1.qml
+++ b/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.1.qml
@@ -10,7 +10,7 @@ Item {
}
}
- property bool expectNull: null
+ property bool expectNull: { return null; }
function setExpectNull(b) {
success = false;
diff --git a/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.2.qml b/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.2.qml
index ed0e0d10f0..3c18739c32 100644
--- a/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.2.qml
+++ b/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.2.qml
@@ -10,7 +10,7 @@ Item {
}
}
- property bool expectNull: null
+ property bool expectNull: { return null; }
function setExpectNull(b) {
success = false;
diff --git a/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.3.qml b/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.3.qml
index f5e94ba715..e2e560199f 100644
--- a/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.3.qml
+++ b/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.3.qml
@@ -10,7 +10,7 @@ Item {
}
}
- property bool expectNull: null
+ property bool expectNull: { return null; }
function setExpectNull(b) {
success = false;
diff --git a/tests/auto/qml/qqmllanguage/data/objectInList.qml b/tests/auto/qml/qqmllanguage/data/objectInList.qml
new file mode 100644
index 0000000000..53c8c3cdd1
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/objectInList.qml
@@ -0,0 +1,17 @@
+import QtQml
+
+QtObject {
+ objectName: "parent"
+ property list<QtObject> child
+ property Component c: QtObject { objectName: "child" }
+
+ function doCreate() {
+ child.push(c.createObject(null));
+ }
+
+ Component.onCompleted: {
+ // Extra function call so that the created object cannot be on the stack
+ doCreate();
+ gc();
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/objectMethodClone.qml b/tests/auto/qml/qqmllanguage/data/objectMethodClone.qml
new file mode 100644
index 0000000000..e21179ea14
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/objectMethodClone.qml
@@ -0,0 +1,23 @@
+import QtQml
+
+QtObject {
+ id: window
+
+ property int doneClicks: 0
+
+ property UIToolBar t1: UIToolBar {
+ objectName: window.objectName
+ onDoneClicked: window.doneClicks++
+ }
+
+ property UIToolBar t2: UIToolBar {
+ objectName: window.objectName
+ onDoneClicked: window.doneClicks++
+ }
+
+ property Timer timer: Timer {
+ interval: 10
+ running: true
+ onTriggered: window.objectName = "bar"
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/optimizedSequenceShift.qml b/tests/auto/qml/qqmllanguage/data/optimizedSequenceShift.qml
new file mode 100644
index 0000000000..32765895a0
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/optimizedSequenceShift.qml
@@ -0,0 +1,14 @@
+import QtQml
+
+QtObject {
+ id: root
+
+ property int changes: 0
+
+ property list<int> numbers: [1, 2, 3, 4, 5]
+ onNumbersChanged: ++changes
+
+ property var one: numbers.shift.bind([1,2,3])()
+
+ Component.onCompleted: root.numbers.shift()
+}
diff --git a/tests/auto/qml/qqmllanguage/data/optionalChainCallOnNullProperty.qml b/tests/auto/qml/qqmllanguage/data/optionalChainCallOnNullProperty.qml
new file mode 100644
index 0000000000..00029e3953
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/optionalChainCallOnNullProperty.qml
@@ -0,0 +1,10 @@
+import QtQml
+
+QtObject {
+ id: root
+ property QtObject target: null
+
+ Component.onCompleted: {
+ target?.destroy( )
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/overrideDefaultProperty.qml b/tests/auto/qml/qqmllanguage/data/overrideDefaultProperty.qml
new file mode 100644
index 0000000000..69f9316c51
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/overrideDefaultProperty.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ property list<var> data: []
+ Item {}
+}
diff --git a/tests/auto/qml/qqmllanguage/data/retainThis.qml b/tests/auto/qml/qqmllanguage/data/retainThis.qml
new file mode 100644
index 0000000000..7a372ee236
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/retainThis.qml
@@ -0,0 +1,49 @@
+import QmlOtherThis
+import QtQml
+
+QtObject {
+ property var cppMethod: objA.greet
+ property var cppMethod2: objA.sum
+
+ property Greeter a: Greeter { id: objA; objectName: "objA" }
+ property Greeter b: Greeter { id: objB; objectName: "objB" }
+
+ function doCall() {
+ cppMethod.call(objB)
+ cppMethod2(5, 6)
+ }
+
+ property var cppMethod3;
+ function doRetrieve(g) {
+ cppMethod3 = g.greet;
+ }
+
+ function doCall2() {
+ cppMethod3();
+ }
+
+ property Greeter c: Greeter {
+ id: objC
+ objectName: "objC"
+
+ property var cppMethod: objC.sum
+
+ function doCall() {
+ cppMethod(7, 7)
+ }
+ }
+
+ Component.onCompleted: {
+ doCall();
+ doCall();
+
+ doRetrieve(objA);
+ doCall2();
+ doRetrieve(objB);
+ doCall2();
+
+ objC.doCall();
+ objC.cppMethod = objB.sum;
+ objC.doCall();
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/signatureEnforced.qml b/tests/auto/qml/qqmllanguage/data/signatureEnforced.qml
index e2ddd75b55..ec00d5d2b3 100644
--- a/tests/auto/qml/qqmllanguage/data/signatureEnforced.qml
+++ b/tests/auto/qml/qqmllanguage/data/signatureEnforced.qml
@@ -8,7 +8,7 @@ QtObject {
property withLength withLength: 5
function a(r: rect) {
- r.x = 77 // does not write back
+ r.x = 77 // does write back, but this is an evil thing to do.
}
function b(s: string) : int {
@@ -28,8 +28,11 @@ QtObject {
property int n: c(99) // creates a withLength
property int o: rect.y
+ function bad(b: int) { return b }
+
Component.onCompleted: {
a(rect)
d(rect)
+ bad(15)
}
}
diff --git a/tests/auto/qml/qqmllanguage/data/signatureIgnored.qml b/tests/auto/qml/qqmllanguage/data/signatureIgnored.qml
index 0e9d0f42dc..bdb373040d 100644
--- a/tests/auto/qml/qqmllanguage/data/signatureIgnored.qml
+++ b/tests/auto/qml/qqmllanguage/data/signatureIgnored.qml
@@ -1,6 +1,6 @@
+pragma FunctionSignatureBehavior: Ignored
import StaticTest
import QtQml
-
QtObject {
property rect rect: ({ x: 12, y: 13 })
property withLength withLength: 5
diff --git a/tests/auto/qml/qqmllanguage/data/singleton/RegisteredCompositeSingletonType.qml b/tests/auto/qml/qqmllanguage/data/singleton/RegisteredCompositeSingletonType.qml
index 5359157b31..b86477e40a 100644
--- a/tests/auto/qml/qqmllanguage/data/singleton/RegisteredCompositeSingletonType.qml
+++ b/tests/auto/qml/qqmllanguage/data/singleton/RegisteredCompositeSingletonType.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
pragma Singleton
diff --git a/tests/auto/qml/qqmllanguage/data/singleton/js/jspragma.js b/tests/auto/qml/qqmllanguage/data/singleton/js/jspragma.js
index 6e28624bb0..50ed2b0e66 100644
--- a/tests/auto/qml/qqmllanguage/data/singleton/js/jspragma.js
+++ b/tests/auto/qml/qqmllanguage/data/singleton/js/jspragma.js
@@ -1,5 +1,5 @@
// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
.pragma library
diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest17.qml b/tests/auto/qml/qqmllanguage/data/singletonTest17.qml
index 4a987e31c0..7c7bffa4ac 100644
--- a/tests/auto/qml/qqmllanguage/data/singletonTest17.qml
+++ b/tests/auto/qml/qqmllanguage/data/singletonTest17.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import org.qtproject.Test 1.0
diff --git a/tests/auto/qml/qqmllanguage/data/typedObjectList.qml b/tests/auto/qml/qqmllanguage/data/typedObjectList.qml
new file mode 100644
index 0000000000..7e6f6e8dd9
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/typedObjectList.qml
@@ -0,0 +1,10 @@
+import QtQml
+
+QtObject {
+ property var b;
+ property Component c: QtObject {}
+
+ function returnList(a: Component) : list<Component> { return [a] }
+
+ Component.onCompleted: b = { b: returnList(c) }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/unregisteredValueTypeConversion.qml b/tests/auto/qml/qqmllanguage/data/unregisteredValueTypeConversion.qml
new file mode 100644
index 0000000000..70484d3f0e
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/unregisteredValueTypeConversion.qml
@@ -0,0 +1,10 @@
+import QtQml
+import Test
+
+UnregisteredValueTypeHandler {
+ Component.onCompleted: {
+ consume(produce())
+ consume(produceDerived())
+ consume(produceGadgeted())
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/variantObjectList.qml b/tests/auto/qml/qqmllanguage/data/variantObjectList.qml
new file mode 100644
index 0000000000..9ec7d4f90f
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/variantObjectList.qml
@@ -0,0 +1,17 @@
+import QtQml
+import People
+
+QtObject {
+ id: root
+
+ property QtObject b: QtObject { id: g1; objectName: "Leo Hodges" }
+ property QtObject c: QtObject { id: g2; objectName: "Jack Smith" }
+ property QtObject d: QtObject { id: g3; objectName: "Anne Brown" }
+
+ property Component pc: Component {
+ id: partyComp
+ BirthdayParty {}
+ }
+
+ property BirthdayParty q: partyComp.createObject(root, { guests: [g1, g2, g3] })
+}
diff --git a/tests/auto/qml/qqmllanguage/testhelper/CMakeLists.txt b/tests/auto/qml/qqmllanguage/testhelper/CMakeLists.txt
new file mode 100644
index 0000000000..6a58889335
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/testhelper/CMakeLists.txt
@@ -0,0 +1,13 @@
+qt_policy(SET QTP0001 NEW)
+qt_add_library(tst_qqmllanguage_qmlmodule STATIC)
+qt_autogen_tools_initial_setup(tst_qqmllanguage_qmlmodule)
+qt_add_qml_module(tst_qqmllanguage_qmlmodule
+ URI testhelper
+ VERSION 1.0
+ SOURCES
+ "declarativelyregistered.h"
+ "declarativelyregistered.cpp"
+)
+
+qt_autogen_tools_initial_setup(tst_qqmllanguage_qmlmoduleplugin)
+target_link_libraries(tst_qqmllanguage PRIVATE tst_qqmllanguage_qmlmoduleplugin)
diff --git a/tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.cpp b/tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.cpp
new file mode 100644
index 0000000000..24fcd83d42
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.cpp
@@ -0,0 +1,7 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+#include "declarativelyregistered.h"
+
+PurelyDeclarativeSingleton::PurelyDeclarativeSingleton() = default;
+
+#include "moc_declarativelyregistered.cpp"
diff --git a/tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.h b/tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.h
new file mode 100644
index 0000000000..4845cc68b9
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.h
@@ -0,0 +1,20 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef DECLARATIVELYREGISTERED_LANGUAGE_H
+#define DECLARATIVELYREGISTERED_LANGUAGE_H
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqmlregistration.h>
+
+class PurelyDeclarativeSingleton : public QObject
+{
+ Q_OBJECT
+ QML_SINGLETON
+ QML_ELEMENT
+public:
+ PurelyDeclarativeSingleton();
+};
+
+
+#endif
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index f571429b07..526cca4b5b 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include "testtypes.h"
#include <private/qv4qmlcontext_p.h>
@@ -55,6 +56,8 @@ void registerTypes()
qmlRegisterTypeNotAvailable("Test",1,0,"UnavailableType", "UnavailableType is unavailable for testing");
+ qmlRegisterTypesAndRevisions<DerivedFromUnexposedBase>("Test", 1);
+
qmlRegisterType<MyQmlObject>("Test.Version",1,0,"MyQmlObject");
qmlRegisterType<MyTypeObject>("Test.Version",1,0,"MyTypeObject");
qmlRegisterType<MyTypeObject>("Test.Version",2,0,"MyTypeObject");
@@ -92,6 +95,8 @@ void registerTypes()
qmlRegisterType<MyArrayBufferTestClass>("Test", 1, 0, "MyArrayBufferTestClass");
+ qmlRegisterTypesAndRevisions<EnumPropsManyUnderlyingTypes>("Test", 1);
+
qmlRegisterType<LazyDeferredSubObject>("Test", 1, 0, "LazyDeferredSubObject");
qmlRegisterType<DeferredProperties>("Test", 1, 0, "DeferredProperties");
qmlRegisterType<ImmediateProperties>("Test", 1, 0, "ImmediateProperties");
@@ -148,6 +153,35 @@ void registerTypes()
qmlRegisterTypesAndRevisions<BaseValueType>("ValueTypes", 1);
qmlRegisterTypesAndRevisions<DerivedValueType>("ValueTypes", 1);
+ qmlRegisterTypesAndRevisions<GetterObject>("Test", 1);
+
+ qmlRegisterNamespaceAndRevisions(&TypedEnums::staticMetaObject, "TypedEnums", 1);
+ qmlRegisterTypesAndRevisions<ObjectWithEnums>("TypedEnums", 1);
+ qmlRegisterTypesAndRevisions<GadgetWithEnums>("TypedEnums", 1);
+
+ QMetaType::registerConverter<UnregisteredValueDerivedType, UnregisteredValueBaseType>();
+ qmlRegisterTypesAndRevisions<UnregisteredValueTypeHandler>("Test", 1);
+
+ qmlRegisterTypesAndRevisions<Greeter>("QmlOtherThis", 1);
+ qmlRegisterTypesAndRevisions<BirthdayParty>("People", 1);
+ qmlRegisterTypesAndRevisions<AttachedInCtor>("Test", 1);
+
+ qmlRegisterTypesAndRevisions<ByteArrayReceiver>("Test", 1);
+
+ qmlRegisterTypesAndRevisions<Counter>("Test", 1);
+
+ qmlRegisterTypesAndRevisions<Singleton>("EnumScopeTest", 1);
+ qmlRegisterTypesAndRevisions<NonSingleton>("EnumScopeTest", 1);
+ qmlRegisterTypesAndRevisions<EnumProviderSingletonQml>("EnumScopeTest", 1);
+
+ qmlRegisterTypesAndRevisions<TypeWithQJsonArrayProperty>("TypeWithQJsonArrayProperty", 1);
+ qmlRegisterTypesAndRevisions<
+ InvokableSingleton,
+ InvokableExtended,
+ InvokableUncreatable,
+ InvokableValueType
+ >("Test", 1);
+ qmlRegisterTypesAndRevisions<NestedVectors>("Test", 1);
}
QVariant myCustomVariantTypeConverter(const QString &data)
@@ -170,7 +204,7 @@ void CustomBinding::componentComplete()
{
Q_ASSERT(m_target);
- foreach (const QV4::CompiledData::Binding *binding, bindings) {
+ for (const QV4::CompiledData::Binding *binding : std::as_const(bindings)) {
QString name = compilationUnit->stringAt(binding->propertyNameIndex);
int bindingId = binding->value.compiledScriptIndex;
@@ -248,3 +282,19 @@ UncreatableSingleton *UncreatableSingleton::instance()
static UncreatableSingleton instance;
return &instance;
}
+
+QT_BEGIN_NAMESPACE
+const QMetaObject *QtPrivate::MetaObjectForType<FakeDynamicObject *, void>::metaObjectFunction(const QMetaTypeInterface *)
+{
+ static auto ptr = []{
+ QMetaObjectBuilder builder(&FakeDynamicObject::staticMetaObject);
+ builder.setFlags(DynamicMetaObject);
+ auto mo = builder.toMetaObject();
+ QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, [mo]() {
+ delete mo;
+ });
+ return mo;
+ }();
+ return ptr;
+}
+QT_END_NAMESPACE
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index 0777ed103d..ce6abf3504 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -1,11 +1,12 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPES_H
#define TESTTYPES_H
#include <QtCore/qobject.h>
#include <QtCore/qrect.h>
#include <QtCore/qdatetime.h>
+#include <QtCore/qjsonarray.h>
#include <QtGui/qtransform.h>
#include <QtGui/qcolor.h>
#include <QtGui/qvector2d.h>
@@ -18,6 +19,8 @@
#include <QtQml/qqmlpropertyvaluesource.h>
#include <QtQml/qqmlscriptstring.h>
#include <QtQml/qqmlproperty.h>
+
+#include <private/qqmlcomponentattached_p.h>
#include <private/qqmlcustomparser_p.h>
QVariant myCustomVariantTypeConverter(const QString &data);
@@ -42,6 +45,77 @@ struct MyCustomVariantType
};
Q_DECLARE_METATYPE(MyCustomVariantType);
+
+class Group : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int value MEMBER value)
+
+public:
+ Group(QObject *parent = nullptr) : QObject(parent) {}
+ int value = 0;
+};
+
+
+struct GroupGadget
+{
+ Q_GADGET
+
+ Q_PROPERTY(int value MEMBER value)
+
+public:
+ friend bool operator==(GroupGadget g1, GroupGadget g2) { return g1.value == g2.value; }
+ friend bool operator!=(GroupGadget g1, GroupGadget g2) { return !(g1 == g2); }
+ int value = 0;
+};
+
+struct FakeDynamicObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString value MEMBER value)
+
+public:
+ FakeDynamicObject() {}
+ QString value;
+};
+
+QT_BEGIN_NAMESPACE
+namespace QtPrivate {
+// don't do this at home – we override the meta-object which QMetaType collects for
+// FakeDynamicObject* properties
+template<>
+struct MetaObjectForType<FakeDynamicObject *, void>
+{
+ static const QMetaObject *metaObjectFunction(const QMetaTypeInterface *);
+};
+}
+QT_END_NAMESPACE
+
+class UnexposedBase : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(Group *group MEMBER group)
+ Q_PROPERTY(GroupGadget groupGadget MEMBER groupGadget)
+ Q_PROPERTY(FakeDynamicObject *dynamic MEMBER dynamic)
+public:
+ UnexposedBase(QObject *parent = nullptr) : QObject(parent)
+ {
+ group = new Group(this);
+ }
+ Group *group;
+ GroupGadget groupGadget;
+ FakeDynamicObject *dynamic = nullptr;
+};
+
+class DerivedFromUnexposedBase : public UnexposedBase
+{
+ Q_OBJECT
+ QML_ELEMENT
+};
+
+
class MyAttachedObject : public QObject
{
Q_OBJECT
@@ -1292,6 +1366,40 @@ public:
}
};
+class EnumPropsManyUnderlyingTypes : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ enum si8 : qint8 { ResolvedValue = 1};
+ enum ui8 : quint8 {};
+ enum si16 : qint16 {};
+ enum ui16 : quint16 {};
+ enum ui64 : qint64 {};
+ enum si64 : quint64 {};
+ Q_ENUM(si8)
+ Q_ENUM(ui8)
+ Q_ENUM(si16)
+ Q_ENUM(ui16)
+ Q_ENUM(si64)
+ Q_ENUM(ui64)
+
+
+ Q_PROPERTY(si8 si8prop MEMBER si8prop)
+ Q_PROPERTY(ui8 ui8prop MEMBER ui8prop)
+ Q_PROPERTY(si16 si16prop MEMBER si16prop)
+ Q_PROPERTY(ui16 ui16prop MEMBER ui16prop)
+ Q_PROPERTY(si64 si64prop MEMBER si64prop)
+ Q_PROPERTY(ui64 ui64prop MEMBER ui64prop)
+
+ si8 si8prop = si8(0);
+ ui8 ui8prop = ui8(0);
+ si16 si16prop = si16(0);
+ ui16 ui16prop = ui16(0);
+ si64 si64prop = si64(0);
+ ui64 ui64prop = ui64(0);
+};
+
Q_DECLARE_METATYPE(MyEnum2Class::EnumB)
Q_DECLARE_METATYPE(MyEnum1Class::EnumA)
Q_DECLARE_METATYPE(Qt::TextFormat)
@@ -1547,6 +1655,7 @@ class BareSingleton : public QObject
Q_OBJECT
QML_SINGLETON
QML_ELEMENT
+ QML_ADDED_IN_VERSION(1, 0)
public:
BareSingleton(QObject *parent = nullptr) : QObject(parent)
@@ -1560,6 +1669,7 @@ class UncreatableSingleton : public QObject
Q_OBJECT
QML_SINGLETON
QML_ELEMENT
+ QML_ADDED_IN_VERSION(1, 0)
public:
static UncreatableSingleton *instance();
@@ -2386,6 +2496,32 @@ public:
}
};
+
+struct ForeignNamespace
+{
+ Q_GADGET
+public:
+ enum Abc { A, B, C, D };
+ Q_ENUM(Abc)
+};
+
+class ForeignNamespaceForeign
+{
+ Q_GADGET
+ QML_ELEMENT
+ QML_FOREIGN_NAMESPACE(ForeignNamespace)
+};
+
+class LeakingForeignNamespaceForeign : public QObject, public ForeignNamespaceForeign
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+public:
+ enum AnotherAbc { D, C, B, A };
+ Q_ENUM(AnotherAbc)
+};
+
struct ValueTypeWithLength
{
Q_GADGET
@@ -2405,4 +2541,506 @@ private:
int m_length = 19;
};
+struct ValueTypeWithString
+{
+ Q_GADGET
+ QML_VALUE_TYPE(withString)
+ QML_CONSTRUCTIBLE_VALUE
+
+public:
+ Q_INVOKABLE ValueTypeWithString(const QString &v = QString()) : m_string(v) {}
+ QString toString() const { return m_string; }
+
+private:
+ QString m_string;
+};
+
+class GetterObject : public QObject {
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+public:
+ explicit GetterObject(QObject *parent = nullptr) : QObject{parent} {}
+
+ // always returns a 0 as uint64_t
+ Q_INVOKABLE uint64_t getFalse() const { return 0; }
+ Q_INVOKABLE uint64_t getTrue() const { return 1; }
+
+ Q_INVOKABLE quint64 getQFalse() const { return 0; }
+ Q_INVOKABLE quint64 getQTrue() const { return 1; }
+};
+
+class EnumProviderSingleton : public QObject {
+ Q_OBJECT
+
+public:
+ enum class Expected {
+ Value = 42
+ };
+ Q_ENUM(Expected)
+
+ EnumProviderSingleton(QObject* parent = nullptr) : QObject(parent) {}
+};
+
+class EnumProviderSingletonQml {
+ Q_GADGET
+ QML_FOREIGN(EnumProviderSingleton)
+ QML_NAMED_ELEMENT(EnumProviderSingleton)
+ QML_SINGLETON
+
+public:
+ static EnumProviderSingleton* create(QQmlEngine*, QJSEngine*) {
+ return new EnumProviderSingleton();
+ }
+
+private:
+ EnumProviderSingletonQml() = default;
+};
+
+
+
+namespace TypedEnums {
+Q_NAMESPACE
+QML_ELEMENT
+
+enum E8S : qint8 {
+ E8SA = std::numeric_limits<qint8>::min(),
+ E8SB = -5,
+ E8SC = -1,
+ E8SD = 0,
+ E8SE = 1,
+ E8SF = 5,
+ E8SG = std::numeric_limits<qint8>::max(),
+};
+Q_ENUM_NS(E8S);
+
+enum E8U : quint8 {
+ E8UA = 0,
+ E8UB = 1,
+ E8UC = 5,
+ E8UD = 1 << 7,
+ E8UE = std::numeric_limits<quint8>::max(),
+};
+Q_ENUM_NS(E8U);
+
+enum E16S : qint16 {
+ E16SA = std::numeric_limits<qint16>::min(),
+ E16SB = -5,
+ E16SC = -1,
+ E16SD = 0,
+ E16SE = 1,
+ E16SF = 5,
+ E16SG = std::numeric_limits<qint16>::max(),
+};
+Q_ENUM_NS(E16S);
+
+enum E16U : quint16 {
+ E16UA = 0,
+ E16UB = 1,
+ E16UC = 5,
+ E16UD = 1 << 15,
+ E16UE = std::numeric_limits<quint16>::max(),
+};
+Q_ENUM_NS(E16U);
+
+enum E32S : qint32 {
+ E32SA = std::numeric_limits<qint32>::min(),
+ E32SB = -5,
+ E32SC = -1,
+ E32SD = 0,
+ E32SE = 1,
+ E32SF = 5,
+ E32SG = std::numeric_limits<qint32>::max(),
+};
+Q_ENUM_NS(E32S);
+
+enum E32U : quint32 {
+ E32UA = 0,
+ E32UB = 1,
+ E32UC = 5,
+ E32UD = 1u << 31,
+ E32UE = std::numeric_limits<quint32>::max(),
+};
+Q_ENUM_NS(E32U);
+
+enum E64S : qint64 {
+ E64SA = std::numeric_limits<qint64>::min(),
+ E64SB = -5,
+ E64SC = -1,
+ E64SD = 0,
+ E64SE = 1,
+ E64SF = 5,
+ E64SG = std::numeric_limits<qint64>::max(),
+};
+Q_ENUM_NS(E64S);
+
+enum E64U : quint64 {
+ E64UA = 0,
+ E64UB = 1,
+ E64UC = 5,
+ E64UD = 1ull << 63,
+ E64UE = std::numeric_limits<quint64>::max(),
+};
+Q_ENUM_NS(E64U);
+}
+
+class GadgetWithEnums
+{
+ Q_GADGET
+ QML_VALUE_TYPE(gadgetWithEnums)
+ Q_PROPERTY(TypedEnums::E8S e8s MEMBER m_e8s);
+ Q_PROPERTY(TypedEnums::E8U e8u MEMBER m_e8u);
+ Q_PROPERTY(TypedEnums::E16S e16s MEMBER m_e16s);
+ Q_PROPERTY(TypedEnums::E16U e16u MEMBER m_e16u);
+ Q_PROPERTY(TypedEnums::E32S e32s MEMBER m_e32s);
+ Q_PROPERTY(TypedEnums::E32U e32u MEMBER m_e32u);
+ Q_PROPERTY(TypedEnums::E64S e64s MEMBER m_e64s);
+ Q_PROPERTY(TypedEnums::E64U e64u MEMBER m_e64u);
+public:
+ TypedEnums::E8S m_e8s = {};
+ TypedEnums::E8U m_e8u = {};
+ TypedEnums::E16S m_e16s = {};
+ TypedEnums::E16U m_e16u = {};
+ TypedEnums::E32S m_e32s = {};
+ TypedEnums::E32U m_e32u = {};
+ TypedEnums::E64S m_e64s = {};
+ TypedEnums::E64U m_e64u = {};
+private:
+ friend bool operator==(const GadgetWithEnums &a, const GadgetWithEnums &b)
+ {
+ return a.m_e8s == b.m_e8s && a.m_e8u == b.m_e8u && a.m_e16s == b.m_e16s
+ && a.m_e16u == b.m_e16u && a.m_e32s == b.m_e32s && a.m_e32u == b.m_e32u
+ && a.m_e64s == b.m_e64s && a.m_e64u == b.m_e64u;
+ }
+ friend bool operator!=(const GadgetWithEnums &a, const GadgetWithEnums &b)
+ {
+ return !(a == b);
+ }
+};
+
+class ObjectWithEnums : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(TypedEnums::E8S e8s MEMBER m_e8s NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E8U e8u MEMBER m_e8u NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E16S e16s MEMBER m_e16s NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E16U e16u MEMBER m_e16u NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E32S e32s MEMBER m_e32s NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E32U e32u MEMBER m_e32u NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E64S e64s MEMBER m_e64s NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E64U e64u MEMBER m_e64u NOTIFY changed);
+ Q_PROPERTY(GadgetWithEnums g MEMBER m_g NOTIFY changed);
+public:
+ ObjectWithEnums(QObject *parent = nullptr) : QObject(parent) {}
+ TypedEnums::E8S m_e8s = {};
+ TypedEnums::E8U m_e8u = {};
+ TypedEnums::E16S m_e16s = {};
+ TypedEnums::E16U m_e16u = {};
+ TypedEnums::E32S m_e32s = {};
+ TypedEnums::E32U m_e32u = {};
+ TypedEnums::E64S m_e64s = {};
+ TypedEnums::E64U m_e64u = {};
+ GadgetWithEnums m_g;
+Q_SIGNALS:
+ void changed();
+};
+
+struct UnregisteredValueBaseType
+{
+ int foo = 12;
+};
+
+struct UnregisteredValueDerivedType: public UnregisteredValueBaseType
+{
+ int bar = 13;
+};
+
+struct GadgetedValueBaseType
+{
+ Q_GADGET
+ int foo = 12;
+};
+
+struct GadgetedValueDerivedType: public GadgetedValueBaseType
+{
+ Q_GADGET
+ int bar = 13;
+};
+
+class UnregisteredValueTypeHandler: public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ int consumed = 0;
+ int gadgeted = 0;
+
+public slots:
+ UnregisteredValueBaseType produce() { return UnregisteredValueBaseType(); }
+ UnregisteredValueDerivedType produceDerived() { return UnregisteredValueDerivedType(); }
+ void consume(UnregisteredValueBaseType) { ++consumed; }
+
+ GadgetedValueDerivedType produceGadgeted() { return GadgetedValueDerivedType(); }
+ void consume(GadgetedValueBaseType) { ++gadgeted; }
+};
+
+class Greeter : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+public:
+ Greeter(QObject *parent = nullptr) : QObject(parent) {}
+
+ Q_INVOKABLE void greet()
+ {
+ qDebug().noquote() << objectName() << "says hello";
+ }
+
+ Q_INVOKABLE void sum(int a, int b)
+ {
+ qDebug().noquote() << objectName() << QString("says %1 + %2 = %3").arg(a).arg(b).arg(a + b);
+ }
+};
+
+class Attachment : public QObject {
+ Q_OBJECT
+public:
+ Attachment(QObject *parent = nullptr) : QObject(parent) {}
+};
+
+class AttachedInCtor : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_ATTACHED(Attachment)
+
+public:
+ AttachedInCtor(QObject *parent = nullptr)
+ : QObject(parent)
+ {
+ attached = qmlAttachedPropertiesObject<AttachedInCtor>(this, true);
+ }
+
+ static Attachment *qmlAttachedProperties(QObject *object) {
+ return new Attachment(object);
+ }
+
+ QObject *attached = nullptr;
+};
+
+class BirthdayParty : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<QObject> guests READ guests)
+ Q_CLASSINFO("DefaultProperty", "guests")
+ QML_ELEMENT
+
+public:
+ using QObject::QObject;
+ QQmlListProperty<QObject> guests() { return {this, &m_guests}; }
+ qsizetype guestCount() const { return m_guests.count(); }
+ QObject *guest(qsizetype i) const { return m_guests.at(i); }
+
+private:
+ QList<QObject *> m_guests;
+};
+
+class ByteArrayReceiver : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+public:
+ QList<QByteArray> byteArrays;
+
+ Q_INVOKABLE void byteArrayTest(const QByteArray &ba)
+ {
+ byteArrays.push_back(ba);
+ }
+};
+
+class CounterAttachedBaseType: public QObject
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+ Q_PROPERTY (int value READ value NOTIFY valueChanged)
+
+public:
+ CounterAttachedBaseType(QObject *parent = nullptr) : QObject(parent) {}
+
+ int value() { return m_value; }
+ Q_SIGNAL void valueChanged();
+
+protected:
+ int m_value = 98;
+};
+
+
+class CounterAttachedType: public CounterAttachedBaseType
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+
+public:
+ CounterAttachedType(QObject *parent = nullptr) : CounterAttachedBaseType(parent) {}
+
+ Q_INVOKABLE void increase() {
+ ++m_value;
+ Q_EMIT valueChanged();
+ }
+};
+
+class Counter : public QObject
+{
+ Q_OBJECT
+ QML_ATTACHED(CounterAttachedBaseType)
+ QML_ELEMENT
+
+public:
+ static CounterAttachedBaseType *qmlAttachedProperties(QObject *o)
+ {
+ return new CounterAttachedType(o);
+ }
+};
+
+
+class Singleton: public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(EnumType enumProperty READ enumProperty CONSTANT)
+ Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
+ QML_ELEMENT
+ QML_SINGLETON
+public:
+ explicit Singleton(QObject* parent = nullptr) : QObject(parent) {}
+ enum class EnumType {
+ EnumValue1,
+ EnumValue2
+ };
+ Q_ENUM(EnumType);
+ EnumType enumProperty() const {
+ return EnumType::EnumValue2;
+ }
+};
+
+class NonSingleton: public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(EnumType enumProperty READ enumProperty CONSTANT)
+ Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
+ QML_ELEMENT
+public:
+ explicit NonSingleton(QObject* parent = nullptr) : QObject(parent) {}
+ enum class EnumType {
+ EnumValue1,
+ EnumValue2
+ };
+ Q_ENUM(EnumType);
+ EnumType enumProperty() const {
+ return EnumType::EnumValue2;
+ }
+};
+
+class TypeWithQJsonArrayProperty : public QObject {
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(QJsonArray jsonArray READ jsonArray WRITE setJsonArray NOTIFY jsonArrayChanged)
+
+public:
+ TypeWithQJsonArrayProperty(QObject *parent = nullptr) : QObject(parent) {}
+
+ const QJsonArray& jsonArray() { return m_jsonArray; }
+ void setJsonArray(const QJsonArray& a) { m_jsonArray = a; }
+
+signals:
+ void jsonArrayChanged();
+
+private:
+ QJsonArray m_jsonArray;
+};
+
+class InvokableSingleton : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+public:
+ InvokableSingleton() = default;
+ Q_INVOKABLE InvokableSingleton(int a, QObject *parent) : QObject(parent), m_a(a) {}
+
+ int m_a = 0;
+};
+
+class InvokableExtension : public QObject
+{
+ Q_OBJECT
+public:
+ Q_INVOKABLE InvokableExtension(QObject *parent = nullptr) : QObject(parent) {}
+};
+
+class InvokableExtended : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_EXTENDED(InvokableExtension)
+
+public:
+ Q_INVOKABLE InvokableExtended() = default;
+};
+
+class InvokableUncreatable : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_UNCREATABLE("no")
+
+public:
+ Q_INVOKABLE InvokableUncreatable() = default;
+};
+
+class InvokableValueType
+{
+ Q_GADGET
+ QML_VALUE_TYPE(vv)
+public:
+ Q_INVOKABLE InvokableValueType() = default;
+ Q_INVOKABLE InvokableValueType(const QString &s) : m_s(s) {}
+ QString m_s;
+};
+
+class NestedVectors : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ NestedVectors(QObject *parent = nullptr) : QObject(parent)
+ {
+ std::vector<int> data;
+ data.push_back(1);
+ data.push_back(2);
+ data.push_back(3);
+ m_list.push_back(data);
+ data.clear();
+ data.push_back(4);
+ data.push_back(5);
+ m_list.push_back(data);
+ }
+
+ Q_INVOKABLE std::vector<std::vector<int>> getList()
+ {
+ return m_list;
+ }
+
+ Q_INVOKABLE void setList(std::vector<std::vector<int>> list)
+ {
+ m_list = list;
+ }
+
+private:
+ std::vector<std::vector<int>> m_list;
+};
+
#endif // TESTTYPES_H
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index fee65fcb17..2212a40eee 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -37,7 +38,7 @@
#include <deque>
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
#include <unistd.h>
#endif
@@ -47,7 +48,7 @@ DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES)
static inline bool isCaseSensitiveFileSystem(const QString &path) {
Q_UNUSED(path);
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
return pathconf(path.toLatin1().constData(), _PC_CASE_SENSITIVE);
#elif defined(Q_OS_WIN)
return false;
@@ -248,6 +249,8 @@ private slots:
void compositeSingletonSelectors();
void compositeSingletonRegistered();
void compositeSingletonCircular();
+ void compositeSingletonRequiredProperties();
+ void compositeSingletonRequiredProperties_data();
void singletonsHaveContextAndEngine();
@@ -316,6 +319,7 @@ private slots:
void inlineComponentFoundBeforeOtherImports();
void inlineComponentDuplicateNameError();
void inlineComponentWithAliasInstantiatedWithNewProperties();
+ void inlineComponentWithImplicitComponent();
void selfReference();
void selfReferencingSingleton();
@@ -358,6 +362,8 @@ private slots:
void hangOnWarning();
+ void groupPropertyFromNonExposedBaseClass();
+
void listEnumConversion();
void deepInlineComponentScriptBinding();
@@ -402,10 +408,62 @@ private slots:
void importPrecedence();
void nullIsNull();
void multiRequired();
+ void isNullOrUndefined();
void objectAndGadgetMethodCallsRejectThisObject();
void objectAndGadgetMethodCallsAcceptThisObject();
+ void asValueType();
+ void asValueTypeGood();
+
+ void longConversion();
+
+ void enumPropsManyUnderylingTypes();
+
+ void typedEnums_data();
+ void typedEnums();
+
+ void objectMethodClone();
+ void unregisteredValueTypeConversion();
+ void retainThis();
+
+ void variantObjectList();
+ void jitExceptions();
+
+ void attachedInCtor();
+ void byteArrayConversion();
+ void propertySignalNames_data();
+ void propertySignalNames();
+ void signalNames_data();
+ void signalNames();
+
+ void callMethodOfAttachedDerived();
+
+ void multiVersionSingletons();
+ void typeAnnotationCycle();
+ void corpseInQmlList();
+ void objectInQmlListAndGc();
+ void asCastToInlineComponent();
+ void deepAliasOnICOrReadonly();
+
+ void optionalChainCallOnNullProperty();
+
+ void ambiguousComponents();
+
+ void writeNumberToEnumAlias();
+ void badInlineComponentAnnotation();
+ void manuallyCallSignalHandler();
+ void overrideDefaultProperty();
+ void enumScopes();
+
+ void typedObjectList();
+ void invokableCtors();
+
+ void jsonArrayPropertyBehavesLikeAnArray();
+
+ void nestedVectors();
+ void optimizedSequenceShift();
+
private:
QQmlEngine engine;
QStringList defaultImportPathList;
@@ -492,11 +550,11 @@ void tst_qqmllanguage::insertedSemicolon()
QQmlComponent component(&engine, testFileUrl(file));
- QScopedPointer<QObject> object;
+ std::unique_ptr<QObject> object;
if(create) {
object.reset(component.create());
- QVERIFY(object.isNull());
+ QVERIFY(object.get());
}
VERIFY_ERRORS(errorFile.toLatin1().constData());
@@ -1381,13 +1439,13 @@ void tst_qqmllanguage::rootItemIsComponent()
QtWarningMsg,
QRegularExpression(
".*/rootItemIsComponent\\.qml:3:1: Using a Component as the root of "
- "a qmldocument is deprecated: types defined in qml documents are automatically "
- "wrapped into Components when needed\\."));
+ "a QML document is deprecated: types defined in qml documents are "
+ "automatically wrapped into Components when needed\\."));
QTest::ignoreMessage(
QtWarningMsg,
QRegularExpression(
".*/EvilComponentType\\.qml:3:1: Using a Component as the root of a "
- "qmldocument is deprecated: types defined in qml documents are automatically "
+ "QML document is deprecated: types defined in qml documents are automatically "
"wrapped into Components when needed\\."));
QTest::ignoreMessage(
QtWarningMsg,
@@ -1707,8 +1765,8 @@ void tst_qqmllanguage::propertyValueSource()
QVERIFY(object != nullptr);
QList<QObject *> valueSources;
- QObjectList allChildren = object->findChildren<QObject*>();
- foreach (QObject *child, allChildren) {
+ const QObjectList allChildren = object->findChildren<QObject*>();
+ for (QObject *child : allChildren) {
if (qobject_cast<QQmlPropertyValueSource *>(child))
valueSources.append(child);
}
@@ -1728,8 +1786,8 @@ void tst_qqmllanguage::propertyValueSource()
QVERIFY(object != nullptr);
QList<QObject *> valueSources;
- QObjectList allChildren = object->findChildren<QObject*>();
- foreach (QObject *child, allChildren) {
+ const QObjectList allChildren = object->findChildren<QObject*>();
+ for (QObject *child : allChildren) {
if (qobject_cast<QQmlPropertyValueSource *>(child))
valueSources.append(child);
}
@@ -2039,7 +2097,7 @@ void tst_qqmllanguage::aliasProperties()
MyQmlObject *o = qvariant_cast<MyQmlObject*>(v);
QCOMPARE(o->value(), 10);
- delete o;
+ delete o; //intentional delete
v = object->property("otherAlias");
QCOMPARE(v.typeId(), qMetaTypeId<MyQmlObject *>());
@@ -2074,7 +2132,7 @@ void tst_qqmllanguage::aliasProperties()
QObject *alias = qvariant_cast<QObject *>(object->property("aliasedObject"));
QCOMPARE(alias, object2);
- delete object1;
+ delete object1; //intentional delete
QObject *alias2 = object.data(); // "Random" start value
int status = -1;
@@ -2583,7 +2641,7 @@ void tst_qqmllanguage::scriptStringWithoutSourceCode()
Q_ASSERT(td);
QVERIFY(!td->backupSourceCode().isValid());
- QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit = td->compilationUnit();
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = td->compilationUnit();
readOnlyQmlUnit.reset(compilationUnit->unitData());
Q_ASSERT(readOnlyQmlUnit);
QV4::CompiledData::Unit *qmlUnit = reinterpret_cast<QV4::CompiledData::Unit *>(malloc(readOnlyQmlUnit->unitSize));
@@ -2863,7 +2921,8 @@ void tst_qqmllanguage::testType(const QString& qml, const QString& type, const Q
if (type.isEmpty()) {
QVERIFY(component.isError());
QString actualerror;
- foreach (const QQmlError e, component.errors()) {
+ const auto errors = component.errors();
+ for (const QQmlError &e : errors) {
if (!actualerror.isEmpty())
actualerror.append("; ");
actualerror.append(e.description());
@@ -3861,6 +3920,7 @@ void tst_qqmllanguage::initTestCase()
qmlRegisterType(testFileUrl("invalidRoot.1.qml"), "Test", 1, 0, "RegisteredCompositeType3");
qmlRegisterType(testFileUrl("CompositeTypeWithEnum.qml"), "Test", 1, 0, "RegisteredCompositeTypeWithEnum");
qmlRegisterType(testFileUrl("CompositeTypeWithAttachedProperty.qml"), "Test", 1, 0, "RegisteredCompositeTypeWithAttachedProperty");
+ qmlRegisterType(testFileUrl("CompositeTypeWithEnumSelfReference.qml"), "Test", 1, 0, "CompositeTypeWithEnumSelfReference");
// Registering the TestType class in other modules should have no adverse effects
qmlRegisterType<TestType>("org.qtproject.TestPre", 1, 0, "Test");
@@ -3889,6 +3949,7 @@ void tst_qqmllanguage::initTestCase()
// Register a Composite Singleton.
qmlRegisterSingletonType(testFileUrl("singleton/RegisteredCompositeSingletonType.qml"), "org.qtproject.Test", 1, 0, "RegisteredSingleton");
+ qmlRegisterType(testFileUrl("Comps/OverlayDrawer.qml"), "Comps", 2, 0, "OverlayDrawer");
}
void tst_qqmllanguage::aliasPropertyChangeSignals()
@@ -4036,6 +4097,17 @@ void tst_qqmllanguage::registeredCompositeTypeWithEnum()
QCOMPARE(o->property("enumValue0").toInt(), static_cast<int>(MyCompositeBaseType::EnumValue0));
QCOMPARE(o->property("enumValue42").toInt(), static_cast<int>(MyCompositeBaseType::EnumValue42));
QCOMPARE(o->property("enumValue15").toInt(), static_cast<int>(MyCompositeBaseType::ScopedCompositeEnum::EnumValue15));
+
+ {
+ QQmlComponent component(&engine);
+ component.setData("import Test\nCompositeTypeWithEnumSelfReference {}", QUrl());
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(o != nullptr);
+
+ QCOMPARE(o->property("e").toInt(), 1);
+ QCOMPARE(o->property("f").toInt(), 2);
+ }
}
// QTBUG-43581
@@ -4212,7 +4284,8 @@ void tst_qqmllanguage::lowercaseEnumRuntime()
QQmlComponent component(&engine, testFileUrl(file));
VERIFY_ERRORS(0);
- delete component.create();
+ std::unique_ptr<QObject> root { component.create() };
+ QVERIFY(root);
}
void tst_qqmllanguage::lowercaseEnumCompileTime_data()
@@ -4229,7 +4302,8 @@ void tst_qqmllanguage::lowercaseEnumCompileTime()
QQmlComponent component(&engine, testFileUrl(file));
VERIFY_ERRORS(0);
- delete component.create();
+ std::unique_ptr<QObject> root { component.create() };
+ QVERIFY(root);
}
void tst_qqmllanguage::scopedEnum()
@@ -4473,7 +4547,6 @@ void tst_qqmllanguage::groupAssignmentFailure()
{
auto ep = std::make_unique<QQmlEngine>();
QTest::failOnWarning("QQmlComponent: Component destroyed while completion pending");
- QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression(".*Invalid property assignment: url expected - Assigning null to incompatible properties in QML is deprecated. This will become a compile error in future versions of Qt..*"));
QQmlComponent component(ep.get(), testFileUrl("groupFailure.qml"));
QScopedPointer<QObject> o(component.create());
QVERIFY(!o);
@@ -4844,6 +4917,36 @@ void tst_qqmllanguage::compositeSingletonCircular()
QCOMPARE(o->property("value").toInt(), 2);
}
+void tst_qqmllanguage::compositeSingletonRequiredProperties()
+{
+ QFETCH(QString, warning);
+ QFETCH(QString, singletonName);
+ QQmlEngine engine;
+ engine.addImportPath(dataDirectory());
+ {
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, qPrintable(warning));
+ std::unique_ptr<QObject> singleton {engine.singletonInstance<QObject *>(
+ "SingletonWithRequiredProperties",
+ singletonName
+ )};
+ QVERIFY(!singleton);
+ }
+}
+
+void tst_qqmllanguage::compositeSingletonRequiredProperties_data()
+{
+ QTest::addColumn<QString>("warning");
+ QTest::addColumn<QString>("singletonName");
+
+ QString warning1 = testFileUrl("SingletonWithRequiredProperties/SingletonWithRequired1.qml").toString()
+ + ":5:5: Required property i was not initialized";
+ QString warning2 = testFileUrl("SingletonWithRequiredProperties/SingletonWithRequired2.qml").toString()
+ + ":6:9: Required property i was not initialized";
+
+ QTest::addRow("toplevelRequired") << warning1 << "SingletonWithRequired1";
+ QTest::addRow("subObjectRequired") << warning2 << "SingletonWithRequired2";
+}
+
void tst_qqmllanguage::singletonsHaveContextAndEngine()
{
QObject *qmlSingleton = nullptr;
@@ -5348,24 +5451,30 @@ void tst_qqmllanguage::namespacedPropertyTypes()
void tst_qqmllanguage::qmlTypeCanBeResolvedByName_data()
{
QTest::addColumn<QUrl>("componentUrl");
+ QTest::addColumn<QString>("name");
// Built-in C++ types
- QTest::newRow("C++ - Anonymous") << testFileUrl("quickTypeByName_anon.qml");
- QTest::newRow("C++ - Named") << testFileUrl("quickTypeByName_named.qml");
+ QTest::newRow("C++ - Anonymous") << testFileUrl("quickTypeByName_anon.qml")
+ << QStringLiteral("QtQuick/Item");
+ QTest::newRow("C++ - Named") << testFileUrl("quickTypeByName_named.qml")
+ << QStringLiteral("QtQuick/Item");
// Composite types with a qmldir
- QTest::newRow("QML - Anonymous - qmldir") << testFileUrl("compositeTypeByName_anon_qmldir.qml");
- QTest::newRow("QML - Named - qmldir") << testFileUrl("compositeTypeByName_named_qmldir.qml");
+ QTest::newRow("QML - Anonymous - qmldir") << testFileUrl("compositeTypeByName_anon_qmldir.qml")
+ << QStringLiteral("SimpleType");
+ QTest::newRow("QML - Named - qmldir") << testFileUrl("compositeTypeByName_named_qmldir.qml")
+ << QStringLiteral("SimpleType");
}
void tst_qqmllanguage::qmlTypeCanBeResolvedByName()
{
QFETCH(QUrl, componentUrl);
+ QFETCH(QString, name);
QQmlEngine engine;
QQmlComponent component(&engine, componentUrl);
VERIFY_ERRORS(0);
- QTest::ignoreMessage(QtMsgType::QtWarningMsg, "[object Object]"); // a bit crude, but it will do
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, qPrintable(name));
QScopedPointer<QObject> o(component.create());
QVERIFY(!o.isNull());
@@ -5654,6 +5763,9 @@ void tst_qqmllanguage::retrieveQmlTypeId()
QVERIFY(qmlTypeId("Test", 1, 0, "MyExtendedUncreateableBaseClass") >= 0);
QVERIFY(qmlTypeId("Test", 1, 0, "MyUncreateableBaseClass") >= 0);
QVERIFY(qmlTypeId("Test", 1, 0, "MyTypeObjectSingleton") >= 0);
+
+ // Must also work for declaratively registered types whose module wasn't imported so far
+ QVERIFY(qmlTypeId("testhelper", 1, 0, "PurelyDeclarativeSingleton") >= 0);
}
void tst_qqmllanguage::polymorphicFunctionLookup()
@@ -5749,7 +5861,7 @@ void tst_qqmllanguage::selfReference()
const QMetaObject *metaObject = o->metaObject();
QMetaProperty selfProperty = metaObject->property(metaObject->indexOfProperty("self"));
- QCOMPARE(selfProperty.metaType().id(), compilationUnit->typeIds.id.id());
+ QCOMPARE(selfProperty.metaType().id(), compilationUnit->metaType().id());
QByteArray typeName = selfProperty.typeName();
QVERIFY(typeName.endsWith('*'));
@@ -5758,7 +5870,7 @@ void tst_qqmllanguage::selfReference()
QMetaMethod selfFunction = metaObject->method(metaObject->indexOfMethod("returnSelf()"));
QVERIFY(selfFunction.isValid());
- QCOMPARE(selfFunction.returnType(), compilationUnit->typeIds.id.id());
+ QCOMPARE(selfFunction.returnType(), compilationUnit->metaType().id());
QMetaMethod selfSignal;
@@ -5772,7 +5884,7 @@ void tst_qqmllanguage::selfReference()
QVERIFY(selfSignal.isValid());
QCOMPARE(selfSignal.parameterCount(), 1);
- QCOMPARE(selfSignal.parameterType(0), compilationUnit->typeIds.id.id());
+ QCOMPARE(selfSignal.parameterType(0), compilationUnit->metaType().id());
}
void tst_qqmllanguage::selfReferencingSingleton()
@@ -5809,10 +5921,10 @@ void tst_qqmllanguage::listContainingDeletedObject()
QVERIFY(root);
auto cmp = root->property("a").value<QQmlComponent*>();
- auto o = cmp->create();
+ std::unique_ptr<QObject> o { cmp->create() };
- QMetaObject::invokeMethod(root.get(), "doAssign", Q_ARG(QVariant, QVariant::fromValue(o)));
- delete o;
+ QMetaObject::invokeMethod(root.get(), "doAssign", Q_ARG(QVariant, QVariant::fromValue(o.get())));
+ o.reset();
QMetaObject::invokeMethod(root.get(), "use");
}
@@ -6096,6 +6208,17 @@ void tst_qqmllanguage::inlineComponentWithAliasInstantiatedWithNewProperties()
QCOMPARE(root->property("result").toString(), "Bar");
}
+void tst_qqmllanguage::inlineComponentWithImplicitComponent()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("inlineComponentWithImplicitComponent.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(root);
+
+ QCOMPARE(root->objectName(), "green blue"_L1);
+}
+
struct QJSValueConvertible {
Q_GADGET
@@ -6392,23 +6515,15 @@ void tst_qqmllanguage::extendedSingleton()
void tst_qqmllanguage::qtbug_85932()
{
- QString warning1 = QLatin1String("%1:10:9: id is not unique").arg(testFileUrl("SingletonTest.qml").toString());
- QString warning2 = QLatin1String("%1:4: Error: Due to the preceding error(s), Singleton \"SingletonTest\" could not be loaded.").arg(testFileUrl("qtbug_85932.qml").toString());
-
- QTest::ignoreMessage(QtMsgType::QtWarningMsg, qPrintable(warning1));
- QTest::ignoreMessage(QtMsgType::QtWarningMsg, qPrintable(warning2));
-
QQmlEngine engine;
- QList<QQmlError> allWarnings;
- QObject::connect(&engine, &QQmlEngine::warnings, [&allWarnings](const QList<QQmlError> &warnings) {
- allWarnings.append(warnings);
- });
- QQmlComponent c(&engine, testFileUrl("qtbug_85932.qml"));
- QScopedPointer<QObject> obj(c.create());
- QTRY_COMPARE(allWarnings.size(), 2);
- QCOMPARE(allWarnings.at(0).toString(), warning1);
- QCOMPARE(allWarnings.at(1).toString(), warning2);
+ QQmlComponent c(&engine, testFileUrl("badSingleton/qtbug_85932.qml"));
+ QVERIFY(c.isError());
+
+ const QString error = c.errorString();
+ QVERIFY(error.contains(QLatin1String("Type SingletonTest unavailable")));
+ QVERIFY(error.contains(QLatin1String("%1:10 id is not unique")
+ .arg(testFileUrl("badSingleton/SingletonTest.qml").toString())));
}
void tst_qqmllanguage::multiExtension()
@@ -6758,15 +6873,22 @@ void tst_qqmllanguage::bareInlineComponent()
if (type.elementName() == QStringLiteral("Tab1")) {
QVERIFY(type.module().isEmpty());
tab1Found = true;
- const auto ics = type.priv()->objectIdToICType;
- QVERIFY(ics.size() > 0);
- for (const QQmlType &ic : ics)
- QVERIFY(ic.containingType() == type);
+
+ const QQmlType leftTab = QQmlMetaType::inlineComponentType(type, "LeftTab");
+ QUrl leftUrl = leftTab.sourceUrl();
+ leftUrl.setFragment(QString());
+ QCOMPARE(leftUrl, type.sourceUrl());
+
+ const QQmlType rightTab = QQmlMetaType::inlineComponentType(type, "RightTab");
+ QUrl rightUrl = rightTab.sourceUrl();
+ rightUrl.setFragment(QString());
+ QCOMPARE(rightUrl, type.sourceUrl());
}
}
QVERIFY(tab1Found);
}
+#if QT_CONFIG(qml_debug)
struct DummyDebugger : public QV4::Debugging::Debugger
{
bool pauseAtNextOpportunity() const final { return false; }
@@ -6775,6 +6897,9 @@ struct DummyDebugger : public QV4::Debugging::Debugger
void leavingFunction(const QV4::ReturnedValue &) final { }
void aboutToThrow() final { }
};
+#else
+using DummyDebugger = QV4::Debugging::Debugger; // it's already dummy
+#endif
void tst_qqmllanguage::hangOnWarning()
{
@@ -6792,6 +6917,25 @@ void tst_qqmllanguage::hangOnWarning()
QVERIFY(object != nullptr);
}
+void tst_qqmllanguage::groupPropertyFromNonExposedBaseClass()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("derivedFromUnexposedBase.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ auto root = qobject_cast<DerivedFromUnexposedBase *>(o.get());
+ QVERIFY(root);
+ QVERIFY(root->group);
+ QCOMPARE(root->group->value, 42);
+ QCOMPARE(root->groupGadget.value, 42);
+
+ c.loadUrl(testFileUrl("dynamicGroupPropertyRejected.qml"));
+ QVERIFY(c.isError());
+ QVERIFY2(c.errorString().contains("Unsupported grouped property access"), qPrintable(c.errorString()));
+}
+
void tst_qqmllanguage::listEnumConversion()
{
QQmlEngine e;
@@ -7424,6 +7568,33 @@ LeakingForeignerForeign {
QVERIFY(o->property("anotherAbc").isValid());
QVERIFY(!o->property("abc").isValid());
}
+
+ {
+ QQmlComponent c(&engine);
+ c.setData(R"(
+import StaticTest
+import QtQml
+QtObject {
+ objectName: 'b' + ForeignNamespaceForeign.B
+})", QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->objectName(), "b1");
+ }
+ {
+ QQmlComponent c(&engine);
+ c.setData(R"(
+import StaticTest
+import QtQml
+QtObject {
+ objectName: 'b' + LeakingForeignNamespaceForeign.B
+})", QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->objectName(), "b2");
+ }
}
void tst_qqmllanguage::attachedOwnProperties()
@@ -7711,12 +7882,20 @@ void tst_qqmllanguage::functionSignatureEnforcement()
QCOMPARE(ignored->property("m").toInt(), 77);
QCOMPARE(ignored->property("n").toInt(), 67);
- QQmlComponent c2(&engine, testFileUrl("signatureEnforced.qml"));
+ const QUrl url2 = testFileUrl("signatureEnforced.qml");
+ QQmlComponent c2(&engine, url2);
QVERIFY2(c2.isReady(), qPrintable(c2.errorString()));
+ QTest::ignoreMessage(
+ QtCriticalMsg,
+ qPrintable(url2.toString() + u":36: 15 should be coerced to void because the function "
+ "called is insufficiently annotated. The original value "
+ "is retained. "
+ "This will change in a future version of Qt."_s));
+
QScopedPointer<QObject> enforced(c2.create());
QCOMPARE(enforced->property("l").toInt(), 2); // strlen("no")
- QCOMPARE(enforced->property("m").toInt(), 12);
+ QCOMPARE(enforced->property("m").toInt(), 77);
QCOMPARE(enforced->property("n").toInt(), 99);
QCOMPARE(enforced->property("o").toInt(), 77);
}
@@ -7766,6 +7945,30 @@ void tst_qqmllanguage::multiRequired()
qPrintable(url.toString() + ":5 Required property description was not initialized\n"));
}
+// QTBUG-111088
+void tst_qqmllanguage::isNullOrUndefined()
+{
+ {
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("isNullOrUndefined_interpreter.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVariant result = o.data()->property("result");
+ QVERIFY(result.isValid());
+ QCOMPARE(result.toInt(), 3);
+ }
+
+ {
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("isNullOrUndefined_jit.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVariant result = o.data()->property("result");
+ QVERIFY(result.isValid());
+ QCOMPARE(result.toInt(), 150);
+ }
+}
+
void tst_qqmllanguage::objectAndGadgetMethodCallsRejectThisObject()
{
QQmlEngine engine;
@@ -7810,6 +8013,15 @@ void tst_qqmllanguage::objectAndGadgetMethodCallsAcceptThisObject()
QQmlComponent c(&engine, testFileUrl("objectAndGadgetMethodCallsAcceptThisObject.qml"));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ // Explicitly retrieve the metaobject for the Qt singleton so that the proxy data is created.
+ // This way the inheritance analysis we do when figuring out what toString() means is somewhat
+ // more interesting. Also, we get a deterministic result for Qt.toString().
+ const QQmlType qtType = QQmlMetaType::qmlType(QStringLiteral("Qt"), QString(), QTypeRevision());
+ QVERIFY(qtType.isValid());
+ const QMetaObject *qtMeta = qtType.metaObject();
+ QVERIFY(qtMeta);
+ QCOMPARE(QString::fromUtf8(qtMeta->className()), QLatin1String("Qt"));
+
QTest::ignoreMessage(
QtWarningMsg, QRegularExpression(
"objectAndGadgetMethodCallsAcceptThisObject.qml:16: Error: "
@@ -7840,7 +8052,7 @@ void tst_qqmllanguage::objectAndGadgetMethodCallsAcceptThisObject()
QCOMPARE(o->property("goodString2"), QStringLiteral("27"));
QCOMPARE(o->property("goodString3"), QStringLiteral("28"));
- QVERIFY(o->property("goodString4").value<QString>().startsWith("QtObject"_L1));
+ QVERIFY(o->property("goodString4").value<QString>().startsWith("Qt("_L1));
QCOMPARE(o->property("badString2"), QString());
QCOMPARE(o->property("badInt"), 0);
@@ -7849,6 +8061,906 @@ void tst_qqmllanguage::objectAndGadgetMethodCallsAcceptThisObject()
QCOMPARE(o->property("goodInt3"), 5);
}
+void tst_qqmllanguage::longConversion()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("longConversion.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ for (const char *prop : {
+ "testProp",
+ "testQProp",
+ "fromLocal",
+ "fromQLocal",
+ "fromBoolean",
+ "fromQBoolean"}) {
+ const QVariant val = o->property(prop);
+ QVERIFY(val.isValid());
+ QCOMPARE(val.metaType(), QMetaType::fromType<bool>());
+ QVERIFY(!val.toBool());
+ }
+}
+
+void tst_qqmllanguage::enumPropsManyUnderylingTypes()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("enumPropsManyUnderlyingTypes.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ auto *enumObject = qobject_cast<EnumPropsManyUnderlyingTypes *>(o.get());
+ QCOMPARE(enumObject->si8prop, EnumPropsManyUnderlyingTypes::ResolvedValue);
+ QCOMPARE(enumObject->ui8prop, EnumPropsManyUnderlyingTypes::ResolvedValue);
+ QCOMPARE(enumObject->si16prop, EnumPropsManyUnderlyingTypes::ResolvedValue);
+ QCOMPARE(enumObject->ui16prop, EnumPropsManyUnderlyingTypes::ResolvedValue);
+ QCOMPARE(enumObject->si64prop, EnumPropsManyUnderlyingTypes::ResolvedValue);
+ QCOMPARE(enumObject->ui64prop, EnumPropsManyUnderlyingTypes::ResolvedValue);
+}
+
+void tst_qqmllanguage::asValueType()
+{
+ QQmlEngine engine;
+ const QUrl url = testFileUrl("asValueType.qml");
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "Could not find any constructor for value type QQmlRectFValueType "
+ "to call with value undefined");
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":7:5: Unable to assign [undefined] to QRectF"_L1));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":10: Coercing a value to QML/point using a type "
+ "assertion. This behavior is deprecated. Add 'pragma "
+ "ValueTypeBehavior: Assertable' to prevent it."_L1));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":14: Coercing between incompatible value types mistakenly "
+ "yields null rather than undefined. Add 'pragma "
+ "ValueTypeBehavior: Assertable' to prevent this."_L1));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":15: Coercing from instances of object types to value "
+ "types mistakenly yields null rather than undefined. Add "
+ "'pragma ValueTypeBehavior: Assertable' to prevent "
+ "this."_L1));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":16: Coercing a value to QML/size using a type "
+ "assertion. This behavior is deprecated. Add 'pragma "
+ "ValueTypeBehavior: Assertable' to prevent it."_L1));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":11: Coercing a value to StaticTest/withString using a "
+ "type assertion. This behavior is deprecated. Add 'pragma "
+ "ValueTypeBehavior: Assertable' to prevent it."_L1));
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "Could not find any constructor for value type QQmlSizeFValueType to call "
+ "with value 11");
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":18: Coercing a value to QML/size using a type "
+ "assertion. This behavior is deprecated. Add 'pragma "
+ "ValueTypeBehavior: Assertable' to prevent it."_L1));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":19: Coercing a value to QML/size using a type "
+ "assertion. This behavior is deprecated. Add 'pragma "
+ "ValueTypeBehavior: Assertable' to prevent it."_L1));
+
+ QScopedPointer<QObject> o(c.create());
+
+ QCOMPARE(o->property("a"), QVariant());
+ QCOMPARE(o->property("b").value<QRectF>(), QRectF());
+ QVERIFY(!o->property("c").toBool());
+
+ const QRectF rect(1, 2, 3, 4);
+ o->setProperty("a", QVariant(rect));
+ QCOMPARE(o->property("b").value<QRectF>(), rect);
+ QVERIFY(o->property("c").toBool());
+
+ QVERIFY(!o->property("d").toBool());
+ const QPointF point = o->property("e").value<QPointF>();
+ QCOMPARE(point.x(), 10.0);
+ QCOMPARE(point.y(), 20.0);
+
+ const ValueTypeWithString withString = o->property("f").value<ValueTypeWithString>();
+ QCOMPARE(withString.toString(), u"red");
+
+ const QVariant string = o->property("g");
+ QCOMPARE(string.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(string.toString(), u"green");
+
+ const QVariant p = o->property("p");
+ QCOMPARE(p.metaType(), QMetaType::fromType<std::nullptr_t>());
+
+ const QVariant q = o->property("q");
+ QCOMPARE(q.metaType(), QMetaType::fromType<std::nullptr_t>());
+
+ const QVariant r = o->property("r");
+ QCOMPARE(r.metaType(), QMetaType::fromType<QSizeF>());
+ QCOMPARE(r.value<QSizeF>(), QSizeF());
+
+ const QVariant s = o->property("s");
+ QCOMPARE(s.metaType(), QMetaType());
+
+ const QVariant t = o->property("t");
+ QCOMPARE(t.metaType(), QMetaType::fromType<QSizeF>());
+ QCOMPARE(t.value<QSizeF>(), QSizeF());
+
+ const QVariant u = o->property("u");
+ QCOMPARE(u.metaType(), QMetaType::fromType<QSizeF>());
+ QCOMPARE(u.value<QSizeF>(), QSizeF());
+}
+
+void tst_qqmllanguage::asValueTypeGood()
+{
+ QQmlEngine engine;
+ const QUrl url = testFileUrl("asValueTypeGood.qml");
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":7:5: Unable to assign [undefined] to QRectF"_L1));
+ QScopedPointer<QObject> o(c.create());
+
+ QCOMPARE(o->property("a"), QVariant());
+ QCOMPARE(o->property("b").value<QRectF>(), QRectF());
+ QVERIFY(!o->property("c").toBool());
+
+ const QRectF rect(1, 2, 3, 4);
+ o->setProperty("a", QVariant(rect));
+ QCOMPARE(o->property("b").value<QRectF>(), rect);
+ QVERIFY(o->property("c").toBool());
+
+ QVERIFY(!o->property("d").toBool());
+ QVERIFY(!o->property("e").isValid());
+ QVERIFY(!o->property("f").isValid());
+
+ const QVariant string = o->property("g");
+ QCOMPARE(string.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(string.toString(), u"green");
+
+ const ValueTypeWithString withString = o->property("h").value<ValueTypeWithString>();
+ QCOMPARE(withString.toString(), u"red");
+
+ const QPointF point = o->property("i").value<QPointF>();
+ QCOMPARE(point.x(), 10.0);
+ QCOMPARE(point.y(), 20.0);
+
+ const QVariant j = o->property("j");
+ QCOMPARE(j.metaType(), QMetaType::fromType<int>());
+ QCOMPARE(j.toInt(), 4);
+
+ QVERIFY(!o->property("k").isValid());
+ QVERIFY(!o->property("l").isValid());
+
+ const QVariant m = o->property("m");
+ QCOMPARE(m.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(m.toString(), u"something");
+
+ QVERIFY(!o->property("n").isValid());
+ QVERIFY(!o->property("o").isValid());
+ QVERIFY(!o->property("p").isValid());
+ QVERIFY(!o->property("q").isValid());
+ QVERIFY(!o->property("r").isValid());
+ QVERIFY(!o->property("s").isValid());
+ QVERIFY(!o->property("t").isValid());
+ QVERIFY(!o->property("u").isValid());
+}
+
+void tst_qqmllanguage::typedEnums_data()
+{
+ QTest::addColumn<QString>("property");
+ QTest::addColumn<double>("value");
+ const QMetaObject *mo = &TypedEnums::staticMetaObject;
+ for (int i = 0, end = mo->enumeratorCount(); i != end; ++i) {
+ const QMetaEnum e = mo->enumerator(i);
+ for (int k = 0, end = e.keyCount(); k != end; ++k) {
+ QTest::addRow("%s::%s", e.name(), e.key(k))
+ << QString::fromLatin1(e.name()).toLower()
+ << double(e.value(k));
+ }
+ }
+}
+void tst_qqmllanguage::typedEnums()
+{
+ QFETCH(QString, property);
+ QFETCH(double, value);
+ QQmlEngine e;
+ const QString qml = QLatin1String(R"(
+ import QtQml
+ import TypedEnums
+ ObjectWithEnums {
+ property real input: %2
+ %1: input
+ g.%1: input
+ property real output1: %1
+ property real output2: g.%1
+ }
+ )").arg(property).arg(value, 0, 'f');
+ QQmlComponent c(&engine);
+ c.setData(qml.toUtf8(), QUrl("enums.qml"_L1));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ // TODO: This silently fails for quint32, qint64 and quint64 because QMetaEnum cannot encode
+ // such values either. For the 64bit values we'll also need a better type than double
+ // inside QML.
+ QEXPECT_FAIL("E32U::E32UD", "Not supported", Abort);
+ QEXPECT_FAIL("E32U::E32UE", "Not supported", Abort);
+ QEXPECT_FAIL("E64U::E64UE", "Not supported", Abort);
+
+ QCOMPARE(o->property("output1").toDouble(), value);
+ QCOMPARE(o->property("output2").toDouble(), value);
+}
+
+void tst_qqmllanguage::objectMethodClone()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("objectMethodClone.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QTRY_COMPARE(o->property("doneClicks").toInt(), 2);
+}
+
+void tst_qqmllanguage::unregisteredValueTypeConversion()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("unregisteredValueTypeConversion.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ UnregisteredValueTypeHandler *handler = qobject_cast<UnregisteredValueTypeHandler *>(o.data());
+ Q_ASSERT(handler);
+ QCOMPARE(handler->consumed, 2);
+ QCOMPARE(handler->gadgeted, 1);
+}
+
+void tst_qqmllanguage::retainThis()
+{
+ QQmlEngine e;
+ const QUrl url = testFileUrl("retainThis.qml");
+ QQmlComponent c(&e, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ const QString warning = u"Calling C++ methods with 'this' objects different "
+ "from the one they were retrieved from is broken, due to "
+ "historical reasons. The original object is used as 'this' "
+ "object. You can allow the given 'this' object to be used "
+ "by setting 'pragma NativeMethodBehavior: AcceptThisObject'"_s;
+
+ // Both cases objA because we retain the thisObject.
+ for (int i = 0; i < 2; ++i) {
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(url.toString() + u":12: "_s + warning));
+ QTest::ignoreMessage(QtDebugMsg, "objA says hello");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(url.toString() + u":13: "_s + warning));
+ QTest::ignoreMessage(QtDebugMsg, "objA says 5 + 6 = 11");
+ }
+
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(url.toString() + u":22: "_s + warning));
+ QTest::ignoreMessage(QtDebugMsg, "objA says hello");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(url.toString() + u":22: "_s + warning));
+ QTest::ignoreMessage(QtDebugMsg, "objB says hello");
+
+ QTest::ignoreMessage(QtDebugMsg, "objC says 7 + 7 = 14");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(url.toString() + u":32: "_s + warning));
+ QTest::ignoreMessage(QtDebugMsg, "objB says 7 + 7 = 14");
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
+
+void tst_qqmllanguage::variantObjectList()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("variantObjectList.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ BirthdayParty *party = o->property("q").value<BirthdayParty *>();
+ QCOMPARE(party->guestCount(), 3);
+ QCOMPARE(party->guest(0)->objectName(), "Leo Hodges");
+ QCOMPARE(party->guest(1)->objectName(), "Jack Smith");
+ QCOMPARE(party->guest(2)->objectName(), "Anne Brown");
+}
+
+void tst_qqmllanguage::jitExceptions()
+{
+ QQmlEngine e;
+ const QUrl url = testFileUrl("jitExceptions.qml");
+ QQmlComponent c(&e, testFileUrl("jitExceptions.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + u":5: ReferenceError: control is not defined"_s));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
+
+void tst_qqmllanguage::attachedInCtor()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e);
+ c.setData(R"(
+ import Test
+ AttachedInCtor {}
+ )", QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ AttachedInCtor *a = qobject_cast<AttachedInCtor *>(o.data());
+ QVERIFY(a->attached);
+ QCOMPARE(a->attached, qmlAttachedPropertiesObject<AttachedInCtor>(a, false));
+}
+
+void tst_qqmllanguage::byteArrayConversion()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e);
+ c.setData(R"(
+ import Test
+ import QtQml
+ ByteArrayReceiver {
+ Component.onCompleted: {
+ byteArrayTest([1, 2, 3]);
+ byteArrayTest(Array.from('456'));
+ }
+ }
+ )", QUrl());
+
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ ByteArrayReceiver *receiver = qobject_cast<ByteArrayReceiver *>(o.data());
+ QVERIFY(receiver);
+ QCOMPARE(receiver->byteArrays.length(), 2);
+ QCOMPARE(receiver->byteArrays[0], QByteArray("\1\2\3"));
+ QCOMPARE(receiver->byteArrays[1], QByteArray("\4\5\6"));
+}
+void tst_qqmllanguage::propertySignalNames_data()
+{
+ QTest::addColumn<QString>("propertyName");
+ QTest::addColumn<QString>("propertyChangedSignal");
+ QTest::addColumn<QString>("propertyChangedHandler");
+ QTest::addRow("helloWorld") << u"helloWorld"_s << u"helloWorldChanged"_s
+ << u"onHelloWorldChanged"_s;
+ QTest::addRow("$helloWorld") << u"$helloWorld"_s << u"$helloWorldChanged"_s
+ << u"on$HelloWorldChanged"_s;
+ QTest::addRow("_helloWorld") << u"_helloWorld"_s << u"_helloWorldChanged"_s
+ << u"on_HelloWorldChanged"_s;
+ QTest::addRow("_") << u"_"_s << u"_Changed"_s << u"on_Changed"_s;
+ QTest::addRow("$") << u"$"_s << u"$Changed"_s << u"on$Changed"_s;
+ QTest::addRow("ä") << u"ä"_s << u"äChanged"_s << u"onÄChanged"_s;
+ QTest::addRow("___123a") << u"___123a"_s << u"___123aChanged"_s << u"on___123AChanged"_s;
+}
+void tst_qqmllanguage::propertySignalNames()
+{
+ QFETCH(QString, propertyName);
+ QFETCH(QString, propertyChangedSignal);
+ QFETCH(QString, propertyChangedHandler);
+ QQmlEngine e;
+ QQmlComponent c(&e);
+ c.setData(uR"(
+import QtQuick
+Item {
+ property int %1: 456
+ property bool success: false
+ function f() { %1 = 123; }
+ function g() { %2(); }
+ %3: success = true
+})"_s.arg(propertyName, propertyChangedSignal, propertyChangedHandler)
+ .toUtf8(),
+ QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o != nullptr);
+ const QMetaObject *metaObject = o->metaObject();
+ auto signalIndex =
+ metaObject->indexOfSignal(propertyChangedSignal.append("()").toStdString().c_str());
+ QVERIFY(signalIndex > -1);
+ auto signal = metaObject->method(signalIndex);
+ QVERIFY(signal.isValid());
+ QSignalSpy changeSignal(o.data(), signal);
+ QMetaObject::invokeMethod(o.data(), "f");
+ QCOMPARE(o->property(propertyName.toStdString().c_str()), 123);
+ QVERIFY(changeSignal.size() == 1);
+ QCOMPARE(o->property("success"), true);
+ QMetaObject::invokeMethod(o.data(), "g");
+ QVERIFY(changeSignal.size() == 2);
+}
+void tst_qqmllanguage::signalNames_data()
+{
+ QTest::addColumn<QString>("signalName");
+ QTest::addColumn<QString>("handlerName");
+ QTest::addRow("helloWorld") << u"helloWorld"_s << u"onHelloWorld"_s;
+ QTest::addRow("$helloWorld") << u"$helloWorld"_s << u"on$HelloWorld"_s;
+ QTest::addRow("_helloWorld") << u"_helloWorld"_s << u"on_HelloWorld"_s;
+ QTest::addRow("_") << u"_"_s << u"on_"_s;
+ QTest::addRow("aUmlaut") << u"ä"_s << u"onÄ"_s;
+ QTest::addRow("___123a") << u"___123a"_s << u"on___123A"_s;
+}
+void tst_qqmllanguage::signalNames()
+{
+ QFETCH(QString, signalName);
+ QFETCH(QString, handlerName);
+ QQmlEngine e;
+ QQmlComponent c(&e);
+ c.setData(uR"(
+import QtQuick
+Item {
+ signal %1()
+ property bool success: false
+ function f() { %1(); }
+ %2: success = true
+})"_s.arg(signalName, handlerName)
+ .toUtf8(),
+ QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o != nullptr);
+ const QMetaObject *metaObject = o->metaObject();
+ auto signalIndex = metaObject->indexOfSignal(signalName.append("()").toStdString().c_str());
+ QVERIFY(signalIndex > -1);
+ auto signal = metaObject->method(signalIndex);
+ QVERIFY(signal.isValid());
+ QSignalSpy changeSignal(o.data(), signal);
+ signal.invoke(o.data());
+ QVERIFY(changeSignal.size() == 1);
+ QCOMPARE(o->property("success"), true);
+ QMetaObject::invokeMethod(o.data(), "f");
+ QVERIFY(changeSignal.size() == 2);
+}
+
+void tst_qqmllanguage::callMethodOfAttachedDerived()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine);
+ c.setData(R"(
+ import QtQml
+ import Test
+
+ QtObject {
+ Component.onCompleted: Counter.increase()
+ property int v: Counter.value
+ }
+ )", QUrl());
+
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("v").toInt(), 99);
+}
+
+void tst_qqmllanguage::multiVersionSingletons()
+{
+ qmlRegisterTypesAndRevisions<BareSingleton>("MultiVersionSingletons", 11);
+ qmlRegisterTypesAndRevisions<UncreatableSingleton>("MultiVersionSingletons", 11);
+ QQmlEngine engine;
+
+ for (const char *name : { "BareSingleton", "UncreatableSingleton"}) {
+ const int id1 = qmlTypeId("MultiVersionSingletons", 1, 0, name);
+ const int id2 = qmlTypeId("MultiVersionSingletons", 11, 0, name);
+ QVERIFY(id1 != id2);
+ const QJSValue value1 = engine.singletonInstance<QJSValue>(id1);
+ const QJSValue value2 = engine.singletonInstance<QJSValue>(id2);
+ QVERIFY(value1.strictlyEquals(value2));
+ }
+}
+
+void tst_qqmllanguage::typeAnnotationCycle()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("TypeAnnotationCycle1.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("b").value<QObject*>(), o.data());
+}
+
+void tst_qqmllanguage::corpseInQmlList()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("corpseInQmlList.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QScopedPointer<QObject> a(new QObject);
+ QMetaObject::invokeMethod(o.data(), "setB", Q_ARG(QObject *, a.data()));
+
+ QJSValue b = o->property("b").value<QJSValue>();
+ QQmlListProperty<QObject> list
+ = qjsvalue_cast<QQmlListProperty<QObject>>(b.property(QStringLiteral("b")));
+
+ QCOMPARE(list.count(&list), 1);
+ QCOMPARE(list.at(&list, 0), a.data());
+
+ a.reset();
+
+ b = o->property("b").value<QJSValue>();
+ list = qjsvalue_cast<QQmlListProperty<QObject>>(b.property(QStringLiteral("b")));
+
+ QCOMPARE(list.count(&list), 1);
+ QCOMPARE(list.at(&list, 0), nullptr);
+
+ // The list itself is still alive:
+
+ list.append(&list, o.data());
+ QCOMPARE(list.count(&list), 2);
+ QCOMPARE(list.at(&list, 0), nullptr);
+ QCOMPARE(list.at(&list, 1), o.data());
+
+ list.replace(&list, 0, o.data());
+ QCOMPARE(list.count(&list), 2);
+ QCOMPARE(list.at(&list, 0), o.data());
+ QCOMPARE(list.at(&list, 1), o.data());
+
+ list.removeLast(&list);
+ QCOMPARE(list.count(&list), 1);
+ QCOMPARE(list.at(&list, 0), o.data());
+
+ list.clear(&list);
+ QCOMPARE(list.count(&list), 0);
+}
+
+void tst_qqmllanguage::objectInQmlListAndGc()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("objectInList.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ // Process the deletion event
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+
+ QQmlListProperty<QObject> children = o->property("child").value<QQmlListProperty<QObject>>();
+ QCOMPARE(children.count(&children), 1);
+ QObject *child = children.at(&children, 0);
+ QVERIFY(child);
+ QCOMPARE(child->objectName(), QLatin1String("child"));
+}
+
+void tst_qqmllanguage::asCastToInlineComponent()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("asCastToInlineComponent.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), QLatin1String("value: 20"));
+}
+
+void tst_qqmllanguage::deepAliasOnICOrReadonly()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("deepAliasOnICUser.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("borderColor").toString(), QLatin1String("black"));
+ QCOMPARE(o->property("borderObjectName").toString(), QLatin1String("theLeaf"));
+
+ const QVariant var = o->property("borderVarvar");
+ QCOMPARE(var.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(var.toString(), QLatin1String("mauve"));
+
+ QQmlComponent c2(&engine, testFileUrl("deepAliasOnReadonly.qml"));
+ QVERIFY(c2.isError());
+ QVERIFY(c2.errorString().contains(
+ QLatin1String(
+ "Invalid property assignment: \"readonlyRectX\" is a read-only property")));
+}
+
+void tst_qqmllanguage::optionalChainCallOnNullProperty()
+{
+ QTest::failOnWarning(QRegularExpression(".*Cannot call method 'destroy' of null.*"));
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("optionalChainCallOnNullProperty.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
+
+void tst_qqmllanguage::ambiguousComponents()
+{
+ auto e1 = std::make_unique<QQmlEngine>();
+ e1->addImportPath(dataDirectory());
+ bool isInstanceOf = false;
+
+ {
+ QQmlComponent c(e1.get());
+ c.loadUrl(testFileUrl("ambiguousComponents.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QTest::ignoreMessage(QtDebugMsg, "do");
+ QMetaObject::invokeMethod(o.data(), "dodo");
+
+ QMetaObject::invokeMethod(o.data(), "testInstanceOf", Q_RETURN_ARG(bool, isInstanceOf));
+ QVERIFY(isInstanceOf);
+ }
+
+ QQmlEngine e2;
+ e2.addImportPath(dataDirectory());
+ QQmlComponent c2(&e2);
+ c2.loadUrl(testFileUrl("ambiguousComponents.qml"));
+ QVERIFY2(c2.isReady(), qPrintable(c2.errorString()));
+
+ QScopedPointer<QObject> o2(c2.create());
+ QTest::ignoreMessage(QtDebugMsg, "do");
+ QMetaObject::invokeMethod(o2.data(), "dodo");
+
+ isInstanceOf = false;
+ QMetaObject::invokeMethod(o2.data(), "testInstanceOf", Q_RETURN_ARG(bool, isInstanceOf));
+ QVERIFY(isInstanceOf);
+
+ e1.reset();
+
+ // We can still invoke the function. This means its CU belongs to e2.
+ QTest::ignoreMessage(QtDebugMsg, "do");
+ QMetaObject::invokeMethod(o2.data(), "dodo");
+
+ isInstanceOf = false;
+ QMetaObject::invokeMethod(o2.data(), "testInstanceOf", Q_RETURN_ARG(bool, isInstanceOf));
+ QVERIFY(isInstanceOf);
+}
+
+void tst_qqmllanguage::writeNumberToEnumAlias()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("aliasWriter.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("strokeStyle").toInt(), 1);
+}
+
+void tst_qqmllanguage::badInlineComponentAnnotation()
+{
+ QQmlEngine engine;
+ const QUrl url = testFileUrl("badICAnnotation.qml");
+ QQmlComponent c(&engine, testFileUrl("badICAnnotation.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtCriticalMsg,
+ qPrintable(url.toString() + ":20: 5 should be coerced to void because the function "
+ "called is insufficiently annotated. The original "
+ "value is retained. This will change in a future "
+ "version of Qt."));
+ QTest::ignoreMessage(
+ QtCriticalMsg,
+ QRegularExpression(":22: IC\\([^\\)]+\\) should be coerced to void because the "
+ "function called is insufficiently annotated. The original "
+ "value is retained. This will change in a future version of "
+ "Qt\\."));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("a").toInt(), 5);
+
+ QObject *ic = o->property("ic").value<QObject *>();
+ QVERIFY(ic);
+
+ QCOMPARE(o->property("b").value<QObject *>(), ic);
+ QCOMPARE(o->property("c").value<QObject *>(), ic);
+ QCOMPARE(o->property("d").value<QObject *>(), nullptr);
+}
+
+void tst_qqmllanguage::manuallyCallSignalHandler()
+{
+ // TODO: This test verifies the absence of regression legacy behavior. See QTBUG-120573
+ // Once we can get rid of the legacy behavior, delete this test!
+
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("manuallyCallSignalHandler.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ for (int i = 0; i < 10; ++i) {
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(
+ "Property 'onDestruction' of object QQmlComponentAttached\\(0x[0-9a-f]+\\) is a signal "
+ "handler\\. You should not call it directly\\. Make it a proper function and call that "
+ "or emit the signal\\."));
+ QTest::ignoreMessage(QtDebugMsg, "evil!");
+ QScopedPointer<QObject> o(c.create());
+ QTest::ignoreMessage(QtDebugMsg, "evil!");
+ }
+}
+
+void tst_qqmllanguage::overrideDefaultProperty()
+{
+ QQmlEngine e;
+ const QUrl url = testFileUrl("overrideDefaultProperty.qml");
+
+ // Should not crash here!
+
+ QQmlComponent c(&e, url);
+ QVERIFY(c.isError());
+ QCOMPARE(c.errorString(),
+ url.toString() + QLatin1String(":5 Cannot assign object to list property \"data\"\n"));
+}
+
+void tst_qqmllanguage::enumScopes()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("enumScopes.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("singletonUnscoped"), false);
+ QCOMPARE(o->property("singletonScoped"), true);
+ QCOMPARE(o->property("nonSingletonUnscoped"), false);
+ QCOMPARE(o->property("nonSingletonScoped"), true);
+
+ QCOMPARE(o->property("singletonScopedValue").toInt(), int(EnumProviderSingleton::Expected::Value));
+ QCOMPARE(o->property("singletonUnscopedValue").toInt(), int(EnumProviderSingleton::Expected::Value));
+}
+
+void tst_qqmllanguage::typedObjectList()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("typedObjectList.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QJSValue b = o->property("b").value<QJSValue>();
+ auto list = qjsvalue_cast<QQmlListProperty<QQmlComponent>>(b.property(QStringLiteral("b")));
+
+ QCOMPARE(list.count(&list), 1);
+ QVERIFY(list.at(&list, 0) != nullptr);
+}
+
+void tst_qqmllanguage::jsonArrayPropertyBehavesLikeAnArray() {
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("jsonArrayProperty.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("concatenatedJsonArray"), o->property("concatenatedJsArray"));
+ QVERIFY(o->property("entriesMatch").toBool());
+ QCOMPARE(o->property("jsonArrayEvery"), o->property("jsArrayEvery"));
+ QCOMPARE(o->property("jsonArrayFiltered"), o->property("jsArrayFiltered"));
+ QCOMPARE(o->property("jsonArrayFind"), o->property("jsArrayFind"));
+ QCOMPARE(o->property("jsonArrayFindIndex"), o->property("jsArrayFindIndex"));
+ QCOMPARE(o->property("jsonArrayForEach"), o->property("jsArrayForEach"));
+ QCOMPARE(o->property("jsonArrayIncludes"), o->property("jsArrayIncludes"));
+ QCOMPARE(o->property("jsonArrayIndexOf"), o->property("jsArrayIndexOf"));
+ QCOMPARE(o->property("jsonArrayJoin"), o->property("jsArrayJoin"));
+ QVERIFY(o->property("keysMatch").toBool());
+ QCOMPARE(o->property("jsonArrayLastIndexOf"), o->property("jsArrayLastIndexOf"));
+ QCOMPARE(o->property("jsonArrayMap"), o->property("jsArrayMap"));
+ QCOMPARE(o->property("jsonArrayReduce"), o->property("jsArrayReduce"));
+ QCOMPARE(o->property("jsonArrayReduceRight"), o->property("jsArrayReduceRight"));
+ QCOMPARE(o->property("jsonArraySlice"), o->property("jsArraySlice"));
+ QCOMPARE(o->property("jsonArraySome"), o->property("jsArraySome"));
+ QCOMPARE(o->property("stringifiedLocaleJsonArray"), o->property("stringifiedLocaleJsArray"));
+ QCOMPARE(o->property("stringifiedJsonArray"), o->property("stringifiedJsArray"));
+ QVERIFY(o->property("valuesMatch").toBool());
+
+ QVERIFY(o->property("jsonArrayWasCopiedWithin").toBool());
+ QVERIFY(o->property("jsonArrayWasFilled").toBool());
+ QVERIFY(o->property("jsonArrayWasPopped").toBool());
+ QVERIFY(o->property("jsonArrayWasPushed").toBool());
+ QVERIFY(o->property("jsonArrayWasReversed").toBool());
+ QVERIFY(o->property("jsonArrayWasShifted").toBool());
+ QVERIFY(o->property("jsonArrayWasSpliced").toBool());
+ QVERIFY(o->property("jsonArrayWasUnshifted").toBool());
+ QVERIFY(o->property("jsonArrayWasSorted").toBool());
+}
+
+void tst_qqmllanguage::invokableCtors()
+{
+ QQmlEngine e;
+
+ const QUrl url = testFileUrl("invokableCtors.qml");
+
+ QQmlComponent c(&e, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ const QString urlString = url.toString();
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(
+ urlString + ":9: You are calling a Q_INVOKABLE constructor of "
+ "InvokableSingleton which is a singleton in QML."));
+
+ // Extended types look like types without any constructors.
+ // Therefore they aren't even FunctionObjects.
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(
+ urlString + ":10: TypeError: Type error"));
+
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(
+ urlString + ":11: You are calling a Q_INVOKABLE constructor of "
+ "InvokableUncreatable which is uncreatable in QML."));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QObject *oo = qvariant_cast<QObject *>(o->property("oo"));
+ QVERIFY(oo);
+ QObject *pp = qvariant_cast<QObject *>(o->property("pp"));
+ QVERIFY(pp);
+ QCOMPARE(pp->parent(), oo);
+
+ InvokableValueType vv = qvariant_cast<InvokableValueType>(o->property("v"));
+ QCOMPARE(vv.m_s, "green");
+
+ InvokableSingleton *i = qvariant_cast<InvokableSingleton *>(o->property("i"));
+ QVERIFY(i);
+ QCOMPARE(i->m_a, 5);
+ QCOMPARE(i->parent(), oo);
+
+ QVariant k = o->property("k");
+ QCOMPARE(k.metaType(), QMetaType::fromType<InvokableExtended *>());
+ QCOMPARE(k.value<InvokableExtended *>(), nullptr);
+
+ InvokableUncreatable *l = qvariant_cast<InvokableUncreatable *>(o->property("l"));
+ QVERIFY(l);
+}
+
+void tst_qqmllanguage::nestedVectors()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("nestedVectors.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ NestedVectors *n = qobject_cast<NestedVectors *>(o.data());
+ QVERIFY(n);
+
+ const std::vector<std::vector<int>> expected1 { { 1, 2, 3 }, { 4, 5 } };
+ const QVariant list1 = n->property("list1");
+ QCOMPARE(list1.metaType(), QMetaType::fromType<std::vector<std::vector<int>>>());
+ QCOMPARE(list1.value<std::vector<std::vector<int>>>(), expected1);
+
+ const std::vector<std::vector<int>> expected2 { { 2, 3, 4 }, { 5, 6 } };
+ QCOMPARE(n->getList(), expected2);
+}
+
+void tst_qqmllanguage::optimizedSequenceShift()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("optimizedSequenceShift.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("changes").toInt(), 2);
+
+ const QVariant one = o->property("one");
+ QCOMPARE(one.metaType(), QMetaType::fromType<int>());
+ QCOMPARE(one.toInt(), 1);
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"
diff --git a/tests/auto/qml/qqmllistcompositor/CMakeLists.txt b/tests/auto/qml/qqmllistcompositor/CMakeLists.txt
index c05b97f6d2..b6999900ba 100644
--- a/tests/auto/qml/qqmllistcompositor/CMakeLists.txt
+++ b/tests/auto/qml/qqmllistcompositor/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmllistcompositor Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmllistcompositor LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmllistcompositor
SOURCES
tst_qqmllistcompositor.cpp
diff --git a/tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp b/tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp
index 2d02cac9f8..c10ceafeae 100644
--- a/tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp
+++ b/tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <private/qqmllistcompositor_p.h>
@@ -179,7 +180,7 @@ void tst_qqmllistcompositor::find()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
compositor.find(startGroup, startIndex);
@@ -241,7 +242,7 @@ void tst_qqmllistcompositor::findInsertPosition()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QQmlListCompositor::insert_iterator it = compositor.findInsertPosition(group, index);
@@ -499,7 +500,7 @@ void tst_qqmllistcompositor::clearFlags()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QVector<C::Remove> removes;
@@ -681,7 +682,7 @@ void tst_qqmllistcompositor::setFlags()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QVector<C::Insert> inserts;
@@ -968,7 +969,7 @@ void tst_qqmllistcompositor::move()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QVector<C::Remove> removes;
@@ -1202,7 +1203,7 @@ void tst_qqmllistcompositor::listItemsInserted()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QVector<C::Insert> inserts;
@@ -1338,7 +1339,7 @@ void tst_qqmllistcompositor::listItemsRemoved()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QVector<C::Remove> removes;
@@ -1532,7 +1533,7 @@ void tst_qqmllistcompositor::listItemsMoved()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QVector<C::Remove> removes;
@@ -1612,7 +1613,7 @@ void tst_qqmllistcompositor::listItemsChanged()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QVector<C::Change> changes;
diff --git a/tests/auto/qml/qqmllistmodel/CMakeLists.txt b/tests/auto/qml/qqmllistmodel/CMakeLists.txt
index 7c689e643c..133a2dce5d 100644
--- a/tests/auto/qml/qqmllistmodel/CMakeLists.txt
+++ b/tests/auto/qml/qqmllistmodel/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmllistmodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmllistmodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmllistmodel/data/nestedLists.qml b/tests/auto/qml/qqmllistmodel/data/nestedLists.qml
new file mode 100644
index 0000000000..4aea6f1ae1
--- /dev/null
+++ b/tests/auto/qml/qqmllistmodel/data/nestedLists.qml
@@ -0,0 +1,37 @@
+import QtQuick
+
+Item {
+ id: mainWindow
+
+ function load(data) {
+ model.clear()
+ for (var i = 0; i < data.length; i++)
+ model.append(data[i])
+ }
+
+ ListModel {
+ id: model
+ }
+
+ Repeater {
+ objectName: "topLevel"
+ model: model
+ Item {
+ objectName: _headline
+ Repeater {
+ objectName: "month"
+ model: _weeks
+ Item {
+ objectName: index
+ Repeater {
+ objectName: "week"
+ model: _week
+ Item {
+ objectName: _day
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
index e522f280a3..d738a7f68d 100644
--- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
+++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
@@ -1,13 +1,15 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQuick/private/qquickanimation_p.h>
#include <QtQuick/private/qquicklistview_p.h>
+#include <QtQuick/private/qquickrepeater_p.h>
#include <QtQml/private/qqmlengine_p.h>
#include <QtQmlModels/private/qqmllistmodel_p.h>
#include <QtQml/private/qqmlexpression_p.h>
+#include <QtQml/private/qqmlsignalnames_p.h>
#include <QQmlComponent>
#include <QtCore/qtimer.h>
@@ -119,6 +121,7 @@ private slots:
void objectOwnershipFlip();
void enumsInListElement();
void protectQObjectFromGC();
+ void nestedLists();
};
bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object)
@@ -248,8 +251,8 @@ void tst_qqmllistmodel::static_types()
QVERIFY(!component.isError());
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj);
if (error.isEmpty()) {
QVariant actual = obj->property("test");
@@ -257,8 +260,6 @@ void tst_qqmllistmodel::static_types()
QCOMPARE(actual, value);
QCOMPARE(actual.toString(), value.toString());
}
-
- delete obj;
}
void tst_qqmllistmodel::static_i18n_data()
@@ -319,15 +320,13 @@ void tst_qqmllistmodel::static_i18n()
QVERIFY(!component.isError());
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj);
QVariant actual = obj->property("test");
QCOMPARE(actual, value);
QCOMPARE(actual.toString(), value.toString());
-
- delete obj;
}
void tst_qqmllistmodel::dynamic_i18n_data()
@@ -368,16 +367,15 @@ void tst_qqmllistmodel::dynamic_i18n()
QVERIFY(!component.isError());
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj);
QVariant actual = obj->property("test");
QCOMPARE(actual, value);
QCOMPARE(actual.toString(), value.toString());
-
- delete obj;
}
+
void tst_qqmllistmodel::static_nestedElements()
{
QFETCH(int, elementCount);
@@ -406,14 +404,12 @@ void tst_qqmllistmodel::static_nestedElements()
QQmlComponent component(&engine);
component.setData(componentStr.toUtf8(), QUrl::fromLocalFile(""));
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj);
QVariant count = obj->property("count");
QCOMPARE(count.typeId(), QMetaType::Int);
QCOMPARE(count.toInt(), elementCount);
-
- delete obj;
}
void tst_qqmllistmodel::static_nestedElements_data()
@@ -606,8 +602,8 @@ void tst_qqmllistmodel::enumerate()
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("enumerate.qml"));
QVERIFY(!component.isError());
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item { qobject_cast<QQuickItem*>(component.create()) };
+ QVERIFY(item);
QLatin1String expectedStrings[] = {
QLatin1String("val1=1Y"),
@@ -638,8 +634,6 @@ void tst_qqmllistmodel::enumerate()
}
QCOMPARE(matchCount, expectedStringCount);
-
- delete item;
}
void tst_qqmllistmodel::error_data()
@@ -779,9 +773,9 @@ void tst_qqmllistmodel::get()
component.setData(
"import QtQuick 2.0\n"
"ListModel {}\n", QUrl());
- QQmlListModel *model = qobject_cast<QQmlListModel*>(component.create());
+ std::unique_ptr<QQmlListModel> model { qobject_cast<QQmlListModel*>(component.create()) };
model->setDynamicRoles(dynamicRoles);
- engine.rootContext()->setContextProperty("model", model);
+ engine.rootContext()->setContextProperty("model", model.get());
RUNEXPR("model.append({roleA: 100})");
RUNEXPR("model.append({roleA: 200, roleB: 400})");
@@ -789,12 +783,12 @@ void tst_qqmllistmodel::get()
RUNEXPR("model.append({roleC: {} })");
RUNEXPR("model.append({roleD: [ { a:1, b:2 }, { c: 3 } ] })");
- QSignalSpy spy(model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)));
- QQmlExpression expr(engine.rootContext(), model, expression);
+ QSignalSpy spy(model.get(), SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)));
+ QQmlExpression expr(engine.rootContext(), model.get(), expression);
expr.evaluate();
QVERIFY(!expr.hasError());
- int role = roleFromName(model, roleName);
+ int role = roleFromName(model.get(), roleName);
QVERIFY(role >= 0);
if (roleValue.typeId() == QMetaType::QVariantList) {
@@ -810,8 +804,6 @@ void tst_qqmllistmodel::get()
QCOMPARE(spyResult.at(0).value<QModelIndex>(), model->index(index, 0, QModelIndex()));
QCOMPARE(spyResult.at(1).value<QModelIndex>(), model->index(index, 0, QModelIndex())); // only 1 item is modified at a time
QCOMPARE(spyResult.at(2).value<QVector<int> >(), (QVector<int>() << role));
-
- delete model;
}
void tst_qqmllistmodel::get_data()
@@ -857,11 +849,11 @@ void tst_qqmllistmodel::get_nested()
component.setData(
"import QtQuick 2.0\n"
"ListModel {}", QUrl());
- QQmlListModel *model = qobject_cast<QQmlListModel*>(component.create());
+ std::unique_ptr<QQmlListModel> model { qobject_cast<QQmlListModel*>(component.create()) };
model->setDynamicRoles(dynamicRoles);
QVERIFY(component.errorString().isEmpty());
QQmlListModel *childModel;
- engine.rootContext()->setContextProperty("model", model);
+ engine.rootContext()->setContextProperty("model", model.get());
RUNEXPR("model.append({ listRoleA: [\n"
"{ roleA: 100 },\n"
@@ -908,16 +900,16 @@ void tst_qqmllistmodel::get_nested()
for (int i=0; i<testData.size(); i++) {
int outerListIndex = testData[i].first;
QString outerListRoleName = testData[i].second;
- int outerListRole = roleFromName(model, outerListRoleName);
+ int outerListRole = roleFromName(model.get(), outerListRoleName);
QVERIFY(outerListRole >= 0);
childModel = qobject_cast<QQmlListModel*>(model->data(outerListIndex, outerListRole).value<QObject*>());
QVERIFY(childModel);
QString extendedExpression = QString("get(%1).%2.%3").arg(outerListIndex).arg(outerListRoleName).arg(expression);
- QQmlExpression expr(engine.rootContext(), model, extendedExpression);
+ QQmlExpression expr(engine.rootContext(), model.get(), extendedExpression);
- QSignalSpy spy(childModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)));
+ QSignalSpy spy(childModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)));
expr.evaluate();
QVERIFY(!expr.hasError());
@@ -935,8 +927,6 @@ void tst_qqmllistmodel::get_nested()
QCOMPARE(spyResult.at(1).value<QModelIndex>(), childModel->index(index, 0, QModelIndex())); // only 1 item is modified at a time
QCOMPARE(spyResult.at(2).value<QVector<int> >(), (QVector<int>() << role));
}
-
- delete model;
}
void tst_qqmllistmodel::get_nested_data()
@@ -949,16 +939,14 @@ void tst_qqmllistmodel::crash_model_with_multiple_roles()
{
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("multipleroles.qml"));
- QObject *rootItem = component.create();
+ std::unique_ptr<QObject> rootItem { component.create() };
QVERIFY(component.errorString().isEmpty());
- QVERIFY(rootItem != nullptr);
+ QVERIFY(rootItem);
QQmlListModel *model = rootItem->findChild<QQmlListModel*>("listModel");
QVERIFY(model != nullptr);
// used to cause a crash
model->setProperty(0, "black", true);
-
- delete rootItem;
}
void tst_qqmllistmodel::crash_model_with_unknown_roles()
@@ -983,22 +971,19 @@ void tst_qqmllistmodel::crash_model_with_dynamic_roles()
// setting a dynamic role to a QObject value, then triggering dtor
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("dynamicroles.qml"));
- QObject *rootItem = component.create();
+ std::unique_ptr<QObject> rootItem { component.create() };
qWarning() << component.errorString();
QVERIFY(component.errorString().isEmpty());
- QVERIFY(rootItem != 0);
+ QVERIFY(rootItem.get() != 0);
QQmlListModel *model = rootItem->findChild<QQmlListModel*>("listModel");
QVERIFY(model != 0);
QMetaObject::invokeMethod(model, "appendNewElement");
- QObject *testObj = new QObject;
- model->setProperty(0, "obj", QVariant::fromValue<QObject*>(testObj));
- delete testObj;
+ model->setProperty(0, "obj", QVariant::fromValue<QObject*>(std::make_unique<QObject>().get()));
- // delete the root item, which will cause the model dtor to run
- // previously, this would crash as it attempted to delete testObj.
- delete rootItem;
+ // Let root item go out of scope to let the model dtor run.
+ // Previously, this would crash as it attempted to delete the already-deleted temporary QObject.
}
{
@@ -1006,22 +991,18 @@ void tst_qqmllistmodel::crash_model_with_dynamic_roles()
// DynamicRoleModelNode::updateValues() to trigger unsafe qobject_cast
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("dynamicroles.qml"));
- QObject *rootItem = component.create();
+ std::unique_ptr<QObject> rootItem { component.create() };
qWarning() << component.errorString();
QVERIFY(component.errorString().isEmpty());
- QVERIFY(rootItem != 0);
+ QVERIFY(rootItem.get() != 0);
QQmlListModel *model = rootItem->findChild<QQmlListModel*>("listModel");
QVERIFY(model != 0);
QMetaObject::invokeMethod(model, "appendNewElement");
- QObject *testObj = new QObject;
- model->setProperty(0, "obj", QVariant::fromValue<QObject*>(testObj));
- delete testObj;
+ model->setProperty(0, "obj", QVariant::fromValue<QObject*>(std::make_unique<QObject>().get()));
QMetaObject::invokeMethod(model, "setElementAgain");
-
- delete rootItem;
}
{
@@ -1098,21 +1079,21 @@ void tst_qqmllistmodel::property_changes()
expr.evaluate();
QVERIFY2(!expr.hasError(), qPrintable(expr.error().toString()));
- QString signalHandler = "on" + QString(roleName[0].toUpper()) + roleName.mid(1, roleName.size()) + "Changed:";
+ QString signalHandler = QQmlSignalNames::propertyNameToChangedHandlerName(roleName);
QString qml = "import QtQuick 2.0\n"
"Connections {\n"
"property bool gotSignal: false\n"
"target: model.get(" + QString::number(listIndex) + ")\n"
- + signalHandler + " gotSignal = true\n"
+ + signalHandler + ": gotSignal = true\n"
"}\n";
QQmlComponent component(&engine);
component.setData(qml.toUtf8(), QUrl::fromLocalFile(""));
engine.rootContext()->setContextProperty("model", &model);
- QObject *connectionsObject = component.create();
+ std::unique_ptr<QObject> connectionsObject { component.create() };
QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
- QSignalSpy spyItemsChanged(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)));
+ QSignalSpy spyItemsChanged(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)));
expr.setExpression(script_change);
expr.evaluate();
@@ -1132,8 +1113,6 @@ void tst_qqmllistmodel::property_changes()
expr.setExpression(testExpression);
QCOMPARE(expr.evaluate().toBool(), true);
-
- delete connectionsObject;
}
void tst_qqmllistmodel::property_changes_data()
@@ -1354,10 +1333,8 @@ void tst_qqmllistmodel::empty_element_warning()
component.setData(qml.toUtf8(), QUrl::fromLocalFile(QString("dummy.qml")));
QVERIFY(!component.isError());
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
-
- delete obj;
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj);
}
void tst_qqmllistmodel::datetime_data()
@@ -1549,6 +1526,8 @@ void tst_qqmllistmodel::modify_through_delegate()
" ListElement { name: \"Doe\"; age: 33 }\n"
" }\n"
" ListView {\n"
+ " height: 100\n" \
+ " width: 100\n" \
" model: testModel\n"
" delegate: Item {\n"
" Component.onCompleted: model.age = 18;\n"
@@ -1929,6 +1908,154 @@ void tst_qqmllistmodel::protectQObjectFromGC()
}
}
+static QVariantList createLast7Days()
+{
+ QVariantList last7DaysList;
+ for (int i = 0; i < 7; i++) {
+ QVariantMap map;
+ map.insert("_day", i);
+ last7DaysList.append(map);
+ }
+ return last7DaysList;
+}
+
+static QVariantList createWeekChartModels()
+{
+ QVariantList list;
+ for (int i = 0; i < 4; i++) {
+ QVariantMap map;
+ map.insert("_week", createLast7Days());
+ list.append(map);
+ }
+ return list;
+}
+
+static QVariantList createVariantModel()
+{
+ QVariantMap element1;
+ element1.insert("_headline", "Element 1");
+ element1.insert("_weeks", createWeekChartModels());
+
+ QVariantMap element2;
+ element2.insert("_headline", "Element 2");
+ element2.insert("_weeks", createWeekChartModels());
+
+ QVariantMap element3;
+ element3.insert("_headline", "Element 3");
+ element3.insert("_weeks", createWeekChartModels());
+
+ QVariantList list;
+ list.append(element1);
+ list.append(element2);
+ list.append(element3);
+
+ return list;
+}
+
+class Day : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int _day READ _day CONSTANT)
+public:
+ Day(int day, QObject *parent = nullptr) : QObject(parent), day(day) {}
+ int _day() const { return day; }
+private:
+ int day = 0;
+};
+
+class Week : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<Day> _week READ _week)
+public:
+ Week(QObject *parent = nullptr) : QObject(parent)
+ {
+ for (int i = 0; i < 7; ++i)
+ week.append(new Day(i, this));
+ }
+
+ QQmlListProperty<Day> _week() { return QQmlListProperty<Day>(this, &week); }
+
+private:
+ QList<Day *> week;
+};
+
+class Month : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<Week> _weeks READ _weeks)
+ Q_PROPERTY(QString _headline READ _headline CONSTANT)
+public:
+
+ Month(int i, QObject *parent = nullptr)
+ : QObject(parent)
+ , headline(QLatin1String("Element ") + QString::number(i))
+ {
+ for (int i = 0; i < 4; ++i)
+ weeks.append(new Week(this));
+ }
+
+ QQmlListProperty<Week> _weeks() { return QQmlListProperty<Week>(this, &weeks); }
+ QString _headline() const { return headline; }
+
+private:
+ QList<Week *> weeks;
+ QString headline;
+};
+
+static void verifyLists(const QVariantList &list, QQuickRepeater *topLevel)
+{
+ QVERIFY(topLevel);
+ QCOMPARE(topLevel->count(), 3);
+
+ for (int month = 0; month < 3; ++month) {
+ const QVariantMap monthData = list[month].toMap();
+ const QQuickItem *monthItem = topLevel->itemAt(month);
+ QCOMPARE(monthItem->objectName(), monthData["_headline"].toString());
+ const QQuickRepeater *monthRepeater = monthItem->findChild<QQuickRepeater *>("month");
+ QVERIFY(monthRepeater);
+ QCOMPARE(monthRepeater->count(), 4);
+ const QVariantList weekList = monthData["_weeks"].toList();
+ for (int week = 0; week < 4; ++week) {
+ const QVariantList weekData = weekList[week].toMap()["_week"].toList();
+ const QQuickItem *weekItem = monthRepeater->itemAt(week);
+ QCOMPARE(weekItem->objectName(), QString::number(week));
+ const QQuickRepeater *weekRepeater = weekItem->findChild<QQuickRepeater *>("week");
+ QVERIFY(weekRepeater);
+ QCOMPARE(weekRepeater->count(), 7);
+ for (int day = 0; day < 7; ++day) {
+ const QVariantMap dayData = weekData[day].toMap();
+ const QQuickItem *dayItem = weekRepeater->itemAt(day);
+ QCOMPARE(dayItem->objectName(), dayData["_day"]);
+ }
+ }
+ }
+}
+
+void tst_qqmllistmodel::nestedLists()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("nestedLists.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+
+ QQuickRepeater *topLevel = o->findChild<QQuickRepeater *>("topLevel");
+
+ const QVariantList list = createVariantModel();
+ QMetaObject::invokeMethod(o.data(), "load", Q_ARG(QVariant, QVariant::fromValue(list)));
+ verifyLists(list, topLevel);
+
+ const QObjectList objects {
+ new Month(1, o.data()),
+ new Month(2, o.data()),
+ new Month(3, o.data())
+ };
+
+ QMetaObject::invokeMethod(o.data(), "load", Q_ARG(QVariant, QVariant::fromValue(objects)));
+ verifyLists(list, topLevel);
+}
+
QTEST_MAIN(tst_qqmllistmodel)
#include "tst_qqmllistmodel.moc"
diff --git a/tests/auto/qml/qqmllistmodelworkerscript/CMakeLists.txt b/tests/auto/qml/qqmllistmodelworkerscript/CMakeLists.txt
index ac77f65b68..93d597e687 100644
--- a/tests/auto/qml/qqmllistmodelworkerscript/CMakeLists.txt
+++ b/tests/auto/qml/qqmllistmodelworkerscript/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmllistmodelworkerscript Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmllistmodelworkerscript LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp b/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp
index 4875602314..93f18ea8d5 100644
--- a/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp
+++ b/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquicktext_p.h>
@@ -55,7 +56,7 @@ public:
private:
int roleFromName(const QQmlListModel *model, const QString &roleName);
- QQuickItem *createWorkerTest(QQmlEngine *eng, QQmlComponent *component, QQmlListModel *model);
+ std::unique_ptr<QQuickItem> createWorkerTest(QQmlEngine *eng, QQmlComponent *component, QQmlListModel *model);
void waitForWorker(QQuickItem *item);
static bool compareVariantList(const QVariantList &testList, QVariant object);
@@ -134,9 +135,9 @@ int tst_qqmllistmodelworkerscript::roleFromName(const QQmlListModel *model, cons
return model->roleNames().key(roleName.toUtf8(), -1);
}
-QQuickItem *tst_qqmllistmodelworkerscript::createWorkerTest(QQmlEngine *eng, QQmlComponent *component, QQmlListModel *model)
+std::unique_ptr<QQuickItem> tst_qqmllistmodelworkerscript::createWorkerTest(QQmlEngine *eng, QQmlComponent *component, QQmlListModel *model)
{
- QQuickItem *item = qobject_cast<QQuickItem*>(component->create());
+ std::unique_ptr<QQuickItem> item { qobject_cast<QQuickItem*>(component->create()) };
QQmlEngine::setContextForObject(model, eng->rootContext());
if (item)
item->setProperty("model", QVariant::fromValue(model));
@@ -326,15 +327,16 @@ void tst_qqmllistmodelworkerscript::dynamic_worker()
model.setDynamicRoles(dynamicRoles);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("model.qml"));
- QQuickItem *item = createWorkerTest(&eng, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&eng, &component, &model);
+ QVERIFY(item);
QSignalSpy spyCount(&model, SIGNAL(countChanged()));
if (script[0] == QLatin1Char('{') && script[script.size()-1] == QLatin1Char('}'))
script = script.mid(1, script.size() - 2);
QVariantList operations;
- foreach (const QString &s, script.split(';')) {
+ const QStringList statements = script.split(';');
+ for (const QString &s : statements) {
if (!s.isEmpty())
operations << s;
}
@@ -342,15 +344,15 @@ void tst_qqmllistmodelworkerscript::dynamic_worker()
if (isValidErrorMessage(warning, dynamicRoles))
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1());
- QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker",
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "evalExpressionViaWorker",
Q_ARG(QVariant, operations)));
- waitForWorker(item);
- QCOMPARE(QQmlProperty(item, "result").read().toInt(), result);
+ waitForWorker(item.get());
+ QCOMPARE(QQmlProperty(item.get(), "result").read().toInt(), result);
if (model.count() > 0)
QVERIFY(spyCount.size() > 0);
- delete item;
+ item.reset();
qApp->processEvents();
}
@@ -377,13 +379,14 @@ void tst_qqmllistmodelworkerscript::dynamic_worker_sync()
model.setDynamicRoles(dynamicRoles);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("model.qml"));
- QQuickItem *item = createWorkerTest(&eng, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&eng, &component, &model);
+ QVERIFY(item);
if (script[0] == QLatin1Char('{') && script[script.size()-1] == QLatin1Char('}'))
script = script.mid(1, script.size() - 2);
QVariantList operations;
- foreach (const QString &s, script.split(';')) {
+ const QStringList statements = script.split(';');
+ for (const QString &s : statements) {
if (!s.isEmpty())
operations << s;
}
@@ -393,14 +396,14 @@ void tst_qqmllistmodelworkerscript::dynamic_worker_sync()
// execute a set of commands on the worker list model, then check the
// changes are reflected in the list model in the main thread
- QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker",
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "evalExpressionViaWorker",
Q_ARG(QVariant, operations.mid(0, operations.size()-1))));
- waitForWorker(item);
+ waitForWorker(item.get());
QQmlExpression e(eng.rootContext(), &model, operations.last().toString());
QCOMPARE(e.evaluate().toInt(), result);
- delete item;
+ item.reset();
qApp->processEvents();
}
@@ -440,25 +443,25 @@ void tst_qqmllistmodelworkerscript::get_worker()
model.setDynamicRoles(dynamicRoles);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("model.qml"));
- QQuickItem *item = createWorkerTest(&eng, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&eng, &component, &model);
+ QVERIFY(item);
// Add some values like get() test
- RUNEVAL(item, "model.append({roleA: 100})");
- RUNEVAL(item, "model.append({roleA: 200, roleB: 400})");
- RUNEVAL(item, "model.append({roleA: 200, roleB: 400})");
- RUNEVAL(item, "model.append({roleC: {} })");
- RUNEVAL(item, "model.append({roleD: [ { a:1, b:2 }, { c: 3 } ] })");
+ RUNEVAL(item.get(), "model.append({roleA: 100})");
+ RUNEVAL(item.get(), "model.append({roleA: 200, roleB: 400})");
+ RUNEVAL(item.get(), "model.append({roleA: 200, roleB: 400})");
+ RUNEVAL(item.get(), "model.append({roleC: {} })");
+ RUNEVAL(item.get(), "model.append({roleD: [ { a:1, b:2 }, { c: 3 } ] })");
int role = roleFromName(&model, roleName);
QVERIFY(role >= 0);
- QSignalSpy spy(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)));
+ QSignalSpy spy(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)));
// in the worker thread, change the model data and call sync()
- QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker",
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "evalExpressionViaWorker",
Q_ARG(QVariant, QStringList(expression))));
- waitForWorker(item);
+ waitForWorker(item.get());
// see if we receive the model changes in the main thread's model
if (roleValue.typeId() == QMetaType::QVariantList) {
@@ -474,8 +477,6 @@ void tst_qqmllistmodelworkerscript::get_worker()
QCOMPARE(spyResult.at(0).value<QModelIndex>(), model.index(index, 0, QModelIndex()));
QCOMPARE(spyResult.at(1).value<QModelIndex>(), model.index(index, 0, QModelIndex())); // only 1 item is modified at a time
QVERIFY(spyResult.at(2).value<QVector<int> >().contains(role));
-
- delete item;
}
void tst_qqmllistmodelworkerscript::get_worker_data()
@@ -570,18 +571,18 @@ void tst_qqmllistmodelworkerscript::property_changes_worker()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("model.qml"));
QVERIFY2(component.errorString().isEmpty(), component.errorString().toUtf8());
- QQuickItem *item = createWorkerTest(&engine, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&engine, &component, &model);
+ QVERIFY(item);
QQmlExpression expr(engine.rootContext(), &model, script_setup);
expr.evaluate();
- QVERIFY2(!expr.hasError(), QTest::toString(expr.error().toString()));
+ QVERIFY2(!expr.hasError(), qPrintable(expr.error().toString()));
- QSignalSpy spyItemsChanged(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)));
+ QSignalSpy spyItemsChanged(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)));
- QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker",
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "evalExpressionViaWorker",
Q_ARG(QVariant, QStringList(script_change))));
- waitForWorker(item);
+ waitForWorker(item.get());
// test itemsChanged() is emitted correctly
if (itemsChanged) {
@@ -592,7 +593,7 @@ void tst_qqmllistmodelworkerscript::property_changes_worker()
QCOMPARE(spyItemsChanged.size(), 0);
}
- delete item;
+ item.reset();
qApp->processEvents();
}
@@ -617,12 +618,12 @@ void tst_qqmllistmodelworkerscript::worker_sync()
model.setDynamicRoles(dynamicRoles);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("workersync.qml"));
- QQuickItem *item = createWorkerTest(&eng, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&eng, &component, &model);
+ QVERIFY(item);
QCOMPARE(model.count(), 0);
- QVERIFY(QMetaObject::invokeMethod(item, "addItem0"));
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "addItem0"));
QCOMPARE(model.count(), 2);
QVariant childData = model.data(0, 0);
@@ -633,39 +634,39 @@ void tst_qqmllistmodelworkerscript::worker_sync()
QSignalSpy spyModelInserted(&model, SIGNAL(rowsInserted(QModelIndex,int,int)));
QSignalSpy spyChildInserted(childModel, SIGNAL(rowsInserted(QModelIndex,int,int)));
- QVERIFY(QMetaObject::invokeMethod(item, "addItemViaWorker"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "addItemViaWorker"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 2);
QCOMPARE(childModel->count(), 1);
QCOMPARE(spyModelInserted.size(), 0);
QCOMPARE(spyChildInserted.size(), 0);
- QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "doSync"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 2);
QCOMPARE(childModel->count(), 2);
QCOMPARE(spyModelInserted.size(), 0);
QCOMPARE(spyChildInserted.size(), 1);
- QVERIFY(QMetaObject::invokeMethod(item, "addItemViaWorker"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "addItemViaWorker"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 2);
QCOMPARE(childModel->count(), 2);
QCOMPARE(spyModelInserted.size(), 0);
QCOMPARE(spyChildInserted.size(), 1);
- QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "doSync"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 2);
QCOMPARE(childModel->count(), 3);
QCOMPARE(spyModelInserted.size(), 0);
QCOMPARE(spyChildInserted.size(), 2);
- delete item;
+ item.reset();
qApp->processEvents();
}
@@ -682,53 +683,51 @@ void tst_qqmllistmodelworkerscript::worker_remove_element()
model.setDynamicRoles(dynamicRoles);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("workerremoveelement.qml"));
- QQuickItem *item = createWorkerTest(&eng, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&eng, &component, &model);
+ QVERIFY(item);
QSignalSpy spyModelRemoved(&model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
QCOMPARE(model.count(), 0);
QCOMPARE(spyModelRemoved.size(), 0);
- QVERIFY(QMetaObject::invokeMethod(item, "addItem"));
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "addItem"));
QCOMPARE(model.count(), 1);
- QVERIFY(QMetaObject::invokeMethod(item, "removeItemViaWorker"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "removeItemViaWorker"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 1);
QCOMPARE(spyModelRemoved.size(), 0);
- QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "doSync"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 0);
QCOMPARE(spyModelRemoved.size(), 1);
- delete item;
+ item.reset();
qApp->processEvents();
{
//don't crash if model was deleted earlier
- QQmlListModel* model = new QQmlListModel;
+ std::unique_ptr<QQmlListModel> model = std::make_unique<QQmlListModel>();
model->setDynamicRoles(dynamicRoles);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("workerremoveelement.qml"));
- QQuickItem *item = createWorkerTest(&eng, &component, model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&eng, &component, model.get());
+ QVERIFY(item);
- QVERIFY(QMetaObject::invokeMethod(item, "addItem"));
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "addItem"));
QCOMPARE(model->count(), 1);
- QVERIFY(QMetaObject::invokeMethod(item, "removeItemViaWorker"));
- QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
- delete model;
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "removeItemViaWorker"));
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "doSync"));
+ model.reset();
qApp->processEvents(); //must not crash here
- waitForWorker(item);
-
- delete item;
+ waitForWorker(item.get());
}
}
@@ -745,31 +744,31 @@ void tst_qqmllistmodelworkerscript::worker_remove_list()
model.setDynamicRoles(dynamicRoles);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("workerremovelist.qml"));
- QQuickItem *item = createWorkerTest(&eng, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&eng, &component, &model);
+ QVERIFY(item);
QSignalSpy spyModelRemoved(&model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
QCOMPARE(model.count(), 0);
QCOMPARE(spyModelRemoved.size(), 0);
- QVERIFY(QMetaObject::invokeMethod(item, "addList"));
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "addList"));
QCOMPARE(model.count(), 1);
- QVERIFY(QMetaObject::invokeMethod(item, "removeListViaWorker"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "removeListViaWorker"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 1);
QCOMPARE(spyModelRemoved.size(), 0);
- QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "doSync"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 0);
QCOMPARE(spyModelRemoved.size(), 1);
- delete item;
+ item.reset();
qApp->processEvents();
}
@@ -792,8 +791,8 @@ void tst_qqmllistmodelworkerscript::dynamic_role()
model.setDynamicRoles(true);
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("model.qml"));
- QQuickItem *item = createWorkerTest(&engine, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&engine, &component, &model);
+ QVERIFY(item);
QQmlExpression preExp(engine.rootContext(), &model, preamble);
QCOMPARE(preExp.evaluate().toInt(), 0);
@@ -801,21 +800,22 @@ void tst_qqmllistmodelworkerscript::dynamic_role()
if (script[0] == QLatin1Char('{') && script[script.size()-1] == QLatin1Char('}'))
script = script.mid(1, script.size() - 2);
QVariantList operations;
- foreach (const QString &s, script.split(';')) {
+ const QStringList statements = script.split(';');
+ for (const QString &s : statements) {
if (!s.isEmpty())
operations << s;
}
// execute a set of commands on the worker list model, then check the
// changes are reflected in the list model in the main thread
- QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker",
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "evalExpressionViaWorker",
Q_ARG(QVariant, operations.mid(0, operations.size()-1))));
- waitForWorker(item);
+ waitForWorker(item.get());
QQmlExpression e(engine.rootContext(), &model, operations.last().toString());
QCOMPARE(e.evaluate().toInt(), result);
- delete item;
+ item.reset();
qApp->processEvents();
}
diff --git a/tests/auto/qml/qqmllistreference/CMakeLists.txt b/tests/auto/qml/qqmllistreference/CMakeLists.txt
index 3286531a45..0fa70259b2 100644
--- a/tests/auto/qml/qqmllistreference/CMakeLists.txt
+++ b/tests/auto/qml/qqmllistreference/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmllistreference Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmllistreference LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmllistreference/data/consoleLogSyntheticList.qml b/tests/auto/qml/qqmllistreference/data/consoleLogSyntheticList.qml
new file mode 100644
index 0000000000..9d2fd3e0b2
--- /dev/null
+++ b/tests/auto/qml/qqmllistreference/data/consoleLogSyntheticList.qml
@@ -0,0 +1,8 @@
+import QtQml
+
+QtObject {
+ id: self
+
+ function createList() : list<QtObject> { return [self] }
+ Component.onCompleted: console.log(createList())
+}
diff --git a/tests/auto/qml/qqmllistreference/data/listIgnoresNull.qml b/tests/auto/qml/qqmllistreference/data/listIgnoresNull.qml
new file mode 100644
index 0000000000..35c8d66dad
--- /dev/null
+++ b/tests/auto/qml/qqmllistreference/data/listIgnoresNull.qml
@@ -0,0 +1,21 @@
+import QtQuick 2.7
+import Test
+
+Item {
+ id: root
+
+ TestItem {
+ id: testItem
+ }
+
+ Component.onCompleted : {
+ testItem.data.push(null);
+ testItem.data.length = 5;
+ testItem.data.unshift(null);
+
+ var state = Qt.createQmlObject( "import QtQuick 2.7; State{ name: 'MyState' }", root, "dynamicState" );
+ root.states.length = 5;
+ root.states.push(null);
+ root.states.unshift(state);
+ }
+}
diff --git a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
index 049ffb2d72..76711a00e6 100644
--- a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
+++ b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QUrl>
@@ -58,6 +58,9 @@ private slots:
void jsArrayMethods();
void jsArrayMethodsWithParams_data();
void jsArrayMethodsWithParams();
+ void listIgnoresNull_data() { modeData(); }
+ void listIgnoresNull();
+ void consoleLogSyntheticList();
};
class TestType : public QObject
@@ -73,12 +76,18 @@ public:
SyntheticClearAndReplace,
SyntheticRemoveLast,
SyntheticRemoveLastAndReplace,
- AutomaticPointer
+ AutomaticPointer,
+ IgnoreNullValues,
};
static void append(QQmlListProperty<TestType> *p, TestType *v) {
reinterpret_cast<QList<TestType *> *>(p->data)->append(v);
}
+ static void appendNoNullValues(QQmlListProperty<TestType> *p, TestType *v) {
+ if (!v)
+ return;
+ reinterpret_cast<QList<TestType *> *>(p->data)->append(v);
+ }
static qsizetype count(QQmlListProperty<TestType> *p) {
return reinterpret_cast<QList<TestType *> *>(p->data)->size();
}
@@ -121,6 +130,10 @@ public:
case AutomaticPointer:
property = QQmlListProperty<TestType>(this, &data);
break;
+ case IgnoreNullValues:
+ property = QQmlListProperty<TestType>(this, &data, appendNoNullValues, count, at, clear,
+ replace, removeLast);
+ break;
}
}
@@ -142,6 +155,7 @@ void tst_qqmllistreference::modeData()
QTest::addRow("SyntheticClearAndReplace") << TestType::SyntheticClearAndReplace;
QTest::addRow("SyntheticRemoveLast") << TestType::SyntheticRemoveLast;
QTest::addRow("SyntheticRemoveLastAndReplace") << TestType::SyntheticRemoveLastAndReplace;
+ QTest::addRow("IgnoreNullValues") << TestType::IgnoreNullValues;
}
void tst_qqmllistreference::initTestCase()
@@ -1036,6 +1050,50 @@ void tst_qqmllistreference::jsArrayMethodsWithParams()
QCOMPARE(object->property("listPropertyLastIndexOf"), object->property("jsArrayLastIndexOf"));
}
+/*!
+ Some of our list implementations ignore attempts to append a null object.
+ This should result in warnings or type errors, and not crash our wrapper
+ code.
+*/
+void tst_qqmllistreference::listIgnoresNull()
+{
+ QFETCH(const TestType::Mode, mode);
+ static TestType::Mode globalMode;
+ globalMode = mode;
+ struct TestItem : public TestType
+ {
+ TestItem() : TestType(globalMode) {}
+ };
+
+ const auto id = qmlRegisterType<TestItem>("Test", 1, 0, "TestItem");
+ const auto unregister = qScopeGuard([id]{
+ QQmlPrivate::qmlunregister(QQmlPrivate::TypeRegistration, id);
+ });
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("listIgnoresNull.qml"));
+
+ // For lists that don't append null values, creating the component shouldn't crash
+ // in the onCompleted handler, but generate type errors and warnings.
+ if (mode == TestType::IgnoreNullValues) {
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".* QML TestItem: List didn't append all objects$"));
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".* TypeError: List doesn't append null objects$"));
+ }
+ QScopedPointer<QObject> object( component.create() );
+ QVERIFY(object != nullptr);
+}
+
+void tst_qqmllistreference::consoleLogSyntheticList()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("consoleLogSyntheticList.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QTest::ignoreMessage(
+ QtDebugMsg, QRegularExpression("\\[QObject_QML_[0-9]+\\(0x[0-9a-f]+\\)\\]"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+}
+
QTEST_MAIN(tst_qqmllistreference)
#include "tst_qqmllistreference.moc"
diff --git a/tests/auto/qml/qqmllocale/CMakeLists.txt b/tests/auto/qml/qqmllocale/CMakeLists.txt
index 8603fe454d..beca01f955 100644
--- a/tests/auto/qml/qqmllocale/CMakeLists.txt
+++ b/tests/auto/qml/qqmllocale/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmllocale Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmllocale LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
index 3349f5f9b6..a7ddf79ad5 100644
--- a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
+++ b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
@@ -1,9 +1,11 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
+#include <private/qqmllocale_p.h>
+
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlcomponent.h>
@@ -457,9 +459,10 @@ void tst_qqmllocale::toString_data()
const QDateTime midnight2000(QDate(2000, 1, 1), QTime(0, 0));
// 12 AM might not exist in this timezone (some timezones have transitions at midnight).
if (midnight2000.isValid()) {
- functionCallScript = "locale.toString(new Date(2000, 1, 1))";
- QTest::newRow(qPrintable(functionCallScript)) << "en_AU" << functionCallScript
- << QLatin1String("Tuesday, 1 February 2000 12:00:00 AM ") + midnight2000.timeZoneAbbreviation() << QString();
+ functionCallScript = "locale.toString(new Date(2000, 0, 1))";
+ const QLocale locale("en_AU");
+ QTest::newRow(qPrintable(functionCallScript)) << locale.name() << functionCallScript
+ << locale.toString(midnight2000, QLocale::LongFormat) << QString();
}
functionCallScript = "locale.toString(new Date(2022, 7, 16), [])";
@@ -475,10 +478,12 @@ void tst_qqmllocale::toString_data()
QTest::newRow(qPrintable(functionCallScript)) << "ar" << functionCallScript << "١٦" << QString();
functionCallScript = "locale.toString(new Date(2022, 7, 16), Locale.ShortFormat)";
- QTest::newRow(qPrintable(functionCallScript)) << "en_AU" << functionCallScript << "16/8/22 12:00 AM" << QString();
+ QTest::newRow(qPrintable(functionCallScript))
+ << "en_AU" << functionCallScript << "16/8/22 12:00 am" << QString();
functionCallScript = "locale.toString(new Date(2022, 7, 16, 1, 23, 4), Locale.ShortFormat)";
- QTest::newRow(qPrintable(functionCallScript)) << "en_AU" << functionCallScript << "16/8/22 1:23 AM" << QString();
+ QTest::newRow(qPrintable(functionCallScript))
+ << "en_AU" << functionCallScript << "16/8/22 1:23 am" << QString();
}
void tst_qqmllocale::toString()
@@ -544,7 +549,7 @@ void tst_qqmllocale::weekDays()
Q_ARG(QVariant, QVariant(locale)));
QVariant val = obj->property("weekDays");
- QCOMPARE(val.userType(), qMetaTypeId<QJSValue>());
+ QCOMPARE(val.metaType(), QMetaType::fromType<QList<QQmlLocale::DayOfWeek>>());
QList<QVariant> qmlDays = val.toList();
QList<Qt::DayOfWeek> days = QLocale(locale).weekdays();
@@ -584,7 +589,7 @@ void tst_qqmllocale::uiLanguages()
Q_ARG(QVariant, QVariant(locale)));
QVariant val = obj->property("uiLanguages");
- QCOMPARE(val.userType(), qMetaTypeId<QJSValue>());
+ QCOMPARE(val.metaType(), QMetaType::fromType<QStringList>());
QList<QVariant> qmlLangs = val.toList();
QStringList langs = QLocale(locale).uiLanguages();
@@ -763,7 +768,15 @@ void tst_qqmllocale::testFunctionCall()
STOP_ON_FAILURE
QVERIFY(evaluationResult.canConvert<QString>());
STOP_ON_FAILURE
- QCOMPARE(evaluationResult.toString(), expectedResult);
+
+ // We're not interested in whether the spaces in the date/time format
+ // are breaking or non-breaking.
+ const QString resultWithBreakingSpaces
+ = evaluationResult.toString().replace(u'\u202f', u' ');
+ const QString expectedWithBreakingSpaces
+ = expectedResult.replace(u'\u202f', u' ');
+
+ QCOMPARE(resultWithBreakingSpaces, expectedWithBreakingSpaces);
STOP_ON_FAILURE
} else {
QVERIFY(qmlExpression.hasError());
diff --git a/tests/auto/qml/qqmlmetaobject/CMakeLists.txt b/tests/auto/qml/qqmlmetaobject/CMakeLists.txt
index 9895bb04fb..6f77e030e6 100644
--- a/tests/auto/qml/qqmlmetaobject/CMakeLists.txt
+++ b/tests/auto/qml/qqmlmetaobject/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlmetaobject Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlmetaobject LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
index d945f460eb..0516140667 100644
--- a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
+++ b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtCore/QScopedPointer>
diff --git a/tests/auto/qml/qqmlmetatype/CMakeLists.txt b/tests/auto/qml/qqmlmetatype/CMakeLists.txt
index 7a5b47b571..2ab974ca91 100644
--- a/tests/auto/qml/qqmlmetatype/CMakeLists.txt
+++ b/tests/auto/qml/qqmlmetatype/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlmetatype Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlmetatype LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlmetatype/data/Components/App.qml b/tests/auto/qml/qqmlmetatype/data/Components/App.qml
index 57b2b4520a..693cffea40 100644
--- a/tests/auto/qml/qqmlmetatype/data/Components/App.qml
+++ b/tests/auto/qml/qqmlmetatype/data/Components/App.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.0
diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
index c1bac33d87..04c2a5bfdb 100644
--- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
+++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qstandardpaths.h>
#include <qtest.h>
@@ -51,6 +51,9 @@ private slots:
void enumsInRecursiveImport();
void revertValueTypeAnimation();
+
+ void clearPropertyCaches();
+ void builtins();
};
class TestType : public QObject
@@ -724,6 +727,115 @@ void tst_qqmlmetatype::revertValueTypeAnimation()
QCOMPARE(o->property("pointSize").toDouble(), 12.0);
}
+void tst_qqmlmetatype::clearPropertyCaches()
+{
+ qmlClearTypeRegistrations();
+ qmlRegisterType<TestType>("ClearPropertyCaches", 1, 0, "A");
+ QQmlPropertyCache::ConstPtr oldCache = QQmlMetaType::propertyCache(&TestType::staticMetaObject);
+ QVERIFY(oldCache);
+ qmlClearTypeRegistrations();
+ qmlRegisterType<TestType>("ClearPropertyCaches", 1, 0, "B");
+ QQmlPropertyCache::ConstPtr newCache = QQmlMetaType::propertyCache(&TestType::staticMetaObject);
+ QVERIFY(oldCache.data() != newCache.data());
+}
+
+template<typename T>
+void checkBuiltinBaseType()
+{
+ const QQmlType type = QQmlMetaType::qmlType(QMetaType::fromType<T>());
+ QVERIFY(type.isValid());
+ QCOMPARE(type.typeId(), QMetaType::fromType<T>());
+ QCOMPARE(type.qListTypeId(), QMetaType::fromType<QList<T>>());
+}
+
+template<typename T>
+void checkBuiltinListType()
+{
+ const QQmlType listType = QQmlMetaType::qmlListType(QMetaType::fromType<QList<T>>());
+ QVERIFY(listType.isValid());
+ QVERIFY(listType.isSequentialContainer());
+ QCOMPARE(listType.typeId(), QMetaType::fromType<T>());
+ QCOMPARE(listType.qListTypeId(), QMetaType::fromType<QList<T>>());
+ QCOMPARE(listType.listMetaSequence().valueMetaType(), QMetaType::fromType<T>());
+}
+
+template<typename... T>
+void checkBuiltinTypes()
+{
+ (checkBuiltinBaseType<T>(), ...);
+ (checkBuiltinListType<T>(), ...);
+}
+
+template<typename T>
+void checkNamedBuiltin(const QString &name)
+{
+ const QQmlType expected = QQmlMetaType::qmlType(QMetaType::fromType<T>());
+ const QQmlType actual = QQmlMetaType::qmlType("QML/" + name, QTypeRevision::fromVersion(1, 0));
+ if (actual != expected) {
+ qWarning() << Q_FUNC_INFO << "looking for" << name;
+ qWarning() << "found" << actual.module() << actual.elementName() << actual.version()
+ << actual.typeId();
+ qWarning() << "expected" << expected.module() << expected.elementName()
+ << expected.version() << expected.typeId();
+ QFAIL("mismatch");
+ }
+}
+
+template<typename T>
+void checkObjectBuiltin(const QString &name)
+{
+ const QQmlType objectType = QQmlMetaType::qmlType(QMetaType::fromType<T *>());
+ QVERIFY(objectType.isValid());
+ QCOMPARE(objectType.typeId(), QMetaType::fromType<T *>());
+ QCOMPARE(objectType.qListTypeId(), QMetaType::fromType<QQmlListProperty<T>>());
+
+ const QQmlType listType = QQmlMetaType::qmlListType(QMetaType::fromType<QQmlListProperty<T>>());
+ QVERIFY(listType.isValid());
+ QCOMPARE(listType.typeId(), QMetaType::fromType<T *>());
+ QCOMPARE(listType.qListTypeId(), QMetaType::fromType<QQmlListProperty<T>>());
+
+ checkNamedBuiltin<T *>(name);
+}
+
+void tst_qqmlmetatype::builtins()
+{
+ qmlClearTypeRegistrations();
+ QQmlEngine engine; // registers the builtins
+
+ checkBuiltinTypes<
+ QVariant, QJSValue, qint8, quint8, short, ushort, int, uint, qlonglong, qulonglong, float,
+ double, QChar, QString, bool, QDateTime, QDate, QTime, QUrl, QByteArray>();
+
+ checkNamedBuiltin<QVariant>("var");
+ checkNamedBuiltin<QVariant>("variant");
+ checkNamedBuiltin<int>("int");
+ checkNamedBuiltin<double>("double");
+ checkNamedBuiltin<double>("real");
+ checkNamedBuiltin<QString>("string");
+ checkNamedBuiltin<bool>("bool");
+ checkNamedBuiltin<QDateTime>("date");
+ checkNamedBuiltin<QUrl>("url");
+
+#if QT_CONFIG(regularexpression)
+ checkBuiltinBaseType<QRegularExpression>();
+ checkBuiltinListType<QRegularExpression>();
+ checkNamedBuiltin<QRegularExpression>("regexp");
+#endif
+
+ // Can't retrieve this one by metatype
+ const QQmlType voidType = QQmlMetaType::qmlType("QML/void", QTypeRevision::fromVersion(1, 0));
+ QVERIFY(voidType.isValid());
+ QCOMPARE(voidType.typeId(), QMetaType());
+ QCOMPARE(voidType.qListTypeId(), QMetaType());
+
+ // No separate list types
+ checkBuiltinBaseType<std::nullptr_t>();
+ checkBuiltinBaseType<QVariantMap>();
+
+ checkObjectBuiltin<QObject>("QtObject");
+ checkObjectBuiltin<QQmlComponent>("Component");
+}
+
QTEST_MAIN(tst_qqmlmetatype)
#include "tst_qqmlmetatype.moc"
diff --git a/tests/auto/qml/qqmlmoduleplugin/CMakeLists.txt b/tests/auto/qml/qqmlmoduleplugin/CMakeLists.txt
index 1d536afd24..4508ae3986 100644
--- a/tests/auto/qml/qqmlmoduleplugin/CMakeLists.txt
+++ b/tests/auto/qml/qqmlmoduleplugin/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlmoduleplugin Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlmoduleplugin LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt b/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt
index ee68ebdfe0..56373ba3f4 100644
--- a/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt
+++ b/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt
@@ -1,2 +1,2 @@
1:-1:a component declaration requires two or three arguments, but 4 were provided
-2:-1:internal types require 2 arguments, but 3 were provided
+2:-1:invalid version bar, expected <major>.<minor>
diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp
index b97fdf7cff..c60161f424 100644
--- a/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp
index cecc074946..000a75375f 100644
--- a/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp
index 5922ca34f5..5ffd28dcbb 100644
--- a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp b/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp
index 4400c11996..858b2b4704 100644
--- a/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp
index 8f20900838..00be65b599 100644
--- a/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/optionalPlugin/optionalPlugin.cpp b/tests/auto/qml/qqmlmoduleplugin/optionalPlugin/optionalPlugin.cpp
index 9d8c110db6..519b567c1d 100644
--- a/tests/auto/qml/qqmlmoduleplugin/optionalPlugin/optionalPlugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/optionalPlugin/optionalPlugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp
index 9b54f3946a..7061c5a8c1 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp
index eaa76e08d4..0ca3603267 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.cpp
index d5906611b7..c97824112e 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp
index db158e6b6d..1ac6e8902f 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp
index f1043b4b72..4dbc3c15bb 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp
index 410d2c483a..3e5ae31d62 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp
index 2142ac604d..dcf9ed676a 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp
index c9cd28fc83..84b795d165 100644
--- a/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp
index 698e5f2692..26d9977f7d 100644
--- a/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp
index e49d1c1a28..c8620cbe5e 100644
--- a/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp
index 96d01191fd..3e4987f9b1 100644
--- a/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp
index 4383325d93..40eebfe3bb 100644
--- a/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp
index 3e851c1df3..644719cebf 100644
--- a/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp
index d8de79dcfd..590f10dced 100644
--- a/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
#include <QDebug>
diff --git a/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp
index ef55650a31..160f8f5ac6 100644
--- a/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp
index d50de5242c..39f7f86acf 100644
--- a/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
index a4901aebad..67e1591b8b 100644
--- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <qdir.h>
#include <QtQml/qqmlengine.h>
@@ -16,7 +17,7 @@
#include <QtQuickShapes/private/qquickshapesglobal_p.h>
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
// For _PC_CASE_SENSITIVE
#include <unistd.h>
#endif
@@ -130,7 +131,9 @@ void registerStaticPlugin(const char *uri)
PluginType::metaData.append(char(QT_VERSION_MAJOR));
PluginType::metaData.append(char(QT_VERSION_MINOR));
PluginType::metaData.append(char(qPluginArchRequirements()));
+#if QT_CONFIG(cborstreamwriter)
PluginType::metaData.append(QCborValue(QCborMap::fromJsonObject(md)).toCbor());
+#endif
auto rawMetaDataFunctor = []() -> QPluginMetaData {
return {reinterpret_cast<const uchar *>(PluginType::metaData.constData()), size_t(PluginType::metaData.size())};
@@ -207,13 +210,13 @@ void tst_qqmlmoduleplugin::importsPlugin()
QTest::ignoreMessage(QtWarningMsg, qPrintable(QString("import%1 worked").arg(suffix)));
QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType' does not contain a module identifier directive - it cannot be protected from external registrations.");
QQmlComponent component(&engine, testFileUrl(qmlFile));
- foreach (QQmlError err, component.errors())
+ const auto errors = component.errors();
+ for (const QQmlError &err : errors)
qWarning() << err;
VERIFY_ERRORS(0);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
QCOMPARE(object->property("value").toInt(),123);
- delete object;
}
void tst_qqmlmoduleplugin::importsPlugin_data()
@@ -239,9 +242,9 @@ void tst_qqmlmoduleplugin::incorrectPluginCase()
QString expectedError = QLatin1String("module \"org.qtproject.WrongCase\" plugin \"PluGin\" not found");
-#if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
+#if defined(Q_OS_DARWIN) || defined(Q_OS_WIN32)
bool caseSensitive = true;
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
int res = pathconf(QDir::currentPath().toLatin1().constData(), _PC_CASE_SENSITIVE);
if (res == -1)
QSKIP("Could not establish case sensitivity of file system");
@@ -282,12 +285,12 @@ void tst_qqmlmoduleplugin::importPluginWithQmlFile()
QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestPluginWithQmlFile' does not contain a module identifier directive - it cannot be protected from external registrations.");
QQmlComponent component(&engine, testFileUrl(QStringLiteral("pluginWithQmlFile.qml")));
- foreach (QQmlError err, component.errors())
+ const auto errors = component.errors();
+ for (const QQmlError &err : errors)
qWarning() << err;
VERIFY_ERRORS(0);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
- delete object;
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
}
void tst_qqmlmoduleplugin::remoteImportWithQuotedUrl()
@@ -300,12 +303,12 @@ void tst_qqmlmoduleplugin::remoteImportWithQuotedUrl()
component.setData(qml.toUtf8(), QUrl());
QTRY_COMPARE(component.status(), QQmlComponent::Ready);
- QObject *object = component.create();
+ std::unique_ptr<QObject> object { component.create() };
QCOMPARE(object->property("width").toInt(), 300);
- QVERIFY(object != nullptr);
- delete object;
+ QVERIFY(object.get() != nullptr);
- foreach (QQmlError err, component.errors())
+ const auto errors = component.errors();
+ for (const QQmlError &err : errors)
qWarning() << err;
VERIFY_ERRORS(0);
}
@@ -323,12 +326,12 @@ void tst_qqmlmoduleplugin::remoteImportWithUnquotedUri()
QTRY_COMPARE(component.status(), QQmlComponent::Ready);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
QCOMPARE(object->property("width").toInt(), 300);
- delete object;
- foreach (QQmlError err, component.errors())
+ const auto errors = component.errors();
+ for (const QQmlError &err : errors)
qWarning() << err;
VERIFY_ERRORS(0);
}
@@ -368,20 +371,18 @@ void tst_qqmlmoduleplugin::importsMixedQmlCppPlugin()
{
QQmlComponent component(&engine, testFileUrl(QStringLiteral("importsMixedQmlCppPlugin.qml")));
- QObject *o = component.create();
- QVERIFY2(o != nullptr, msgComponentError(component, &engine));
+ std::unique_ptr<QObject> o { component.create() };
+ QVERIFY2(o.get() != nullptr, msgComponentError(component, &engine));
QCOMPARE(o->property("test").toBool(), true);
- delete o;
}
{
QQmlComponent component(&engine, testFileUrl(QStringLiteral("importsMixedQmlCppPlugin.2.qml")));
- QObject *o = component.create();
- QVERIFY2(o != nullptr, msgComponentError(component, &engine));
+ std::unique_ptr<QObject> o { component.create() };
+ QVERIFY2(o.get() != nullptr, msgComponentError(component, &engine));
QCOMPARE(o->property("test").toBool(), true);
QCOMPARE(o->property("test2").toBool(), true);
- delete o;
}
@@ -444,9 +445,8 @@ void tst_qqmlmoduleplugin::implicitQmldir()
QList<QQmlError> errors = component.errors();
VERIFY_ERRORS(errorFileName.toLatin1().constData());
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
- QObject *obj = component.create();
- QVERIFY(!obj);
- delete obj;
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(!obj.get());
}
void tst_qqmlmoduleplugin::importsNested_data()
@@ -481,17 +481,17 @@ void tst_qqmlmoduleplugin::importsNested()
QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlNestedPluginType' does not contain a module identifier directive - it cannot be protected from external registrations.");
QQmlComponent component(&engine, testFile(file));
- QObject *obj = component.create();
+ std::unique_ptr<QObject> obj { component.create() };
if (errorFile.isEmpty()) {
if (qgetenv("DEBUG") != "" && !component.errors().isEmpty())
qWarning() << "Unexpected Errors:" << component.errors();
- QVERIFY(obj);
- delete obj;
+ QVERIFY(obj.get());
+ obj.reset();
} else {
QList<QQmlError> errors = component.errors();
VERIFY_ERRORS(errorFile.toLatin1().constData());
- QVERIFY(!obj);
+ QVERIFY(!obj.get());
}
}
@@ -684,13 +684,13 @@ void tst_qqmlmoduleplugin::importsChildPlugin()
QTest::ignoreMessage(QtWarningMsg, "child import worked");
QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType.ChildPlugin' does not contain a module identifier directive - it cannot be protected from external registrations.");
QQmlComponent component(&engine, testFileUrl(QStringLiteral("child.qml")));
- foreach (QQmlError err, component.errors())
+ const auto errors = component.errors();
+ for (const QQmlError &err : errors)
qWarning() << err;
VERIFY_ERRORS(0);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
QCOMPARE(object->property("value").toInt(),123);
- delete object;
}
void tst_qqmlmoduleplugin::importsChildPlugin2()
@@ -701,13 +701,13 @@ void tst_qqmlmoduleplugin::importsChildPlugin2()
QTest::ignoreMessage(QtWarningMsg, "child import2 worked");
QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType.ChildPlugin' does not contain a module identifier directive - it cannot be protected from external registrations.");
QQmlComponent component(&engine, testFileUrl(QStringLiteral("child2.qml")));
- foreach (QQmlError err, component.errors())
+ const auto errors = component.errors();
+ for (const QQmlError &err : errors)
qWarning() << err;
VERIFY_ERRORS(0);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
QCOMPARE(object->property("value").toInt(),123);
- delete object;
}
void tst_qqmlmoduleplugin::importsChildPlugin21()
@@ -718,13 +718,13 @@ void tst_qqmlmoduleplugin::importsChildPlugin21()
QTest::ignoreMessage(QtWarningMsg, "child import2.1 worked");
QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType.ChildPlugin' does not contain a module identifier directive - it cannot be protected from external registrations.");
QQmlComponent component(&engine, testFileUrl(QStringLiteral("child21.qml")));
- foreach (QQmlError err, component.errors())
+ const auto errors = component.errors();
+ for (const QQmlError &err : errors)
qWarning() << err;
VERIFY_ERRORS(0);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
QCOMPARE(object->property("value").toInt(),123);
- delete object;
}
void tst_qqmlmoduleplugin::parallelPluginImport()
@@ -780,10 +780,9 @@ void tst_qqmlmoduleplugin::multiSingleton()
engine.addImportPath(m_importsDirectory);
QQmlComponent component(&engine, testFileUrl("multiSingleton.qml"));
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
QCOMPARE(obj.objectName(), QLatin1String("first"));
- delete object;
}
void tst_qqmlmoduleplugin::optionalPlugin()
diff --git a/tests/auto/qml/qqmlnotifier/CMakeLists.txt b/tests/auto/qml/qqmlnotifier/CMakeLists.txt
index 44bd62ed9c..f91c1411e3 100644
--- a/tests/auto/qml/qqmlnotifier/CMakeLists.txt
+++ b/tests/auto/qml/qqmlnotifier/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlnotifier Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlnotifier LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp b/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
index e3171496d8..501aa472bc 100644
--- a/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
+++ b/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Research In Motion
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
#include <QQmlEngine>
diff --git a/tests/auto/qml/qqmlobjectmodel/CMakeLists.txt b/tests/auto/qml/qqmlobjectmodel/CMakeLists.txt
index c54e195b26..aea2cae6dd 100644
--- a/tests/auto/qml/qqmlobjectmodel/CMakeLists.txt
+++ b/tests/auto/qml/qqmlobjectmodel/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlobjectmodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlobjectmodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlobjectmodel
SOURCES
tst_qqmlobjectmodel.cpp
diff --git a/tests/auto/qml/qqmlobjectmodel/tst_qqmlobjectmodel.cpp b/tests/auto/qml/qqmlobjectmodel/tst_qqmlobjectmodel.cpp
index d007f4d024..95a05ebf44 100644
--- a/tests/auto/qml/qqmlobjectmodel/tst_qqmlobjectmodel.cpp
+++ b/tests/auto/qml/qqmlobjectmodel/tst_qqmlobjectmodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQmlModels/private/qqmlobjectmodel_p.h>
#include <QtQmlModels/private/qqmlchangeset_p.h>
#include <QtTest/qsignalspy.h>
diff --git a/tests/auto/qml/qqmlopenmetaobject/CMakeLists.txt b/tests/auto/qml/qqmlopenmetaobject/CMakeLists.txt
index f01d281ed3..b6ecc6bc0f 100644
--- a/tests/auto/qml/qqmlopenmetaobject/CMakeLists.txt
+++ b/tests/auto/qml/qqmlopenmetaobject/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlopenmetaobject Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlopenmetaobject LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlopenmetaobject
SOURCES
tst_qqmlopenmetaobject.cpp
diff --git a/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp b/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp
index 2432282f8c..a3ccda0a1a 100644
--- a/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp
+++ b/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <private/qqmlopenmetaobject_p.h>
diff --git a/tests/auto/qml/qqmlparser/CMakeLists.txt b/tests/auto/qml/qqmlparser/CMakeLists.txt
index 48e1a97f44..faa241bb5e 100644
--- a/tests/auto/qml/qqmlparser/CMakeLists.txt
+++ b/tests/auto/qml/qqmlparser/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlparser Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlparser LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
index adad96b864..62f67e548f 100644
--- a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
+++ b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <private/qqmljsengine_p.h>
#include <private/qqmljsparser_p.h>
@@ -34,6 +34,10 @@ private slots:
void codeLocationsWithContinuationStringLiteral_data();
void noSubstitutionTemplateLiteral();
void templateLiteral();
+ void numericSeparator_data();
+ void numericSeparator();
+ void invalidNumericSeparator_data();
+ void invalidNumericSeparator();
void leadingSemicolonInClass();
void templatedReadonlyProperty();
void qmlImportInJS();
@@ -243,15 +247,13 @@ QStringList tst_qqmlparser::findFiles(const QDir &d)
QStringList rv;
- QStringList files = d.entryList(QStringList() << QLatin1String("*.qml") << QLatin1String("*.js"),
- QDir::Files);
- foreach (const QString &file, files) {
+ const QStringList files = d.entryList(
+ QStringList() << QLatin1String("*.qml") << QLatin1String("*.js"), QDir::Files);
+ for (const QString &file : files)
rv << d.absoluteFilePath(file);
- }
- QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
- QDir::NoSymLinks);
- foreach (const QString &dir, dirs) {
+ const QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
+ for (const QString &dir : dirs) {
QDir sub = d;
sub.cd(dir);
rv << findFiles(sub);
@@ -277,7 +279,7 @@ void tst_qqmlparser::qmlParser_data()
files << findFiles(QDir(examples));
files << findFiles(QDir(tests));
- foreach (const QString &file, files)
+ for (const QString &file : std::as_const(files))
QTest::newRow(qPrintable(file)) << file;
}
#endif
@@ -498,6 +500,74 @@ void tst_qqmlparser::templateLiteral()
QVERIFY(e);
}
+void tst_qqmlparser::numericSeparator_data() {
+ QTest::addColumn<QString>("code");
+ QTest::addColumn<double>("expected_value");
+
+ QTest::newRow("Separator in decimal literal") << "1_000_000_000" << 1000000000.0;
+ QTest::newRow("Separator in fractional part") << "1000.22_33" << 1000.2233;
+ QTest::newRow("Separator in exponent part") << "1e1_0_0" << std::pow(10, 100);
+ QTest::newRow("Separator in positive exponent part") << "1e+1_0_0" << 1e100;
+ QTest::newRow("Separator in negative exponent part") << "1e-1_0_0" << 1e-100;
+ QTest::newRow("Separator in binary literal with b prefix") << "0b1010_0001_1000_0101" << static_cast<double>(0b1010000110000101);
+ QTest::newRow("Separator in binary literal with B prefix") << "0B01_10_01_10" << static_cast<double>(0b01100110);
+ QTest::newRow("Separator in octal literal with o prefix") << "0o1234_5670" << static_cast<double>(012345670);
+ QTest::newRow("Separator in octal literal with O prefix") << "0O7777_0000" << static_cast<double>(077770000);
+ QTest::newRow("Separator in hex literal with x prefix") << "0xA0_B0_C0" << static_cast<double>(0xA0B0C0);
+ QTest::newRow("Separator in hex literal with X prefix") << "0X1000_AAAA" << static_cast<double>(0x1000AAAA);
+}
+
+void tst_qqmlparser::numericSeparator() {
+ using namespace QQmlJS;
+
+ QFETCH(QString, code);
+ QFETCH(double, expected_value);
+
+ QQmlJS::Engine engine;
+
+ QQmlJS::Lexer lexer(&engine);
+ lexer.setCode(code, 1);
+
+ QQmlJS::Parser parser(&engine);
+ QVERIFY(parser.parseExpression());
+
+ AST::ExpressionNode *expression = parser.expression();
+ QVERIFY(expression);
+
+ auto *literal = QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(expression);
+ QVERIFY(literal);
+
+ QCOMPARE(literal->value, expected_value);
+ QCOMPARE(literal->firstSourceLocation().begin(), 0u);
+ QCOMPARE(literal->lastSourceLocation().end(), quint32(code.size()));
+}
+
+void tst_qqmlparser::invalidNumericSeparator_data() {
+ QTest::addColumn<QString>("code");
+ QTest::addColumn<QString>("error");
+
+ QTest::newRow("Trailing numeric separator") << "1_" << "A trailing numeric separator is not allowed in numeric literals";
+ QTest::newRow("Multiple numeric separators") << "1__2" << "There can be at most one numeric separator between digits";
+}
+
+void tst_qqmlparser::invalidNumericSeparator() {
+ using namespace QQmlJS;
+
+ QFETCH(QString, code);
+ QFETCH(QString, error);
+
+ QQmlJS::Engine engine;
+
+ QQmlJS::Lexer lexer(&engine);
+ lexer.setCode(code, 1);
+
+ QQmlJS::Parser parser(&engine);
+ QVERIFY(!parser.parseExpression());
+
+ QVERIFY(lexer.errorCode() != Lexer::NoError);
+ QCOMPARE(lexer.errorMessage(), error);
+}
+
void tst_qqmlparser::leadingSemicolonInClass()
{
QQmlJS::Engine engine;
diff --git a/tests/auto/qml/qqmlpromise/CMakeLists.txt b/tests/auto/qml/qqmlpromise/CMakeLists.txt
index b12da35bab..749963fc12 100644
--- a/tests/auto/qml/qqmlpromise/CMakeLists.txt
+++ b/tests/auto/qml/qqmlpromise/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlpromise Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlpromise LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlpromise/data/promise-all-empty-input.qml b/tests/auto/qml/qqmlpromise/data/promise-all-empty-input.qml
index 18e141f787..9846777d97 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-all-empty-input.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-all-empty-input.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-all-invoke-then-method.qml b/tests/auto/qml/qqmlpromise/data/promise-all-invoke-then-method.qml
index be6651a3c3..103263aca6 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-all-invoke-then-method.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-all-invoke-then-method.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-all-noniterable-input.qml b/tests/auto/qml/qqmlpromise/data/promise-all-noniterable-input.qml
index 1345fbc6d7..8f0ce78006 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-all-noniterable-input.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-all-noniterable-input.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-last.qml b/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-last.qml
index 380026c485..eef8065713 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-last.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-last.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-mid.qml b/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-mid.qml
index e4bee826fa..b3be71243e 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-mid.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-mid.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-all-resolve.qml b/tests/auto/qml/qqmlpromise/data/promise-all-resolve.qml
index 7088aa935c..d6c37bee1d 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-all-resolve.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-all-resolve.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-async-reject-with-value.qml b/tests/auto/qml/qqmlpromise/data/promise-async-reject-with-value.qml
index c924b476d9..9a5f2d0331 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-async-reject-with-value.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-async-reject-with-value.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-async-resolve-with-value.qml b/tests/auto/qml/qqmlpromise/data/promise-async-resolve-with-value.qml
index c7d9536bdb..7767aa49eb 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-async-resolve-with-value.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-async-resolve-with-value.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-executor-function-extensible.qml b/tests/auto/qml/qqmlpromise/data/promise-executor-function-extensible.qml
index e494983ae6..f8e5a3c32c 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-executor-function-extensible.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-executor-function-extensible.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-executor-reject.qml b/tests/auto/qml/qqmlpromise/data/promise-executor-reject.qml
index 541b884303..321506c483 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-executor-reject.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-executor-reject.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-executor-resolve.qml b/tests/auto/qml/qqmlpromise/data/promise-executor-resolve.qml
index baafee07a1..800db1144c 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-executor-resolve.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-executor-resolve.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-executor-throw-exception.qml b/tests/auto/qml/qqmlpromise/data/promise-executor-throw-exception.qml
index 806d276f51..22f066b2bd 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-executor-throw-exception.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-executor-throw-exception.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-get-length.qml b/tests/auto/qml/qqmlpromise/data/promise-get-length.qml
index 96d48b42fb..cf0648025b 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-get-length.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-get-length.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-race-empty-input.qml b/tests/auto/qml/qqmlpromise/data/promise-race-empty-input.qml
index 454930f06b..c6e9dce72b 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-race-empty-input.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-race-empty-input.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st-in-executor-function.qml b/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st-in-executor-function.qml
index 84f85f19dc..76d344eb3b 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st-in-executor-function.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st-in-executor-function.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st.qml b/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st.qml
index b537af12a3..847911cc9f 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-race-resolve-2nd.qml b/tests/auto/qml/qqmlpromise/data/promise-race-resolve-2nd.qml
index 498c3fa778..d7d5fbd06e 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-race-resolve-2nd.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-race-resolve-2nd.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-reject-catch.qml b/tests/auto/qml/qqmlpromise/data/promise-reject-catch.qml
index 5dc5abcb27..003c2ef102 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-reject-catch.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-reject-catch.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-reject-with-value.qml b/tests/auto/qml/qqmlpromise/data/promise-reject-with-value.qml
index 6d09642842..30a08d5004 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-reject-with-value.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-reject-with-value.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-resolve-function-length.qml b/tests/auto/qml/qqmlpromise/data/promise-resolve-function-length.qml
index 46700fe77e..88005b62e6 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-resolve-function-length.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-resolve-function-length.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-resolve-is-a-function.qml b/tests/auto/qml/qqmlpromise/data/promise-resolve-is-a-function.qml
index 383c827741..1327d91e5f 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-resolve-is-a-function.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-resolve-is-a-function.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-array.qml b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-array.qml
index 7d31972633..f71000d0dd 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-array.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-array.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-empty.qml b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-empty.qml
index aefe25bfc1..1571b3a837 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-empty.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-empty.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-promise.qml b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-promise.qml
index 7ba5352431..62b70828fd 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-promise.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-promise.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-value.qml b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-value.qml
index 52842dde76..08cb4d62df 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-value.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-value.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/then-fulfilled-non-callable.qml b/tests/auto/qml/qqmlpromise/data/then-fulfilled-non-callable.qml
index 07d607ca99..eaa5c89717 100644
--- a/tests/auto/qml/qqmlpromise/data/then-fulfilled-non-callable.qml
+++ b/tests/auto/qml/qqmlpromise/data/then-fulfilled-non-callable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/then-reject-chaining.qml b/tests/auto/qml/qqmlpromise/data/then-reject-chaining.qml
index 876a953b7e..be31f1a4f2 100644
--- a/tests/auto/qml/qqmlpromise/data/then-reject-chaining.qml
+++ b/tests/auto/qml/qqmlpromise/data/then-reject-chaining.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/then-reject-non-callable.qml b/tests/auto/qml/qqmlpromise/data/then-reject-non-callable.qml
index 37c046d823..908149b1e6 100644
--- a/tests/auto/qml/qqmlpromise/data/then-reject-non-callable.qml
+++ b/tests/auto/qml/qqmlpromise/data/then-reject-non-callable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/then-resolve-chaining.qml b/tests/auto/qml/qqmlpromise/data/then-resolve-chaining.qml
index bb525fab7b..780e75660f 100644
--- a/tests/auto/qml/qqmlpromise/data/then-resolve-chaining.qml
+++ b/tests/auto/qml/qqmlpromise/data/then-resolve-chaining.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/then-resolve-multiple-then.qml b/tests/auto/qml/qqmlpromise/data/then-resolve-multiple-then.qml
index 7075fc8a41..778bd085d8 100644
--- a/tests/auto/qml/qqmlpromise/data/then-resolve-multiple-then.qml
+++ b/tests/auto/qml/qqmlpromise/data/then-resolve-multiple-then.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp b/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp
index 2e00729dbc..c6c7767d44 100644
--- a/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp
+++ b/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QString>
#include <QtTest>
#include <QQmlEngine>
diff --git a/tests/auto/qml/qqmlproperty/CMakeLists.txt b/tests/auto/qml/qqmlproperty/CMakeLists.txt
index 0d41159fb3..7148289318 100644
--- a/tests/auto/qml/qqmlproperty/CMakeLists.txt
+++ b/tests/auto/qml/qqmlproperty/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlproperty Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlproperty LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlproperty/data/invalidateQPropertyChangeTriggers.qml b/tests/auto/qml/qqmlproperty/data/invalidateQPropertyChangeTriggers.qml
new file mode 100644
index 0000000000..bfa832c1c8
--- /dev/null
+++ b/tests/auto/qml/qqmlproperty/data/invalidateQPropertyChangeTriggers.qml
@@ -0,0 +1,50 @@
+import QtQml
+
+QtObject {
+ id: root
+ objectName: column.text
+
+ property Component c: Component {
+ id: comp
+ QtObject { }
+ }
+
+ property QtObject rectItem: null
+
+ property bool running: false
+
+ property Timer t: Timer {
+ id: column
+ interval: 200
+ running: root.running
+ repeat: true
+
+ property string text: {
+ let item = root.rectItem
+ let result = rectItem ? rectItem.objectName : "Create Object"
+ return result
+ }
+
+ onTriggered: {
+ let rectItem = root.rectItem
+
+ // If rectItem exists destory it.
+ if (rectItem) {
+ rectItem.destroy()
+ return
+ }
+
+ // Otherwise create a new object
+ let newRectItem = comp.createObject(column, {})
+
+
+ // Setting the objectName before setting root.rectItem seems to work.
+ // newRectItem.width = 1200
+ root.rectItem = newRectItem
+
+ // But setting the objectName after setting root.rectItem seems to
+ // cause the issue.
+ newRectItem.objectName = "1300"
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlproperty/data/listAssignmentSignals.qml b/tests/auto/qml/qqmlproperty/data/listAssignmentSignals.qml
new file mode 100644
index 0000000000..8a2c68ab5d
--- /dev/null
+++ b/tests/auto/qml/qqmlproperty/data/listAssignmentSignals.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.0
+
+Item {
+ property int signalCounter: 0
+ property list<QtObject> sourceList: [ QtObject{}, QtObject{}, QtObject{} ]
+ property list<QtObject> targetList1: sourceList
+
+ onTargetList1Changed: signalCounter++
+
+ function assignList() {
+ targetList1 = sourceList
+ }
+}
diff --git a/tests/auto/qml/qqmlproperty/data/propertyStartsWithOn.qml b/tests/auto/qml/qqmlproperty/data/propertyStartsWithOn.qml
new file mode 100644
index 0000000000..0ced54a9ca
--- /dev/null
+++ b/tests/auto/qml/qqmlproperty/data/propertyStartsWithOn.qml
@@ -0,0 +1,9 @@
+import QtQml
+
+QtObject {
+ id: root
+ property int onlineStatus
+ property Binding b: Binding {
+ root.onlineStatus: 12
+ }
+}
diff --git a/tests/auto/qml/qqmlproperty/interfaces.h b/tests/auto/qml/qqmlproperty/interfaces.h
index 7ca15214d4..e8f08d06fc 100644
--- a/tests/auto/qml/qqmlproperty/interfaces.h
+++ b/tests/auto/qml/qqmlproperty/interfaces.h
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef INTERFACES_H
#define INTERFACES_H
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index 88c34f0e22..2635af705b 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "interfaces.h"
#include <qtest.h>
@@ -30,8 +30,15 @@ class MyQmlObject : public QObject
{
Q_OBJECT
Q_PROPERTY(QPoint pointProperty MEMBER m_point)
+ Q_PROPERTY(QString a READ objectName NOTIFY somethingHappened)
+ Q_PROPERTY(QString b READ objectName NOTIFY somethingHappened)
public:
- MyQmlObject(QObject *parent = nullptr) : QObject(parent) {}
+ MyQmlObject(QObject *parent = nullptr) : QObject(parent) {
+ connect(this, &QObject::objectNameChanged, this, &MyQmlObject::somethingHappened);
+ }
+
+signals:
+ void somethingHappened();
private:
QPoint m_point;
@@ -217,6 +224,13 @@ private slots:
void bindToNonQObjectTarget();
void assignVariantList();
+
+ void listAssignmentSignals();
+
+ void invalidateQPropertyChangeTriggers();
+
+ void propertyStartsWithOn();
+
private:
QQmlEngine engine;
};
@@ -355,6 +369,7 @@ void tst_qqmlproperty::registeredCompositeTypeProperty()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("registeredCompositeTypeProperty.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
QScopedPointer<QObject> obj(component.create());
QVERIFY(obj);
@@ -2416,9 +2431,13 @@ void tst_qqmlproperty::initFlags_data()
const QString names[] = {
QStringLiteral("foo"),
+ QStringLiteral("aChanged"),
QStringLiteral("self.foo"),
+ QStringLiteral("self.aChanged"),
QStringLiteral("onFoo"),
+ QStringLiteral("onAChanged"),
QStringLiteral("self.onFoo"),
+ QStringLiteral("self.onAChanged"),
QStringLiteral("bar"),
QStringLiteral("self.bar"),
QStringLiteral("abar"),
@@ -2453,15 +2472,15 @@ void tst_qqmlproperty::initFlags()
QQmlEngine engine;
QQmlComponent c(&engine);
c.setData(R"(
- import QtQml
- QtObject {
+ import Test
+ MyQmlObject {
id: self
signal foo()
property int bar: 12
property alias abar: self.bar
}
)", QUrl());
- QVERIFY(c.isReady());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(!o.isNull());
@@ -2471,7 +2490,9 @@ void tst_qqmlproperty::initFlags()
passObject ? o.data() : nullptr, name, context, flags);
const bool usesId = name.startsWith(QStringLiteral("self."));
- const bool hasSignal = name.endsWith(QStringLiteral("foo"));
+ const bool hasSignal = name.endsWith(QStringLiteral("foo"))
+ || name.endsWith(QStringLiteral("aChanged"));
+
if (!passObject && !usesId) {
QVERIFY(!property.isValid());
} else if (passObject && usesId) {
@@ -2486,10 +2507,14 @@ void tst_qqmlproperty::initFlags()
QVERIFY(property.isProperty());
QCOMPARE(property.name(), usesId ? name.mid(strlen("self.")) : name);
QCOMPARE(property.propertyMetaType(), QMetaType::fromType<int>());
- } else {
+ } else if (name.endsWith(QStringLiteral("oo"))) { // 'onFoo' or 'foo'
QVERIFY(property.isSignalProperty());
QCOMPARE(property.name(), QStringLiteral("onFoo"));
QVERIFY(!property.propertyMetaType().isValid());
+ } else {
+ QVERIFY(property.isSignalProperty());
+ QCOMPARE(property.name(), QStringLiteral("onSomethingHappened"));
+ QVERIFY(!property.propertyMetaType().isValid());
}
}
@@ -2544,6 +2569,58 @@ void tst_qqmlproperty::assignVariantList()
QCOMPARE(holder->doubleList(), doubleList);
}
+void tst_qqmlproperty::listAssignmentSignals()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("listAssignmentSignals.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
+
+ QCOMPARE(root->property("signalCounter").toInt(), 1);
+ QMetaObject::invokeMethod(root.get(), "assignList");
+ QCOMPARE(root->property("signalCounter").toInt(), 2);
+}
+
+void tst_qqmlproperty::invalidateQPropertyChangeTriggers()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("invalidateQPropertyChangeTriggers.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
+
+ QStringList names;
+ QObject::connect(root.data(), &QObject::objectNameChanged, [&](const QString &name) {
+ if (names.length() == 10)
+ root->setProperty("running", false);
+ else
+ names.append(name);
+ });
+
+ root->setProperty("running", true);
+ QTRY_VERIFY(!root->property("running").toBool());
+
+ QCOMPARE(names, (QStringList {
+ u""_s, u"1300"_s, u"Create Object"_s,
+ u""_s, u"1300"_s, u"Create Object"_s,
+ u""_s, u"1300"_s, u"Create Object"_s,
+ u""_s
+ }));
+}
+
+void tst_qqmlproperty::propertyStartsWithOn()
+{
+ QTest::failOnWarning("\"onlineStatus\" is not a properly capitalized signal handler name. "
+ "\"onLineStatus\" would be correct.");
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("propertyStartsWithOn.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
+ QCOMPARE(root->property("onlineStatus").toInt(), 12);
+}
+
QTEST_MAIN(tst_qqmlproperty)
#include "tst_qqmlproperty.moc"
diff --git a/tests/auto/qml/qqmlpropertycache/CMakeLists.txt b/tests/auto/qml/qqmlpropertycache/CMakeLists.txt
index 8a7ffd2d9d..6dcb042dab 100644
--- a/tests/auto/qml/qqmlpropertycache/CMakeLists.txt
+++ b/tests/auto/qml/qqmlpropertycache/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlpropertycache Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlpropertycache LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlpropertycache/data/duplicateIdsAndGeneralizedGroupProperties.qml b/tests/auto/qml/qqmlpropertycache/data/duplicateIdsAndGeneralizedGroupProperties.qml
new file mode 100644
index 0000000000..2dd2cd8e21
--- /dev/null
+++ b/tests/auto/qml/qqmlpropertycache/data/duplicateIdsAndGeneralizedGroupProperties.qml
@@ -0,0 +1,64 @@
+import QtQuick 2.15
+
+Item {
+ component First : Item {
+ Item {
+ id: a
+ }
+
+ states: [
+ State {
+ name: "test1"
+
+ PropertyChanges {
+ a.enabled: false
+ }
+ }
+ ]
+ }
+
+ component Second : Item {
+ QtObject {
+ id: a
+ property bool enabled: true
+ }
+
+ states: [
+ State {
+ name: "test2"
+
+ PropertyChanges {
+ a.enabled: false
+ }
+ }
+ ]
+
+ property Component cc: Item {
+ Item { id: a }
+
+ states: [
+ State {
+ name: "test3"
+
+ PropertyChanges {
+ a.enabled: false
+ }
+ }
+ ]
+ }
+ }
+
+ First { id: first }
+ Second { id: second }
+ property Item third: second.cc.createObject();
+
+ Component.onCompleted: {
+ console.log(1, first.data[0].enabled, second.data[0].enabled, third.data[0].enabled);
+ first.state = "test1";
+ console.log(2, first.data[0].enabled, second.data[0].enabled, third.data[0].enabled);
+ second.state = "test2";
+ console.log(3, first.data[0].enabled, second.data[0].enabled, third.data[0].enabled);
+ third.state = "test3";
+ console.log(4, first.data[0].enabled, second.data[0].enabled, third.data[0].enabled);
+ }
+}
diff --git a/tests/auto/qml/qqmlpropertycache/data/overriddenSignal.qml b/tests/auto/qml/qqmlpropertycache/data/overriddenSignal.qml
new file mode 100644
index 0000000000..c948d47a1b
--- /dev/null
+++ b/tests/auto/qml/qqmlpropertycache/data/overriddenSignal.qml
@@ -0,0 +1,36 @@
+import QtQml
+import Test.PropertyCache
+
+QtObject {
+ id: root
+
+ property BaseObject obj: null
+ property Connections connection: Connections {
+ target: obj
+ function onPropertyAChanged() { ++root.a }
+ }
+ onObjChanged: {
+ connection.target = obj // Make sure this takes effect before sending the signal
+ obj.propertyAChanged()
+ }
+
+ property BaseObject obj2: null
+ property Connections connection2: Connections {
+ target: obj2
+ function onSignalA() { ++root.b }
+ }
+ onObj2Changed: {
+ connection2.target = obj2 // Make sure this takes effect before sending the signal
+ obj2.signalA();
+ }
+
+ property BaseObject theObj: BaseObject {}
+ Component.onCompleted: {
+ // Make sure the change signals are triggered also initially
+ obj = theObj;
+ obj2 = theObj;
+ }
+
+ property int a: 0
+ property int b: 0
+}
diff --git a/tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal.qml b/tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal.qml
new file mode 100644
index 0000000000..b8fee08978
--- /dev/null
+++ b/tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal.qml
@@ -0,0 +1,8 @@
+import QtQml
+import Test.PropertyCache
+
+BaseObject {
+ property int callCount: 0
+ function signalA() { ++callCount }
+ Component.onCompleted: signalA()
+}
diff --git a/tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal2.qml b/tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal2.qml
new file mode 100644
index 0000000000..cbf1cfe037
--- /dev/null
+++ b/tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal2.qml
@@ -0,0 +1,6 @@
+import QtQml
+import Test.PropertyCache
+
+BaseObject {
+ signal propertyAChanged
+}
diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
index cfea7c0da1..6af2a3e371 100644
--- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
+++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <private/qqmlpropertycache_p.h>
@@ -8,6 +8,7 @@
#include <QtQml/qqmlcomponent.h>
#include <private/qmetaobjectbuilder_p.h>
#include <private/qqmlcontextdata_p.h>
+#include <private/qqmlpropertycachecreator_p.h>
#include <QCryptographicHash>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -34,6 +35,8 @@ private slots:
void derivedGadgetMethod();
void restrictRegistrationVersion();
void rejectOverriddenFinal();
+ void overriddenSignals();
+ void duplicateIdsAndGeneralizedGroupProperties();
private:
QQmlEngine engine;
@@ -164,6 +167,19 @@ Q_SIGNALS:
void signalB();
};
+class OverriddenSignal : public BaseObject
+{
+ Q_OBJECT
+public:
+ OverriddenSignal(QObject *parent = nullptr) : BaseObject(parent) {}
+
+ Q_INVOKABLE void propertyAChanged() { ++propertyAChangedCalled; }
+ int propertyAChangedCalled = 0;
+
+Q_SIGNALS:
+ void signalA();
+};
+
const QQmlPropertyData *cacheProperty(const QQmlPropertyCache::ConstPtr &cache, const char *name)
{
return cache->property(QLatin1String(name), nullptr, nullptr);
@@ -707,4 +723,70 @@ void tst_qqmlpropertycache::rejectOverriddenFinal()
QCOMPARE(o->property("c").toInt(), 0);
}
+void tst_qqmlpropertycache::overriddenSignals()
+{
+ qmlRegisterTypesAndRevisions<BaseObject>("Test.PropertyCache", 3);
+ QQmlEngine engine;
+
+ QQmlComponent c1(&engine, testFileUrl("overriddenSignal.qml"));
+ QVERIFY2(!c1.isError(), qPrintable(c1.errorString()));
+
+ QScopedPointer<QObject> o(c1.create());
+
+ // the propertyAChanged _signal_ is sent once (initially).
+ QCOMPARE(o->property("a").toInt(), 1);
+
+ // signalA() is invoked once as signal, and the other time as method since both are C++.
+ QCOMPARE(o->property("b").toInt(), 1);
+
+ OverriddenSignal *derived = new OverriddenSignal(o.data());
+
+ // Does call our overridden method, since that is defined in C++
+ QCOMPARE(derived->propertyAChangedCalled, 0);
+ o->setProperty("obj", QVariant::fromValue(derived));
+ QCOMPARE(derived->propertyAChangedCalled, 1);
+
+ o->setProperty("obj2", QVariant::fromValue(derived));
+
+ // the propertyAChanged _signal_ is sent once (initially).
+ QCOMPARE(o->property("a").toInt(), 1);
+
+ // We get to receive both signalA() signals since we only match by name.
+ QCOMPARE(o->property("b").toInt(), 2);
+
+ // We shouldn't be allowed to define such things in QML, though.
+
+ const QUrl c2Url = testFileUrl("qmlOverriddenSignal.qml");
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(c2Url.toString() + QLatin1String(
+ ":6:14: Duplicate method name: "
+ "invalid override of property change signal or superclass signal")));
+ QQmlComponent c2(&engine, c2Url);
+ // Should be an error, but we can't enforce it yet.
+
+ const QUrl c3Url = testFileUrl("qmlOverriddenSignal2.qml");
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(c3Url.toString() + QLatin1String(
+ ":5:12: Duplicate signal name: "
+ "invalid override of property change signal or superclass signal")));
+ QQmlComponent c3(&engine, c3Url);
+ // Should be an error, but we can't enforce it yet.
+}
+
+void tst_qqmlpropertycache::duplicateIdsAndGeneralizedGroupProperties()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("duplicateIdsAndGeneralizedGroupProperties.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(QtDebugMsg, "1 true true true");
+ QTest::ignoreMessage(QtDebugMsg, "2 false true true");
+ QTest::ignoreMessage(QtDebugMsg, "3 false false true");
+ QTest::ignoreMessage(QtDebugMsg, "4 false false false");
+
+ QScopedPointer<QObject> o(c.create());
+}
+
QTEST_MAIN(tst_qqmlpropertycache)
diff --git a/tests/auto/qml/qqmlpropertymap/CMakeLists.txt b/tests/auto/qml/qqmlpropertymap/CMakeLists.txt
index bb314ba006..2a7bd742fa 100644
--- a/tests/auto/qml/qqmlpropertymap/CMakeLists.txt
+++ b/tests/auto/qml/qqmlpropertymap/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlpropertymap Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlpropertymap LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
index 689202346c..2d91a8502d 100644
--- a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
+++ b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQml/qqmlengine.h>
@@ -346,9 +346,8 @@ void tst_QQmlPropertyMap::controlledWrite()
component.setData(qmlSource, QUrl::fromLocalFile(""));
QVERIFY(component.isReady());
- QObject *obj = component.create();
- QVERIFY(obj);
- delete obj;
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj.get());
QCOMPARE(map.value(QLatin1String("key1")), QVariant("HELLO WORLD"));
QCOMPARE(map.value(QLatin1String("key2")), QVariant("Goodbye"));
@@ -364,8 +363,7 @@ void tst_QQmlPropertyMap::crashBug()
QQmlComponent c(&engine);
c.setData("import QtQuick 2.0\nBinding { target: map; property: \"myProp\"; value: 10 + 23 }",QUrl());
- QObject *obj = c.create(&context);
- delete obj;
+ std::unique_ptr<QObject> obj { c.create(&context) };
}
void tst_QQmlPropertyMap::QTBUG_17868()
@@ -378,10 +376,9 @@ void tst_QQmlPropertyMap::QTBUG_17868()
map.insert("key", 1);
QQmlComponent c(&engine);
c.setData("import QtQuick 2.0\nItem {property bool error:false; Component.onCompleted: {try{ map.keys(); }catch(e) {error=true;}}}",QUrl());
- QObject *obj = c.create(&context);
- QVERIFY(obj);
+ std::unique_ptr<QObject> obj { c.create(&context) };
+ QVERIFY(obj.get());
QVERIFY(!obj->property("error").toBool());
- delete obj;
}
@@ -434,17 +431,14 @@ void tst_QQmlPropertyMap::QTBUG_31226()
" Timer { interval: 5; running: true; onTriggered: { myProp = qmlPropertyMap.greeting; } }\n"
"}",
QUrl());
- QObject *obj = c.create(&context);
- QVERIFY(obj);
+ std::unique_ptr<QObject> obj { c.create(&context) };
+ QVERIFY(obj.get());
QQmlPropertyMap *qmlPropertyMap = obj->findChild<QQmlPropertyMap*>(QString("qmlPropertyMap"));
QVERIFY(qmlPropertyMap);
qmlPropertyMap->insert("greeting", QString("Hello world!"));
QTRY_COMPARE(obj->property("myProp").toString(), QString("Hello world!"));
-
- delete obj;
-
}
void tst_QQmlPropertyMap::QTBUG_29836()
@@ -461,13 +455,10 @@ void tst_QQmlPropertyMap::QTBUG_29836()
" Timer { interval: 5; running: true; onTriggered: enhancedMap.testSlot() }\n"
"}",
QUrl());
- QObject *obj = c.create(&context);
- QVERIFY(obj);
+ std::unique_ptr<QObject> obj { c.create(&context) };
+ QVERIFY(obj.get());
QTRY_COMPARE(map.testSlotCalled(), true);
-
- delete obj;
-
}
void tst_QQmlPropertyMap::QTBUG_35233()
diff --git a/tests/auto/qml/qqmlqt/CMakeLists.txt b/tests/auto/qml/qqmlqt/CMakeLists.txt
index f43c12d907..31f86d8877 100644
--- a/tests/auto/qml/qqmlqt/CMakeLists.txt
+++ b/tests/auto/qml/qqmlqt/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlqt Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlqt LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlqt/data/qtbug_125495.qml b/tests/auto/qml/qqmlqt/data/qtbug_125495.qml
new file mode 100644
index 0000000000..88f9cb259f
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/qtbug_125495.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+Item {
+ property font fontProperty: Qt.font({ styleName: "Some Style" });
+}
diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
index 5ba1f6f848..8139ec48d7 100644
--- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
+++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <private/qqmlengine_p.h>
@@ -27,7 +27,8 @@
#include <QTimeZone>
#include <QtQuickTestUtils/private/qmlutils_p.h>
-#include <private/qglobal_p.h>
+#include <private/qtenvironmentvariables_p.h> // for qTzSet()
+#include <private/qqmlengine_p.h>
class tst_qqmlqt : public QQmlDataTest
{
@@ -56,8 +57,10 @@ private slots:
void alpha();
void tint();
void color();
+#if QT_CONFIG(desktopservices)
void openUrlExternally();
void openUrlExternally_pragmaLibrary();
+#endif
void md5();
void createComponent();
void createComponent_pragmaLibrary();
@@ -82,6 +85,8 @@ private slots:
void timeRoundtrip_data();
void timeRoundtrip();
+ void fontSetsStyleName();
+
private:
QQmlEngine engine;
};
@@ -612,6 +617,7 @@ public slots:
void noteCall(const QUrl &url) { called++; last = url; }
};
+#if QT_CONFIG(desktopservices)
void tst_qqmlqt::openUrlExternally()
{
MyUrlHandler handler;
@@ -658,6 +664,7 @@ void tst_qqmlqt::openUrlExternally_pragmaLibrary()
QCOMPARE(handler.called,2);
QCOMPARE(handler.last, htmlTestFile);
}
+#endif
void tst_qqmlqt::md5()
{
@@ -805,7 +812,7 @@ void tst_qqmlqt::dateTimeFormatting()
<< component.url().toString() + ":40: TypeError: Passing incompatible arguments to C++ functions from JavaScript is not allowed."
<< component.url().toString() + ":43: TypeError: Passing incompatible arguments to C++ functions from JavaScript is not allowed.";
- foreach (const QString &warning, warnings)
+ for (const QString &warning : std::as_const(warnings))
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
warnings.clear();
@@ -820,7 +827,7 @@ void tst_qqmlqt::dateTimeFormatting()
<< "Could not convert argument 1 at"
<< "expression for err_dateTime2@";
- foreach (const QString &warning, warnings)
+ for (const QString &warning : std::as_const(warnings))
QTest::ignoreMessage(QtWarningMsg, QRegularExpression(warning));
QScopedPointer<QObject> object(component.createWithInitialProperties({
@@ -833,7 +840,7 @@ void tst_qqmlqt::dateTimeFormatting()
QVERIFY(inputProperties.size() > 0);
QVariant result;
- foreach(const QString &prop, inputProperties) {
+ for (const QString &prop : std::as_const(inputProperties)) {
QVERIFY(QMetaObject::invokeMethod(object.data(), method.toUtf8().constData(),
Q_RETURN_ARG(QVariant, result),
Q_ARG(QVariant, prop)));
@@ -1280,12 +1287,13 @@ void tst_qqmlqt::later_data()
void tst_qqmlqt::later()
{
+ QQmlEngine engine;
QFETCH(QString, function);
QFETCH(QStringList, expectedWarnings);
QFETCH(QStringList, propNames);
QFETCH(QVariantList, values);
- foreach (const QString &w, expectedWarnings)
+ for (const QString &w : std::as_const(expectedWarnings))
QTest::ignoreMessage(QtWarningMsg, qPrintable(w));
QQmlComponent component(&engine, testFileUrl("later.qml"));
@@ -1300,7 +1308,7 @@ void tst_qqmlqt::later()
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
QCoreApplication::processEvents();
} else if (propNames.at(i) == QLatin1String("collectGarbage")) {
- engine.collectGarbage();
+ gc(engine, GCFlags::DontSendPostedEvents);
} else {
QCOMPARE(root->property(qPrintable(propNames.at(i))), values.at(i));
}
@@ -1463,6 +1471,18 @@ void tst_qqmlqt::timeRoundtrip()
QCOMPARE(tp.m_getTime, tp.m_putTime);
}
+void tst_qqmlqt::fontSetsStyleName() {
+ QQmlComponent component(&engine, testFileUrl("qtbug_125495.qml"));
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
+
+ QFont f;
+ f.setStyleName("Some Style");
+
+ QCOMPARE(qvariant_cast<QFont>(object->property("fontProperty")), f);
+}
+
QTEST_MAIN(tst_qqmlqt)
#include "tst_qqmlqt.moc"
diff --git a/tests/auto/qml/qqmlsettings/CMakeLists.txt b/tests/auto/qml/qqmlsettings/CMakeLists.txt
index fab4502c65..a444324120 100644
--- a/tests/auto/qml/qqmlsettings/CMakeLists.txt
+++ b/tests/auto/qml/qqmlsettings/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlsettings_labs Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlsettings_labs LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlsettings/data/aliases.qml b/tests/auto/qml/qqmlsettings/data/aliases.qml
index 25ca431a6d..21bc558799 100644
--- a/tests/auto/qml/qqmlsettings/data/aliases.qml
+++ b/tests/auto/qml/qqmlsettings/data/aliases.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.1
import QtQuick 2.2
import Qt.labs.settings 1.0
diff --git a/tests/auto/qml/qqmlsettings/data/basic.qml b/tests/auto/qml/qqmlsettings/data/basic.qml
index ce02d65a87..64520b33f2 100644
--- a/tests/auto/qml/qqmlsettings/data/basic.qml
+++ b/tests/auto/qml/qqmlsettings/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import Qt.labs.settings 1.0
Settings {
diff --git a/tests/auto/qml/qqmlsettings/data/categories.qml b/tests/auto/qml/qqmlsettings/data/categories.qml
index c333ec17eb..a6407f9cb2 100644
--- a/tests/auto/qml/qqmlsettings/data/categories.qml
+++ b/tests/auto/qml/qqmlsettings/data/categories.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import Qt.labs.settings 1.0
Settings {
diff --git a/tests/auto/qml/qqmlsettings/data/cpp-aliases.qml b/tests/auto/qml/qqmlsettings/data/cpp-aliases.qml
index 0ee95641c4..84f8923705 100644
--- a/tests/auto/qml/qqmlsettings/data/cpp-aliases.qml
+++ b/tests/auto/qml/qqmlsettings/data/cpp-aliases.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.1
import QtQuick 2.2
import Qt.labs.settings 1.0
diff --git a/tests/auto/qml/qqmlsettings/data/siblings.qml b/tests/auto/qml/qqmlsettings/data/siblings.qml
index 548a0869da..962cbc128b 100644
--- a/tests/auto/qml/qqmlsettings/data/siblings.qml
+++ b/tests/auto/qml/qqmlsettings/data/siblings.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import Qt.labs.settings 1.0
diff --git a/tests/auto/qml/qqmlsettings/data/types.qml b/tests/auto/qml/qqmlsettings/data/types.qml
index fc2209375d..eec4bb709b 100644
--- a/tests/auto/qml/qqmlsettings/data/types.qml
+++ b/tests/auto/qml/qqmlsettings/data/types.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.1
import QtQuick 2.2
import Qt.labs.settings 1.0
diff --git a/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp b/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp
index 88d8c58e2c..46ab2be3c9 100644
--- a/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp
+++ b/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtCore/QCoreApplication>
#include <QtCore/QScopedPointer>
diff --git a/tests/auto/qml/qqmlsqldatabase/CMakeLists.txt b/tests/auto/qml/qqmlsqldatabase/CMakeLists.txt
index 7537a92803..92809d0963 100644
--- a/tests/auto/qml/qqmlsqldatabase/CMakeLists.txt
+++ b/tests/auto/qml/qqmlsqldatabase/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlsqldatabase Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlsqldatabase LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlsqldatabase/data/changeVersion.qml b/tests/auto/qml/qqmlsqldatabase/data/changeVersion.qml
index fbd770740d..74226808f2 100644
--- a/tests/auto/qml/qqmlsqldatabase/data/changeVersion.qml
+++ b/tests/auto/qml/qqmlsqldatabase/data/changeVersion.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.2
import QtQuick.LocalStorage 2.0
diff --git a/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp b/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp
index 67c44684a4..0269756225 100644
--- a/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp
+++ b/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -164,9 +165,9 @@ void tst_qqmlsqldatabase::testQml_cleanopen()
engine->collectGarbage();
- foreach (QString dbname, QSqlDatabase::connectionNames()) {
+ const QStringList connectionNames = QSqlDatabase::connectionNames();
+ for (const QString &dbname : connectionNames)
QSqlDatabase::removeDatabase(dbname);
- }
}
void tst_qqmlsqldatabase::totalDatabases()
diff --git a/tests/auto/qml/qqmltablemodel/CMakeLists.txt b/tests/auto/qml/qqmltablemodel/CMakeLists.txt
index ebd3e94835..8edd052e3c 100644
--- a/tests/auto/qml/qqmltablemodel/CMakeLists.txt
+++ b/tests/auto/qml/qqmltablemodel/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmltablemodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmltablemodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmltablemodel/data/TestModel.qml b/tests/auto/qml/qqmltablemodel/data/TestModel.qml
index a862af35d2..2b41837bac 100644
--- a/tests/auto/qml/qqmltablemodel/data/TestModel.qml
+++ b/tests/auto/qml/qqmltablemodel/data/TestModel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/TestUtils.js b/tests/auto/qml/qqmltablemodel/data/TestUtils.js
index 83ac1b80a8..f6a5d4bb20 100644
--- a/tests/auto/qml/qqmltablemodel/data/TestUtils.js
+++ b/tests/auto/qml/qqmltablemodel/data/TestUtils.js
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
function testModelRoleDataProvider(index, role, cellData) {
switch (role) {
diff --git a/tests/auto/qml/qqmltablemodel/data/common.qml b/tests/auto/qml/qqmltablemodel/data/common.qml
index 7e9f46dd6f..1b3b8b5846 100644
--- a/tests/auto/qml/qqmltablemodel/data/common.qml
+++ b/tests/auto/qml/qqmltablemodel/data/common.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.13
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/complex.qml b/tests/auto/qml/qqmltablemodel/data/complex.qml
index 9075a6a26f..41c69d44f4 100644
--- a/tests/auto/qml/qqmltablemodel/data/complex.qml
+++ b/tests/auto/qml/qqmltablemodel/data/complex.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.13
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/dataAndSetData.qml b/tests/auto/qml/qqmltablemodel/data/dataAndSetData.qml
index a1d9463665..dcdfd42a28 100644
--- a/tests/auto/qml/qqmltablemodel/data/dataAndSetData.qml
+++ b/tests/auto/qml/qqmltablemodel/data/dataAndSetData.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/empty.qml b/tests/auto/qml/qqmltablemodel/data/empty.qml
index 77c0021ee6..164a38b9d1 100644
--- a/tests/auto/qml/qqmltablemodel/data/empty.qml
+++ b/tests/auto/qml/qqmltablemodel/data/empty.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/intAndDouble.qml b/tests/auto/qml/qqmltablemodel/data/intAndDouble.qml
index c08525bc95..d20650f3be 100644
--- a/tests/auto/qml/qqmltablemodel/data/intAndDouble.qml
+++ b/tests/auto/qml/qqmltablemodel/data/intAndDouble.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/omitTableModelColumnIndex.qml b/tests/auto/qml/qqmltablemodel/data/omitTableModelColumnIndex.qml
index bb278ff9d1..60f502d4b1 100644
--- a/tests/auto/qml/qqmltablemodel/data/omitTableModelColumnIndex.qml
+++ b/tests/auto/qml/qqmltablemodel/data/omitTableModelColumnIndex.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml b/tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml
index 04c76098dd..847a89667f 100644
--- a/tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml
+++ b/tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml b/tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml
index 884427d24b..f5ece4bcf3 100644
--- a/tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml
+++ b/tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp b/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
index cd6eb3e9c5..f2eec6e79c 100644
--- a/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
+++ b/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
diff --git a/tests/auto/qml/qqmltimer/CMakeLists.txt b/tests/auto/qml/qqmltimer/CMakeLists.txt
index 1853a545d7..88d596be85 100644
--- a/tests/auto/qml/qqmltimer/CMakeLists.txt
+++ b/tests/auto/qml/qqmltimer/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmltimer Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmltimer LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmltimer
SOURCES
tst_qqmltimer.cpp
@@ -15,6 +21,7 @@ qt_internal_add_test(tst_qqmltimer
Qt::Gui
Qt::GuiPrivate
Qt::QmlPrivate
+ Qt::QmlMetaPrivate
Qt::QuickPrivate
)
diff --git a/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp b/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp
index 736907d5f0..495f7044f6 100644
--- a/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp
+++ b/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp
@@ -1,14 +1,18 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <QtTest/QSignalSpy>
-#include <qtest.h>
-#include <QtQml/qqmlengine.h>
-#include <QtQml/qqmlcomponent.h>
-#include <QtQml/private/qqmltimer_p.h>
-#include <QtQuick/qquickitem.h>
-#include <QDebug>
-#include <QtCore/QPauseAnimation>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <private/qabstractanimation_p.h>
+#include <private/qqmltimer_p.h>
+
+#include <QtQuick/qquickitem.h>
+
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlengine.h>
+
+#include <QtTest/qsignalspy.h>
+#include <QtTest/qtest.h>
+
+#include <QtCore/qpauseanimation.h>
void consistentWait(int ms)
{
@@ -69,7 +73,8 @@ void tst_qqmltimer::notRepeating()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 100; running: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
+ std::unique_ptr<QObject> o { component.create() };
+ QQmlTimer *timer = qobject_cast<QQmlTimer*>(o.get());
QVERIFY(timer != nullptr);
QVERIFY(timer->isRunning());
QVERIFY(!timer->isRepeating());
@@ -91,12 +96,12 @@ void tst_qqmltimer::notRepeatingStart()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 100 }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
- QVERIFY(timer != nullptr);
+ std::unique_ptr<QQmlTimer> timer { qobject_cast<QQmlTimer*>(component.create()) };
+ QVERIFY(timer.get());
QVERIFY(!timer->isRunning());
TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ connect(timer.get(), SIGNAL(triggered()), &helper, SLOT(timeout()));
consistentWait(200);
QCOMPARE(helper.count, 0);
@@ -107,8 +112,6 @@ void tst_qqmltimer::notRepeatingStart()
consistentWait(200);
QCOMPARE(helper.count, 1);
QVERIFY(!timer->isRunning());
-
- delete timer;
}
void tst_qqmltimer::repeat()
@@ -116,11 +119,11 @@ void tst_qqmltimer::repeat()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 100; repeat: true; running: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
- QVERIFY(timer != nullptr);
+ std::unique_ptr<QQmlTimer> timer { qobject_cast<QQmlTimer*>(component.create()) };
+ QVERIFY(timer);
TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ connect(timer.get(), SIGNAL(triggered()), &helper, SLOT(timeout()));
QCOMPARE(helper.count, 0);
consistentWait(200);
@@ -138,7 +141,7 @@ void tst_qqmltimer::repeat()
QCOMPARE(helper.count, oldCount);
QVERIFY(!timer->isRunning());
- QSignalSpy spy(timer, SIGNAL(repeatChanged()));
+ QSignalSpy spy(timer.get(), SIGNAL(repeatChanged()));
timer->setRepeating(false);
QVERIFY(!timer->isRepeating());
@@ -149,8 +152,6 @@ void tst_qqmltimer::repeat()
timer->setRepeating(true);
QCOMPARE(spy.size(),2);
-
- delete timer;
}
void tst_qqmltimer::triggeredOnStart()
@@ -158,12 +159,12 @@ void tst_qqmltimer::triggeredOnStart()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 100; running: true; triggeredOnStart: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
- QVERIFY(timer != nullptr);
+ std::unique_ptr<QQmlTimer> timer { qobject_cast<QQmlTimer*>(component.create()) };
+ QVERIFY(timer);
QVERIFY(timer->triggeredOnStart());
TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ connect(timer.get(), SIGNAL(triggered()), &helper, SLOT(timeout()));
consistentWait(1);
QCOMPARE(helper.count, 1);
consistentWait(200);
@@ -172,7 +173,7 @@ void tst_qqmltimer::triggeredOnStart()
QCOMPARE(helper.count, 2);
QVERIFY(!timer->isRunning());
- QSignalSpy spy(timer, SIGNAL(triggeredOnStartChanged()));
+ QSignalSpy spy(timer.get(), SIGNAL(triggeredOnStartChanged()));
timer->setTriggeredOnStart(false);
QVERIFY(!timer->triggeredOnStart());
@@ -183,8 +184,6 @@ void tst_qqmltimer::triggeredOnStart()
timer->setTriggeredOnStart(true);
QCOMPARE(spy.size(),2);
-
- delete timer;
}
void tst_qqmltimer::triggeredOnStartRepeat()
@@ -192,11 +191,11 @@ void tst_qqmltimer::triggeredOnStartRepeat()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 100; running: true; triggeredOnStart: true; repeat: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
- QVERIFY(timer != nullptr);
+ std::unique_ptr<QQmlTimer> timer { qobject_cast<QQmlTimer*>(component.create()) };
+ QVERIFY(timer);
TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ connect(timer.get(), SIGNAL(triggered()), &helper, SLOT(timeout()));
consistentWait(1);
QCOMPARE(helper.count, 1);
@@ -206,8 +205,6 @@ void tst_qqmltimer::triggeredOnStartRepeat()
consistentWait(200);
QVERIFY(helper.count > oldCount);
QVERIFY(timer->isRunning());
-
- delete timer;
}
void tst_qqmltimer::noTriggerIfNotRunning()
@@ -221,12 +218,10 @@ void tst_qqmltimer::noTriggerIfNotRunning()
"property Timer timer2: Timer { interval: 10; running: true; onTriggered: t1.running=false }"
"}"
), QUrl::fromLocalFile(""));
- QObject *item = component.create();
- QVERIFY(item != nullptr);
+ std::unique_ptr<QObject> item { component.create() };
+ QVERIFY(item);
consistentWait(200);
QCOMPARE(item->property("ok").toBool(), true);
-
- delete item;
}
void tst_qqmltimer::changeDuration()
@@ -234,11 +229,11 @@ void tst_qqmltimer::changeDuration()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 200; repeat: true; running: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
- QVERIFY(timer != nullptr);
+ std::unique_ptr<QQmlTimer> timer { qobject_cast<QQmlTimer*>(component.create()) };
+ QVERIFY(timer);
TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ connect(timer.get(), SIGNAL(triggered()), &helper, SLOT(timeout()));
QCOMPARE(helper.count, 0);
consistentWait(500);
@@ -250,7 +245,7 @@ void tst_qqmltimer::changeDuration()
QCOMPARE(helper.count, 3);
QVERIFY(timer->isRunning());
- QSignalSpy spy(timer, SIGNAL(intervalChanged()));
+ QSignalSpy spy(timer.get(), SIGNAL(intervalChanged()));
timer->setInterval(200);
QCOMPARE(timer->interval(), 200);
@@ -261,8 +256,6 @@ void tst_qqmltimer::changeDuration()
timer->setInterval(300);
QCOMPARE(spy.size(),2);
-
- delete timer;
}
void tst_qqmltimer::restart()
@@ -270,11 +263,11 @@ void tst_qqmltimer::restart()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 1000; repeat: true; running: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
- QVERIFY(timer != nullptr);
+ std::unique_ptr<QQmlTimer> timer { qobject_cast<QQmlTimer*>(component.create()) };
+ QVERIFY(timer);
TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ connect(timer.get(), SIGNAL(triggered()), &helper, SLOT(timeout()));
QCOMPARE(helper.count, 0);
consistentWait(1200);
@@ -290,8 +283,6 @@ void tst_qqmltimer::restart()
QCOMPARE(helper.count, 2);
QVERIFY(timer->isRunning());
-
- delete timer;
}
void tst_qqmltimer::restartFromTriggered()
@@ -356,14 +347,12 @@ void tst_qqmltimer::parentProperty()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQuick 2.0\nItem { Timer { objectName: \"timer\"; running: parent.visible } }"), QUrl::fromLocalFile(""));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item { qobject_cast<QQuickItem*>(component.create()) };
+ QVERIFY(item);
QQmlTimer *timer = item->findChild<QQmlTimer*>("timer");
QVERIFY(timer != nullptr);
QVERIFY(timer->isRunning());
-
- delete timer;
}
void tst_qqmltimer::stopWhenEventPosted()
@@ -371,7 +360,8 @@ void tst_qqmltimer::stopWhenEventPosted()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 200; running: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
+ std::unique_ptr<QObject> o { component.create() };
+ QQmlTimer *timer = qobject_cast<QQmlTimer*>(o.get());
TimerHelper helper;
connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
@@ -395,7 +385,8 @@ void tst_qqmltimer::restartWhenEventPosted()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 200; running: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
+ std::unique_ptr<QObject> o { component.create() };
+ QQmlTimer *timer = qobject_cast<QQmlTimer*>(o.get());
TimerHelper helper;
connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
diff --git a/tests/auto/qml/qqmltranslation/CMakeLists.txt b/tests/auto/qml/qqmltranslation/CMakeLists.txt
index 86198e7867..12d98b95a9 100644
--- a/tests/auto/qml/qqmltranslation/CMakeLists.txt
+++ b/tests/auto/qml/qqmltranslation/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmltranslation Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmltranslation LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmltranslation/data/jstranslation.qml b/tests/auto/qml/qqmltranslation/data/jstranslation.qml
index 7adde019fa..cca8bfa9e8 100644
--- a/tests/auto/qml/qqmltranslation/data/jstranslation.qml
+++ b/tests/auto/qml/qqmltranslation/data/jstranslation.qml
@@ -17,4 +17,5 @@ QtObject {
property string singular2: Js.singular2()
property string plural: Js.plural()
property string plural2: Js.plural2()
+ property string emptyContext: Js.emptyContext()
}
diff --git a/tests/auto/qml/qqmltranslation/data/pragmacontext.qml b/tests/auto/qml/qqmltranslation/data/pragmacontext.qml
new file mode 100644
index 0000000000..e158cfe4bf
--- /dev/null
+++ b/tests/auto/qml/qqmltranslation/data/pragmacontext.qml
@@ -0,0 +1,8 @@
+import QtQml 2.12
+
+pragma Translator: contextSetWithPragma
+
+QtObject {
+ property string german1: qsTr("English in translation")
+ property string german2: qsTranslate("setContext","English in translation")
+}
diff --git a/tests/auto/qml/qqmltranslation/data/pragmacontextstringliteral.qml b/tests/auto/qml/qqmltranslation/data/pragmacontextstringliteral.qml
new file mode 100644
index 0000000000..31a3d0e009
--- /dev/null
+++ b/tests/auto/qml/qqmltranslation/data/pragmacontextstringliteral.qml
@@ -0,0 +1,8 @@
+import QtQml 2.12
+
+pragma Translator: "contextSetWithPragmaStringLiteral"
+
+QtObject {
+ property string german1: qsTr("English in translation")
+ property string german2: qsTranslate("setContext","English in translation")
+}
diff --git a/tests/auto/qml/qqmltranslation/data/translation.js b/tests/auto/qml/qqmltranslation/data/translation.js
index 11117fd36e..5269926604 100644
--- a/tests/auto/qml/qqmltranslation/data/translation.js
+++ b/tests/auto/qml/qqmltranslation/data/translation.js
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
function basic() {
return qsTr("hello")
@@ -58,3 +58,7 @@ function plural2() {
return qsTr("%n duck(s)", "", 2)
return "";
}
+
+function emptyContext() {
+ return qsTranslate("", "hello")
+}
diff --git a/tests/auto/qml/qqmltranslation/data/translation.qml b/tests/auto/qml/qqmltranslation/data/translation.qml
index b96471c9dd..127b5cb5b4 100644
--- a/tests/auto/qml/qqmltranslation/data/translation.qml
+++ b/tests/auto/qml/qqmltranslation/data/translation.qml
@@ -1,8 +1,8 @@
import QtQuick 2.0
-
+// The translation data starts at line == 4. QCoreApplication::translate() tolerates this.
QtObject {
objectName: "test"
-
+ property string emptyContext: qsTranslate("", "hello")
property string basic: qsTr("hello")
property string basic2: qsTranslate("CustomContext", "goodbye")
property string basic3: if (objectName.length > 0) qsTr("hello")
diff --git a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
index f78bd3ac76..69dbd6179b 100644
--- a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
+++ b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -24,6 +24,8 @@ private slots:
void idTranslation();
void translationChange();
void preferJSContext();
+ void pragmaContext();
+ void pragmaContextStringLiteral();
void listModel();
};
@@ -50,11 +52,11 @@ void tst_qqmltranslation::translation()
QQmlEngine engine;
QQmlComponent component(&engine, testFile);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
if (verifyCompiledData) {
- QQmlContext *context = qmlContext(object);
+ QQmlContext *context = qmlContext(object.get());
QQmlEnginePrivate *engine = QQmlEnginePrivate::get(context->engine());
QQmlRefPointer<QQmlTypeData> typeData = engine->typeLoader.getType(context->baseUrl());
QVERIFY(!typeData->backupSourceCode().isValid());
@@ -66,7 +68,9 @@ void tst_qqmltranslation::translation()
<< QStringLiteral("basic2")
<< QStringLiteral("disambiguation")
<< QStringLiteral("disambiguation2")
- << QStringLiteral("singular") << QStringLiteral("plural");
+ << QStringLiteral("singular")
+ << QStringLiteral("plural")
+ << QStringLiteral("emptyContext");
const QV4::CompiledData::Object *rootObject
= compilationUnit->qmlData->objectAt(/*root object*/0);
@@ -100,9 +104,9 @@ void tst_qqmltranslation::translation()
QCOMPARE(object->property("singular2").toString(), QLatin1String("1 canard"));
QCOMPARE(object->property("plural").toString(), QLatin1String("2 canards"));
QCOMPARE(object->property("plural2").toString(), QLatin1String("2 canards"));
+ QCOMPARE(object->property("emptyContext").toString(), QLatin1String("hello"));
QCoreApplication::removeTranslator(&translator);
- delete object;
}
void tst_qqmltranslation::idTranslation()
@@ -113,11 +117,11 @@ void tst_qqmltranslation::idTranslation()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("idtranslation.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
{
- QQmlContext *context = qmlContext(object);
+ QQmlContext *context = qmlContext(object.get());
QQmlEnginePrivate *engine = QQmlEnginePrivate::get(context->engine());
QQmlRefPointer<QQmlTypeData> typeData = engine->typeLoader.getType(context->baseUrl());
QVERIFY(!typeData->backupSourceCode().isValid());
@@ -144,7 +148,6 @@ void tst_qqmltranslation::idTranslation()
QCOMPARE(object->property("idTranslation3").toString(), QLatin1String("bonjour tout le monde"));
QCoreApplication::removeTranslator(&translator);
- delete object;
}
class CppTranslationBase : public QQuickItem
@@ -174,6 +177,12 @@ class DummyTranslator : public QTranslator
return QString::fromUtf8("Deutsch in mylibrary");
if (!qstrcmp(sourceText, "English in translation") && !qstrcmp(context, "nested_js_translation"))
return QString::fromUtf8("Deutsch in Setzung");
+ if (!qstrcmp(sourceText, "English in translation") && !qstrcmp(context, "contextSetWithPragma"))
+ return QString::fromUtf8("Deutsch in Setzung pragma");
+ if (!qstrcmp(sourceText, "English in translation") && !qstrcmp(context, "contextSetWithPragmaStringLiteral"))
+ return QString::fromUtf8("Deutsch in Setzung pragma string literal");
+ if (!qstrcmp(sourceText, "English in translation") && !qstrcmp(context, "setContext"))
+ return QString::fromUtf8("Deutsch in Setzung set");
if (!qstrcmp(sourceText, "soup"))
return QString::fromUtf8("Suppe");
if (!qstrcmp(sourceText, "fish"))
@@ -245,6 +254,42 @@ void tst_qqmltranslation::preferJSContext()
QCoreApplication::removeTranslator(&translator);
}
+void tst_qqmltranslation::pragmaContext()
+{
+ DummyTranslator translator;
+ QCoreApplication::installTranslator(&translator);
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("pragmacontext.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QCOMPARE(object->property("german1").toString(),
+ QStringLiteral("Deutsch in Setzung pragma"));
+ QCOMPARE(object->property("german2").toString(),
+ QStringLiteral("Deutsch in Setzung set"));
+
+ QCoreApplication::removeTranslator(&translator);
+}
+
+void tst_qqmltranslation::pragmaContextStringLiteral()
+{
+ DummyTranslator translator;
+ QCoreApplication::installTranslator(&translator);
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("pragmacontextstringliteral.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QCOMPARE(object->property("german1").toString(),
+ QStringLiteral("Deutsch in Setzung pragma string literal"));
+ QCOMPARE(object->property("german2").toString(),
+ QStringLiteral("Deutsch in Setzung set"));
+
+ QCoreApplication::removeTranslator(&translator);
+}
+
void tst_qqmltranslation::listModel()
{
QQmlEngine engine;
diff --git a/tests/auto/qml/qqmltreemodeltotablemodel/CMakeLists.txt b/tests/auto/qml/qqmltreemodeltotablemodel/CMakeLists.txt
index 7c55146ddc..f260ca8287 100644
--- a/tests/auto/qml/qqmltreemodeltotablemodel/CMakeLists.txt
+++ b/tests/auto/qml/qqmltreemodeltotablemodel/CMakeLists.txt
@@ -5,6 +5,12 @@
## tst_qqmltreemodeltotablemodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmltreemodeltotablemodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.cpp b/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.cpp
index 58587da79c..7cf077f265 100644
--- a/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.cpp
+++ b/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testmodel.h"
@@ -129,3 +129,31 @@ bool TestModel::insertRows(int position, int rows, const QModelIndex &parent)
endInsertRows();
return true;
}
+
+void insertColumnsRecursive(TreeItem *item, int cols)
+{
+ int pos = item->m_entries.size();
+ for (int col = 0; col < cols; col++)
+ item->m_entries << QVariant(QString("%1, %2 (inserted)").arg(pos + col).arg(col));
+ for (auto child : item->m_childItems)
+ insertColumnsRecursive(child, cols);
+}
+
+bool TestModel::insertColumns(int position, int cols, const QModelIndex &parent)
+{
+ if (!parent.isValid()) {
+ qWarning() << "Cannot insert columns on an invalid parent!";
+ return false;
+ }
+
+ beginInsertColumns(parent, position, position + cols - 1);
+ TreeItem *parentItem = treeItem(parent);
+
+ TreeItem *item = m_rootItem.data();
+
+ insertColumnsRecursive(item, cols);
+ m_columnCount += cols;
+
+ endInsertColumns();
+ return true;
+}
diff --git a/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.h b/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.h
index f886c56d4a..c67410d5f1 100644
--- a/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.h
+++ b/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTMODEL_H
#define TESTMODEL_H
@@ -38,6 +38,7 @@ public:
QModelIndex parent(const QModelIndex &index) const override;
bool insertRows(int position, int rows, const QModelIndex &parent) override;
+ bool insertColumns(int position, int rows, const QModelIndex &parent) override;
private:
QScopedPointer<TreeItem> m_rootItem;
diff --git a/tests/auto/qml/qqmltreemodeltotablemodel/tst_qqmltreemodeltotablemodel.cpp b/tests/auto/qml/qqmltreemodeltotablemodel/tst_qqmltreemodeltotablemodel.cpp
index cd9aed4b30..47bbf1440b 100644
--- a/tests/auto/qml/qqmltreemodeltotablemodel/tst_qqmltreemodeltotablemodel.cpp
+++ b/tests/auto/qml/qqmltreemodeltotablemodel/tst_qqmltreemodeltotablemodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QAbstractItemModelTester>
diff --git a/tests/auto/qml/qqmltypeloader/CMakeLists.txt b/tests/auto/qml/qqmltypeloader/CMakeLists.txt
index d20449579e..1bf4da34f9 100644
--- a/tests/auto/qml/qqmltypeloader/CMakeLists.txt
+++ b/tests/auto/qml/qqmltypeloader/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmltypeloader Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmltypeloader LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmltypeloader/SlowImport/plugin.cpp b/tests/auto/qml/qqmltypeloader/SlowImport/plugin.cpp
index e0ff775cb5..b1726f190f 100644
--- a/tests/auto/qml/qqmltypeloader/SlowImport/plugin.cpp
+++ b/tests/auto/qml/qqmltypeloader/SlowImport/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "plugin.h"
diff --git a/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h b/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h
index dfaafe278f..2a5a1b2a4e 100644
--- a/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h
+++ b/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef SLOW_PLUGIN_H
#define SLOW_PLUGIN_H
diff --git a/tests/auto/qml/qqmltypeloader/SlowImport/slow.cpp b/tests/auto/qml/qqmltypeloader/SlowImport/slow.cpp
index 910f3eaeb6..c17da49e93 100644
--- a/tests/auto/qml/qqmltypeloader/SlowImport/slow.cpp
+++ b/tests/auto/qml/qqmltypeloader/SlowImport/slow.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "slow.h"
diff --git a/tests/auto/qml/qqmltypeloader/SlowImport/slow.h b/tests/auto/qml/qqmltypeloader/SlowImport/slow.h
index e9f6341e5a..c3ec73bc53 100644
--- a/tests/auto/qml/qqmltypeloader/SlowImport/slow.h
+++ b/tests/auto/qml/qqmltypeloader/SlowImport/slow.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef SLOWSTUFF_H
#define SLOWSTUFF_H
diff --git a/tests/auto/qml/qqmltypeloader/data/GenericView.qml b/tests/auto/qml/qqmltypeloader/data/GenericView.qml
index 2a708d425d..0f90ef26da 100644
--- a/tests/auto/qml/qqmltypeloader/data/GenericView.qml
+++ b/tests/auto/qml/qqmltypeloader/data/GenericView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import Slow 1.0
diff --git a/tests/auto/qml/qqmltypeloader/data/Intercept.qml b/tests/auto/qml/qqmltypeloader/data/Intercept.qml
index 57290832ea..d0de7e04ec 100644
--- a/tests/auto/qml/qqmltypeloader/data/Intercept.qml
+++ b/tests/auto/qml/qqmltypeloader/data/Intercept.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import Fast 1.0
diff --git a/tests/auto/qml/qqmltypeloader/data/NiceView.qml b/tests/auto/qml/qqmltypeloader/data/NiceView.qml
index cb73650551..4f1782000a 100644
--- a/tests/auto/qml/qqmltypeloader/data/NiceView.qml
+++ b/tests/auto/qml/qqmltypeloader/data/NiceView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmltypeloader/data/doesExist.qml b/tests/auto/qml/qqmltypeloader/data/doesExist.qml
new file mode 100644
index 0000000000..54531c4bdc
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/doesExist.qml
@@ -0,0 +1,2 @@
+import QtQml
+QtObject {}
diff --git a/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/a.qml b/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/a.qml
new file mode 100644
index 0000000000..8fc36a40da
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/a.qml
@@ -0,0 +1,3 @@
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qml/qqmltypeloader/data/load_synchronous.qml b/tests/auto/qml/qqmltypeloader/data/load_synchronous.qml
index 10e1784ff1..c22a880fbd 100644
--- a/tests/auto/qml/qqmltypeloader/data/load_synchronous.qml
+++ b/tests/auto/qml/qqmltypeloader/data/load_synchronous.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.2
diff --git a/tests/auto/qml/qqmltypeloader/data/test_intercept.qml b/tests/auto/qml/qqmltypeloader/data/test_intercept.qml
index cd6a726f9b..930d481f7b 100644
--- a/tests/auto/qml/qqmltypeloader/data/test_intercept.qml
+++ b/tests/auto/qml/qqmltypeloader/data/test_intercept.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmltypeloader/data/test_load_complete.qml b/tests/auto/qml/qqmltypeloader/data/test_load_complete.qml
index 6cba31c434..95439b8308 100644
--- a/tests/auto/qml/qqmltypeloader/data/test_load_complete.qml
+++ b/tests/auto/qml/qqmltypeloader/data/test_load_complete.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmltypeloader/declarativetesttype.h b/tests/auto/qml/qqmltypeloader/declarativetesttype.h
index 5a33f25be5..b767342951 100644
--- a/tests/auto/qml/qqmltypeloader/declarativetesttype.h
+++ b/tests/auto/qml/qqmltypeloader/declarativetesttype.h
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DECLARATIVETESTTYPE_H
#define DECLARATIVETESTTYPE_H
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
index 89e208f441..7828a869e1 100644
--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
+++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQml/qqmlengine.h>
@@ -38,6 +38,7 @@ private slots:
void redirect();
void qmlSingletonWithinModule();
void multiSingletonModule();
+ void multiSingletonModuleNoWarning();
void implicitComponentModule();
void customDiskCachePath();
void qrcRootPathUrl();
@@ -47,6 +48,7 @@ private slots:
void circularDependency();
void declarativeCppAndQmlDir();
void signalHandlersAreCompatible();
+ void loadTypeOnShutdown();
private:
void checkSingleton(const QString & dataDirectory);
@@ -62,19 +64,18 @@ void tst_QQMLTypeLoader::testLoadComplete()
#ifdef Q_OS_ANDROID
QSKIP("Loading dynamic plugins does not work on Android");
#endif
- QQuickView *window = new QQuickView();
+ std::unique_ptr<QQuickView> window = std::make_unique<QQuickView>();
window->engine()->addImportPath(QT_TESTCASE_BUILDDIR);
qDebug() << window->engine()->importPathList();
window->setGeometry(0,0,240,320);
window->setSource(testFileUrl("test_load_complete.qml"));
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowExposed(window.get()));
QObject *rootObject = window->rootObject();
QTRY_VERIFY(rootObject != nullptr);
QTRY_COMPARE(rootObject->property("created").toInt(), 2);
QTRY_COMPARE(rootObject->property("loaded").toInt(), 2);
- delete window;
}
void tst_QQMLTypeLoader::loadComponentSynchronously()
@@ -92,7 +93,7 @@ void tst_QQMLTypeLoader::trimCache()
QQmlEngine engine;
QQmlTypeLoader &loader = QQmlEnginePrivate::get(&engine)->typeLoader;
QVector<QQmlTypeData *> releaseLater;
- QVector<QV4::ExecutableCompilationUnit *> releaseCompilationUnitLater;
+ QVector<QV4::CompiledData::CompilationUnit *> releaseCompilationUnitLater;
for (int i = 0; i < 256; ++i) {
QUrl url = testFileUrl("trim_cache.qml");
url.setQuery(QString::number(i));
@@ -534,6 +535,18 @@ void tst_QQMLTypeLoader::multiSingletonModule()
checkCleanCacheLoad(QLatin1String("multiSingletonModule"));
}
+void tst_QQMLTypeLoader::multiSingletonModuleNoWarning()
+{
+ // Should not warn about a "cyclic" dependency between the singletons
+ QTest::failOnWarning(QRegularExpression(".*"));
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("imports/multisingletonmodule/a.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+}
+
void tst_QQMLTypeLoader::implicitComponentModule()
{
#ifdef Q_OS_ANDROID
@@ -673,7 +686,7 @@ static void getCompilationUnitAndRuntimeInfo(QQmlRefPointer<QV4::ExecutableCompi
QVERIFY(!typeData->isError()); // this returns
}
- unit = typeData->compilationUnit();
+ unit = engine->handle()->executableCompilationUnit(typeData->compilationUnit());
QVERIFY(unit);
// the QmlIR::Document is deleted once loader.getType() is complete, so
@@ -724,6 +737,49 @@ void tst_QQMLTypeLoader::signalHandlersAreCompatible()
QVERIFY(unitFromCachegen->url() != unitFromTypeCompiler->url());
}
+void tst_QQMLTypeLoader::loadTypeOnShutdown()
+{
+ bool dead1 = false;
+ bool dead2 = false;
+
+ {
+ QQmlEngine engine;
+ auto good = new QQmlComponent(
+ &engine, testFileUrl("doesExist.qml"),
+ QQmlComponent::CompilationMode::Asynchronous, &engine);
+ QObject::connect(
+ good, &QQmlComponent::statusChanged, &engine,
+ [&](QQmlComponent::Status) {
+
+ // Must not call this if the engine is already dead.
+ QVERIFY(engine.rootContext());
+
+ });
+
+ QObject::connect(good, &QQmlComponent::destroyed, good, [&]() { dead1 = true; });
+ QVERIFY(good->isLoading());
+
+ auto bad = new QQmlComponent(
+ &engine, testFileUrl("doesNotExist.qml"),
+ QQmlComponent::CompilationMode::Asynchronous, &engine);
+ QObject::connect(
+ bad, &QQmlComponent::statusChanged, &engine,
+ [&](QQmlComponent::Status) {
+
+ // Must not call this if the engine is already dead.
+ // Must also not leak memory from the events the error produces.
+ QVERIFY(engine.rootContext());
+
+ });
+
+ QObject::connect(bad, &QQmlComponent::destroyed, bad, [&]() { dead2 = true; });
+ QVERIFY(bad->isLoading());
+ }
+
+ QVERIFY(dead1);
+ QVERIFY(dead2);
+}
+
QTEST_MAIN(tst_QQMLTypeLoader)
#include "tst_qqmltypeloader.moc"
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/CMakeLists.txt b/tests/auto/qml/qqmlvaluetypeproviders/CMakeLists.txt
index 156022bac1..93460d72a9 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/CMakeLists.txt
+++ b/tests/auto/qml/qqmlvaluetypeproviders/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlvaluetypeproviders Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlvaluetypeproviders LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/data/changedSignal.qml b/tests/auto/qml/qqmlvaluetypeproviders/data/changedSignal.qml
index 95a588d1bd..6081d460b8 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/data/changedSignal.qml
+++ b/tests/auto/qml/qqmlvaluetypeproviders/data/changedSignal.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 basysKom GmbH, opensource@basyskom.com.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/data/recursiveWriteBack.qml b/tests/auto/qml/qqmlvaluetypeproviders/data/recursiveWriteBack.qml
index d6707e37cd..e2c39d2d72 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/data/recursiveWriteBack.qml
+++ b/tests/auto/qml/qqmlvaluetypeproviders/data/recursiveWriteBack.qml
@@ -3,11 +3,16 @@ import Test
MyTypeObject {
property list<structured> l: [{i : 21}, {c: 22}, {p: {x: 199, y: 222}}]
+ property int aa: 5
Component.onCompleted: {
l[2].i = 4
l[1].p.x = 88
l[0].sizes[1].width = 19
structured.p.x = 76
+
+ var sizesDetached = l[0].sizesDetached();
+ sizesDetached[1].width = 12;
+ aa = sizesDetached[1].width;
}
}
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/data/structuredValueTypes.qml b/tests/auto/qml/qqmlvaluetypeproviders/data/structuredValueTypes.qml
index 6a42a4f1a8..abd6f6af08 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/data/structuredValueTypes.qml
+++ b/tests/auto/qml/qqmlvaluetypeproviders/data/structuredValueTypes.qml
@@ -40,7 +40,22 @@ MyTypeObject {
r2 = {x: 9, y: 10, width: 11, height: 12};
c3 = 99;
b2 = {i: 11, c: 15, p: {x: 4} }
-
+ acceptConstructible(object)
c4 = {foo: 11};
}
+
+ barren: ({i: 17})
+ function changeBarren() { barren = "foos" }
+
+ property QtObject object: QtObject {}
+ property constructible fromObject: object
+ property int listResult: acceptConstructibles([Qt.resolvedUrl("foo/bar.baz"), fromObject, 12])
+
+ property var insanity: ({})
+ property structured fromInsanity: acceptStructured(insanity)
+
+ property rect newItemPadding
+ function updatePadding() {
+ setEffectPadding(newItemPadding);
+ }
}
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp
index 1746957872..fd85c117e1 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp
@@ -1,11 +1,16 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testtypes.h"
+QList<Padding::LogEntry> Padding::log;
+
void registerTypes()
{
qmlRegisterType<MyTypeObject>("Test", 1, 0, "MyTypeObject");
qmlRegisterTypesAndRevisions<ConstructibleValueType>("Test", 1);
qmlRegisterTypesAndRevisions<ConstructibleFromQReal>("Test", 1);
qmlRegisterTypesAndRevisions<StructuredValueType>("Test", 1);
+ qmlRegisterTypesAndRevisions<ForeignAnonymousStructuredValueType>("Test", 1);
+ qmlRegisterTypesAndRevisions<Padding>("Test", 1);
+ qmlRegisterTypesAndRevisions<MyItem>("Test", 1);
}
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h
index ca1d1b2b7a..8130ea2912 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h
+++ b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPES_H
#define TESTTYPES_H
@@ -33,6 +33,8 @@ struct ConstructibleValueType
public:
ConstructibleValueType() = default;
Q_INVOKABLE ConstructibleValueType(int foo) : m_foo(foo) {}
+ Q_INVOKABLE ConstructibleValueType(QObject *) : m_foo(67) {}
+ Q_INVOKABLE ConstructibleValueType(const QUrl &) : m_foo(68) {}
int foo() const { return m_foo; }
@@ -96,6 +98,8 @@ public:
const QList<QSizeF> &sizes() const { return m_sizes; }
void setSizes(const QList<QSizeF> &sizes) { m_sizes = sizes; }
+ Q_INVOKABLE QList<QSizeF> sizesDetached() const { return m_sizes; }
+
private:
friend bool operator==(const StructuredValueType &a, const StructuredValueType &b)
@@ -109,6 +113,35 @@ private:
QList<QSizeF> m_sizes = { QSizeF(1, 1), QSizeF(2, 2) };
};
+struct BarrenValueType
+{
+ Q_GADGET
+ Q_PROPERTY(int i READ i WRITE setI)
+
+public:
+ BarrenValueType() = default;
+ Q_INVOKABLE BarrenValueType(const QString &) : m_i(25) {}
+
+ int i() const { return m_i; }
+ void setI(int newI) { m_i = newI; }
+
+private:
+ friend bool operator==(const BarrenValueType &a, const BarrenValueType &b)
+ {
+ return a.m_i == b.m_i;
+ }
+
+ int m_i = 0;
+};
+
+struct ForeignAnonymousStructuredValueType
+{
+ Q_GADGET
+ QML_ANONYMOUS
+ QML_FOREIGN(BarrenValueType)
+ QML_STRUCTURED_VALUE
+};
+
class MyTypeObject : public QObject
{
Q_OBJECT
@@ -133,6 +166,7 @@ class MyTypeObject : public QObject
Q_PROPERTY(QVariant variant READ variant NOTIFY changed)
Q_PROPERTY(ConstructibleValueType constructible READ constructible WRITE setConstructible NOTIFY constructibleChanged)
Q_PROPERTY(StructuredValueType structured READ structured WRITE setStructured NOTIFY structuredChanged)
+ Q_PROPERTY(BarrenValueType barren READ barren WRITE setBarren NOTIFY barrenChanged)
Q_PROPERTY(QDateTime aDateTime READ aDateTime WRITE setADateTime NOTIFY aDateTimeChanged)
Q_PROPERTY(QDate aDate READ aDate WRITE setADate NOTIFY aDateChanged)
@@ -275,7 +309,7 @@ public:
{
return m_aDate;
}
- void setADate(const QDate &newADate)
+ void setADate(QDate newADate)
{
if (m_aDate == newADate)
return;
@@ -287,7 +321,7 @@ public:
{
return m_aTime;
}
- void setATime(const QTime &newATime)
+ void setATime(QTime newATime)
{
if (m_aTime == newATime)
return;
@@ -307,6 +341,47 @@ public:
emit aVariantChanged();
}
+ BarrenValueType barren() const
+ {
+ return m_barren;
+ }
+
+ void setBarren(const BarrenValueType &newBarren)
+ {
+ if (m_barren == newBarren)
+ return;
+ m_barren = newBarren;
+ emit barrenChanged();
+ }
+
+ Q_INVOKABLE void acceptConstructible(const ConstructibleValueType &a)
+ {
+ setAVariant(QVariant::fromValue(a));
+ }
+
+ Q_INVOKABLE int acceptConstructibles(const QList<ConstructibleValueType> &constructibles)
+ {
+ int result = 0;
+ for (const auto &c: constructibles) {
+ result += c.foo();
+ }
+ return result;
+ }
+
+ Q_INVOKABLE StructuredValueType acceptStructured(const StructuredValueType &a)
+ {
+ return a;
+ }
+
+ Q_INVOKABLE void setEffectPadding(const QRect &r)
+ {
+ m_hasEffectPadding = true;
+ m_effectPadding = r;
+ }
+
+ bool hasEffectPadding() const { return m_hasEffectPadding; }
+ QRectF effectPadding() const { return m_effectPadding; }
+
signals:
void changed();
void runScript();
@@ -319,6 +394,8 @@ signals:
void aTimeChanged();
void aVariantChanged();
+ void barrenChanged();
+
public slots:
QSize method() { return QSize(13, 14); }
private:
@@ -329,6 +406,139 @@ private:
QDate m_aDate;
QTime m_aTime;
QVariant m_aVariant;
+ BarrenValueType m_barren;
+ QRectF m_effectPadding;
+ bool m_hasEffectPadding = false;
+};
+
+class Padding
+{
+ Q_GADGET
+
+ Q_PROPERTY(int left READ left WRITE setLeft)
+ Q_PROPERTY(int right READ right WRITE setRight)
+
+ QML_VALUE_TYPE(padding)
+ QML_STRUCTURED_VALUE
+
+public:
+ enum LogType {
+ DefaultCtor,
+ CopyCtor,
+ MoveCtor,
+ CopyAssign,
+ MoveAssign,
+ InvokableCtor,
+ CustomCtor,
+ Invalid,
+ };
+
+ Q_ENUM(LogType);
+
+ struct LogEntry {
+ LogType type = Invalid;
+ int left = 0;
+ int right = 0;
+
+ friend QDebug operator<<(QDebug &debug, const LogEntry &self)
+ {
+ return debug << self.type << " " << self.left << " " << self.right;
+ }
+ };
+
+ static QList<LogEntry> log;
+
+ void doLog(LogType type) {
+ log.append({
+ type, m_left, m_right
+ });
+ }
+
+ Padding()
+ {
+ doLog(DefaultCtor);
+ }
+
+ Padding(const Padding &other)
+ : m_left(other.m_left)
+ , m_right(other.m_right)
+ {
+ doLog(CopyCtor);
+ }
+
+ Padding(Padding &&other)
+ : m_left(other.m_left)
+ , m_right(other.m_right)
+ {
+ doLog(MoveCtor);
+ }
+
+ Padding(int left, int right)
+ : m_left( left )
+ , m_right( right )
+ {
+ doLog(CustomCtor);
+ }
+
+ Padding &operator=(const Padding &other) {
+ if (this != &other) {
+ m_left = other.m_left;
+ m_right = other.m_right;
+ }
+ doLog(CopyAssign);
+ return *this;
+ }
+
+ Padding &operator=(Padding &&other) {
+ if (this != &other) {
+ m_left = other.m_left;
+ m_right = other.m_right;
+ }
+ doLog(MoveAssign);
+ return *this;
+ }
+
+ Q_INVOKABLE Padding(int padding )
+ : m_left( padding )
+ , m_right( padding )
+ {
+ doLog(InvokableCtor);
+ }
+
+ void setLeft(int padding) { m_left = padding; }
+ int left() const { return m_left; }
+
+ void setRight(int padding) { m_right = padding; }
+ int right() const { return m_right; }
+
+private:
+ int m_left = 0;
+ int m_right = 0;
+};
+
+class MyItem : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(Padding padding READ padding WRITE setPadding NOTIFY paddingChanged)
+ QML_ELEMENT
+
+public:
+ void setPadding(const Padding &padding)
+ {
+ if (padding.left() == m_padding.left() && padding.right() == m_padding.right())
+ return;
+
+ m_padding = padding;
+ emit paddingChanged();
+ }
+
+ const Padding &padding() const{ return m_padding; }
+
+signals:
+ void paddingChanged();
+
+private:
+ Padding m_padding{ 17, 17 };
};
void registerTypes();
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp
index 5a36c6edd3..da7e14411d 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp
+++ b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -41,6 +41,7 @@ private slots:
void structured();
void recursive();
void date();
+ void constructors();
};
void tst_qqmlvaluetypeproviders::initTestCase()
@@ -253,7 +254,6 @@ void tst_qqmlvaluetypeproviders::structured()
" with value [object Object]",
"Could not find any constructor for value type ConstructibleValueType to call"
" with value QVariant(QJSValue, )",
- "Could not convert QLocale(English, Latin, Australia) to double for property y",
"Could not find any constructor for value type ConstructibleValueType to call"
" with value [object Object]",
"Could not find any constructor for value type ConstructibleValueType to call"
@@ -292,8 +292,16 @@ void tst_qqmlvaluetypeproviders::structured()
QCOMPARE(o->property("c3").value<ConstructibleValueType>(), ConstructibleValueType(99));
QCOMPARE(o->property("c4").value<ConstructibleValueType>(), ConstructibleValueType(0));
- QCOMPARE(o->property("ps").value<QList<QPointF>>(),
- QList<QPointF>({QPointF(1, 2), QPointF(3, 4), QPointF(55, 0)}));
+ const QList<QPointF> actual = o->property("ps").value<QList<QPointF>>();
+ const QList<QPointF> expected = {
+ QPointF(1, 2), QPointF(3, 4), QPointF(55, std::numeric_limits<double>::quiet_NaN())
+ };
+ QCOMPARE(actual.size(), expected.size());
+ QCOMPARE(actual[0], expected[0]);
+ QCOMPARE(actual[1], expected[1]);
+ QCOMPARE(actual[2].x(), expected[2].x());
+ QVERIFY(std::isnan(actual[2].y()));
+
QCOMPARE(o->property("ss").value<QList<QSizeF>>(),
QList<QSizeF>({QSizeF(5, 6), QSizeF(7, 8), QSizeF(-1, 99)}));
QCOMPARE(o->property("cs").value<QList<ConstructibleValueType>>(),
@@ -343,6 +351,112 @@ void tst_qqmlvaluetypeproviders::structured()
ConstructibleFromQReal(-112.5));
QCOMPARE(o->property("cr7").value<ConstructibleFromQReal>(),
ConstructibleFromQReal(50));
+
+ BarrenValueType barren;
+ barren.setI(17);
+ QCOMPARE(o->property("barren").value<BarrenValueType>(), barren);
+
+ QMetaObject::invokeMethod(o.data(), "changeBarren");
+ QCOMPARE(o->property("barren").value<BarrenValueType>(), BarrenValueType(QString()));
+
+ QCOMPARE(o->property("fromObject").value<ConstructibleValueType>(),
+ ConstructibleValueType(nullptr));
+ QCOMPARE(o->property("aVariant").value<ConstructibleValueType>(),
+ ConstructibleValueType(nullptr));
+
+ QCOMPARE(o->property("listResult").toInt(), 12 + 67 + 68);
+
+
+ // You can store all kinds of insanity in a VariantObject, but we generally don't.
+ // Since we cannot rule out the possibility of there being such VariantObjects, we need to test
+ // their conversions.
+
+
+ QCOMPARE(o->property("fromInsanity").value<StructuredValueType>(), StructuredValueType());
+
+ QV4::Scope scope(e.handle());
+ QV4::ScopedString name(scope, scope.engine->newString("insanity"));
+
+ QObject *po = o.data();
+ QV4::ScopedObject js(
+ scope, scope.engine->metaTypeToJS(QMetaType::fromType<MyTypeObject *>(), &po));
+
+ const QVariantHash hash {
+ {"i", 12},
+ {"c", QUrl("http://example.com")},
+ {"p", QVariantMap {
+ {"x", 17},
+ {"y", 18}
+ }}
+ };
+ QV4::ScopedValue hashValue(
+ scope, e.handle()->newVariantObject(QMetaType::fromType<QVariantHash>(), &hash));
+
+ js->put(name, hashValue);
+
+ StructuredValueType fromHash;
+ fromHash.setI(12);
+ fromHash.setC(ConstructibleValueType(QUrl()));
+ fromHash.setP(QPointF(17, 18));
+
+ QCOMPARE(o->property("fromInsanity").value<StructuredValueType>(), fromHash);
+
+ const QVariantMap map {
+ {"i", 13},
+ {"c", QVariant::fromValue(po) },
+ {"p", QVariantMap {
+ {"x", 19},
+ {"y", 20}
+ }}
+ };
+ QV4::ScopedValue mapValue(
+ scope, e.handle()->newVariantObject(QMetaType::fromType<QVariantMap>(), &map));
+ js->put(name, mapValue);
+
+ StructuredValueType fromMap;
+ fromMap.setI(13);
+ fromMap.setC(ConstructibleValueType(po));
+ fromMap.setP(QPointF(19, 20));
+
+ QCOMPARE(o->property("fromInsanity").value<StructuredValueType>(), fromMap);
+
+ BarrenValueType immediate;
+ immediate.setI(14);
+ QV4::ScopedValue immediateValue(
+ scope, e.handle()->newVariantObject(QMetaType::fromType<BarrenValueType>(), &immediate));
+ js->put(name, immediateValue);
+
+ StructuredValueType fromImmediate;
+ fromImmediate.setI(14);
+
+ QCOMPARE(o->property("fromInsanity").value<StructuredValueType>(), fromImmediate);
+
+ QQmlComponent c2(&e);
+ c2.setData(
+ "import QtQml; QtObject { property int i: 99; property point p: ({x: 3, y: 4}) }", QUrl());
+ QVERIFY(c2.isReady());
+ QScopedPointer<QObject> o2(c2.create());
+ QVERIFY(!o2.isNull());
+ QObject *object = o2.data();
+ QV4::ScopedValue objectValue(
+ scope, e.handle()->newVariantObject(QMetaType::fromType<QObject *>(), &object));
+ js->put(name, objectValue);
+
+ StructuredValueType fromObject;
+ fromObject.setI(99);
+ fromObject.setP(QPointF(3, 4));
+
+ QCOMPARE(o->property("fromInsanity").value<StructuredValueType>(), fromObject);
+
+ const MyTypeObject *m = static_cast<const MyTypeObject *>(po);
+ QVERIFY(!m->hasEffectPadding());
+ QMetaObject::invokeMethod(po, "updatePadding");
+ QVERIFY(m->hasEffectPadding());
+ QCOMPARE(m->effectPadding(), QRectF());
+ po->setProperty("newItemPadding", QRectF(1, 2, 3, 4));
+ QMetaObject::invokeMethod(po, "updatePadding");
+ QVERIFY(m->hasEffectPadding());
+ QCOMPARE(m->effectPadding(), QRectF(1, 2, 3, 4));
}
void tst_qqmlvaluetypeproviders::recursive()
@@ -363,6 +477,9 @@ void tst_qqmlvaluetypeproviders::recursive()
MyTypeObject *m = qobject_cast<MyTypeObject *>(o.data());
QCOMPARE(m->structured().p().x(), 76);
+
+ // Recursive write back into a list detached from the property.
+ QCOMPARE(m->property("aa").toInt(), 12);
}
void tst_qqmlvaluetypeproviders::date()
@@ -379,6 +496,72 @@ void tst_qqmlvaluetypeproviders::date()
QCOMPARE(o->property("aVariant").value<QDateTime>().time().minute(), 44);
}
+void tst_qqmlvaluetypeproviders::constructors()
+{
+
+ QQmlEngine e;
+
+ {
+ const auto guard = qScopeGuard([]() { Padding::log.clear(); });
+ QQmlComponent component(&e);
+ component.setData("import Test\nMyItem { padding : 50 }", QUrl());
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+ MyItem *item = qobject_cast<MyItem *>(o.data());
+ QVERIFY(item);
+ QCOMPARE(item->padding().left(), 50);
+ QCOMPARE(item->padding().right(), 50);
+
+ QCOMPARE(Padding::log.length(), 3);
+
+ // Created by default ctor of MyItem
+ QCOMPARE(Padding::log[0].type, Padding::CustomCtor);
+ QCOMPARE(Padding::log[0].left, 17);
+ QCOMPARE(Padding::log[0].right, 17);
+
+ // Created by assignment of integer
+ QCOMPARE(Padding::log[1].type, Padding::InvokableCtor);
+ QCOMPARE(Padding::log[1].left, 50);
+ QCOMPARE(Padding::log[1].right, 50);
+
+ // In MyItem::setPadding()
+ QCOMPARE(Padding::log[2].type, Padding::CopyAssign);
+ QCOMPARE(Padding::log[2].left, 50);
+ QCOMPARE(Padding::log[2].right, 50);
+ }
+
+ {
+ const auto guard = qScopeGuard([]() { Padding::log.clear(); });
+ QQmlComponent component(&e);
+ component.setData("import Test\nMyItem { padding: ({ left: 10, right: 20 }) }", QUrl());
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+ MyItem *item = qobject_cast<MyItem *>(o.data());
+ QVERIFY(item);
+ QCOMPARE(item->padding().left(), 10);
+ QCOMPARE(item->padding().right(), 20);
+
+ QCOMPARE(Padding::log.length(), 3);
+
+ // Created by default ctor of MyItem
+ QCOMPARE(Padding::log[0].type, Padding::CustomCtor);
+ QCOMPARE(Padding::log[0].left, 17);
+ QCOMPARE(Padding::log[0].right, 17);
+
+ // Preparing for setting properties of structured value
+ QCOMPARE(Padding::log[1].type, Padding::DefaultCtor);
+ QCOMPARE(Padding::log[1].left, 0);
+ QCOMPARE(Padding::log[1].right, 0);
+
+ // In MyItem::setPadding()
+ QCOMPARE(Padding::log[2].type, Padding::CopyAssign);
+ QCOMPARE(Padding::log[2].left, 10);
+ QCOMPARE(Padding::log[2].right, 20);
+ }
+}
+
QTEST_MAIN(tst_qqmlvaluetypeproviders)
#include "tst_qqmlvaluetypeproviders.moc"
diff --git a/tests/auto/qml/qqmlvaluetypes/CMakeLists.txt b/tests/auto/qml/qqmlvaluetypes/CMakeLists.txt
index fd4bbc1c3f..e167aade13 100644
--- a/tests/auto/qml/qqmlvaluetypes/CMakeLists.txt
+++ b/tests/auto/qml/qqmlvaluetypes/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlvaluetypes Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlvaluetypes LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlvaluetypes/data/constructors.qml b/tests/auto/qml/qqmlvaluetypes/data/constructors.qml
new file mode 100644
index 0000000000..d94d6d8ad4
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypes/data/constructors.qml
@@ -0,0 +1,14 @@
+import QtQuick as Q
+
+Q.QtObject {
+ property var point: new Q.point()
+ property var size: new Q.size()
+ property var rect: new Q.rect()
+ property var color: new Q.color()
+ property var vector2d: new Q.vector2d()
+ property var vector3d: new Q.vector3d()
+ property var vector4d: new Q.vector4d()
+ property var quaternion: new Q.quaternion()
+ property var matrix4x4: new Q.matrix4x4()
+ property var font: new Q.font()
+}
diff --git a/tests/auto/qml/qqmlvaluetypes/data/matrix4x4_invokables.qml b/tests/auto/qml/qqmlvaluetypes/data/matrix4x4_invokables.qml
index c28901956d..1827b57ca9 100644
--- a/tests/auto/qml/qqmlvaluetypes/data/matrix4x4_invokables.qml
+++ b/tests/auto/qml/qqmlvaluetypes/data/matrix4x4_invokables.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick
Item {
property bool success: false
@@ -6,6 +6,7 @@ Item {
property variant m1: Qt.matrix4x4(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4)
property variant m2: Qt.matrix4x4(5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8)
property variant m3: Qt.matrix4x4(123,22,6,42,55,54,67,77,777,1,112,22,55,6696,77,777)
+ property matrix4x4 m4: PlanarTransform.fromAffineMatrix(1, 2, 3, 4, 5, 6)
property variant v1: Qt.vector4d(1,2,3,4)
property variant v2: Qt.vector3d(1,2,3)
property real factor: 2.23
@@ -101,6 +102,7 @@ Item {
if (m1.transposed() != Qt.matrix4x4(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4)) success = false;
if (m1.fuzzyEquals(m2)) success = false;
if (!m1.fuzzyEquals(m2, 10)) success = false;
+ if (m4 != Qt.matrix4x4(1, 3, 0, 5, 2, 4, 0, 6, 0, 0, 1, 0, 0, 0, 0, 1)) success = false;
if (!testTransformation()) success = false;
if (!testMatrixMapping()) success = false;
}
diff --git a/tests/auto/qml/qqmlvaluetypes/testtypes.cpp b/tests/auto/qml/qqmlvaluetypes/testtypes.cpp
index 4344445514..d6304bf086 100644
--- a/tests/auto/qml/qqmlvaluetypes/testtypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/testtypes.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testtypes.h"
void registerTypes()
diff --git a/tests/auto/qml/qqmlvaluetypes/testtypes.h b/tests/auto/qml/qqmlvaluetypes/testtypes.h
index 2c431c64af..19cfc25d23 100644
--- a/tests/auto/qml/qqmlvaluetypes/testtypes.h
+++ b/tests/auto/qml/qqmlvaluetypes/testtypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPES_H
#define TESTTYPES_H
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index 1f9dfb7fd4..ea521053ae 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -78,6 +78,7 @@ private slots:
void writeBackOnFunctionCall();
void valueTypeConversions();
void readReferenceOnGetOwnProperty();
+ void constructors();
private:
QQmlEngine engine;
@@ -93,30 +94,26 @@ void tst_qqmlvaluetypes::point()
{
{
QQmlComponent component(&engine, testFileUrl("point_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->property("p_x").toInt(), 10);
QCOMPARE(object->property("p_y").toInt(), 4);
QCOMPARE(object->property("copy"), QVariant(QPoint(10, 4)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("point_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->point(), QPoint(11, 12));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("point_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QPoint(10, 4)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -129,8 +126,6 @@ void tst_qqmlvaluetypes::point()
QCOMPARE(object->property("equalsSelf").toBool(), true);
QCOMPARE(object->property("equalsOther").toBool(), false);
QCOMPARE(object->property("pointEqualsPointf").toBool(), true);
-
- delete object;
}
}
@@ -138,30 +133,26 @@ void tst_qqmlvaluetypes::pointf()
{
{
QQmlComponent component(&engine, testFileUrl("pointf_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(float(object->property("p_x").toDouble()), float(11.3));
QCOMPARE(float(object->property("p_y").toDouble()), float(-10.9));
QCOMPARE(object->property("copy"), QVariant(QPointF(11.3, -10.9)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("pointf_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->pointf(), QPointF(6.8, 9.3));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("pointf_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QPointF(11.3, -10.9)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -174,8 +165,6 @@ void tst_qqmlvaluetypes::pointf()
QCOMPARE(object->property("equalsSelf").toBool(), true);
QCOMPARE(object->property("equalsOther").toBool(), false);
QCOMPARE(object->property("pointfEqualsPoint").toBool(), true);
-
- delete object;
}
}
@@ -183,30 +172,26 @@ void tst_qqmlvaluetypes::size()
{
{
QQmlComponent component(&engine, testFileUrl("size_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->property("s_width").toInt(), 1912);
QCOMPARE(object->property("s_height").toInt(), 1913);
QCOMPARE(object->property("copy"), QVariant(QSize(1912, 1913)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("size_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->size(), QSize(13, 88));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("size_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QSize(1912, 1913)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -219,8 +204,6 @@ void tst_qqmlvaluetypes::size()
QCOMPARE(object->property("equalsSelf").toBool(), true);
QCOMPARE(object->property("equalsOther").toBool(), false);
QCOMPARE(object->property("sizeEqualsSizef").toBool(), true);
-
- delete object;
}
}
@@ -228,30 +211,26 @@ void tst_qqmlvaluetypes::sizef()
{
{
QQmlComponent component(&engine, testFileUrl("sizef_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(float(object->property("s_width").toDouble()), float(0.1));
QCOMPARE(float(object->property("s_height").toDouble()), float(100923.2));
QCOMPARE(object->property("copy"), QVariant(QSizeF(0.1, 100923.2)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("sizef_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->sizef(), QSizeF(44.3, 92.8));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("sizef_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QSizeF(0.1, 100923)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -264,8 +243,6 @@ void tst_qqmlvaluetypes::sizef()
QCOMPARE(object->property("equalsSelf").toBool(), true);
QCOMPARE(object->property("equalsOther").toBool(), false);
QCOMPARE(object->property("sizefEqualsSize").toBool(), true);
-
- delete object;
}
}
@@ -299,9 +276,9 @@ void tst_qqmlvaluetypes::locale()
QCOMPARE(object->property("textDirection").toInt(), int(locale.textDirection()));
QCOMPARE(object->property("uiLanguages").toStringList(), locale.uiLanguages());
QList<Qt::DayOfWeek> weekDays;
- foreach (const QVariant &weekDay, object->property("weekDays").toList()) {
+ const QVariantList weekDaysProperty = object->property("weekDays").toList();
+ for (const QVariant &weekDay : weekDaysProperty)
weekDays.append(Qt::DayOfWeek(weekDay.toInt()));
- }
QCOMPARE(weekDays, locale.weekdays());
QCOMPARE(object->property("zeroDigit").toString().at(0), locale.zeroDigit());
#endif // im
@@ -311,29 +288,25 @@ void tst_qqmlvaluetypes::locale()
void tst_qqmlvaluetypes::qmlproperty()
{
QQmlComponent component(&engine, testFileUrl("qmlproperty_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
- QCOMPARE(object->property("colorPropertyObject").value<QObject *>(), object);
+ QCOMPARE(object->property("colorPropertyObject").value<QObject *>(), object.get());
QCOMPARE(object->property("colorPropertyName").toString(), "color");
QCOMPARE(object->property("invalidPropertyObject").value<QObject *>(), nullptr);
QCOMPARE(object->property("invalidPropertyName").toString(), "");
-
- delete object;
}
void tst_qqmlvaluetypes::sizereadonly()
{
{
QQmlComponent component(&engine, testFileUrl("sizereadonly_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->property("s_width").toInt(), 1912);
QCOMPARE(object->property("s_height").toInt(), 1913);
QCOMPARE(object->property("copy"), QVariant(QSize(1912, 1913)));
-
- delete object;
}
{
@@ -357,12 +330,10 @@ void tst_qqmlvaluetypes::sizereadonly()
{
QQmlComponent component(&engine, testFileUrl("sizereadonly_writeerror4.qml"));
- QObject *object = component.create();
+ std::unique_ptr<QObject> object { component.create() };
QVERIFY(object);
QCOMPARE(object->property("sizereadonly").toSize(), QSize(1912, 1913));
-
- delete object;
}
}
@@ -370,8 +341,8 @@ void tst_qqmlvaluetypes::rect()
{
{
QQmlComponent component(&engine, testFileUrl("rect_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->property("r_x").toInt(), 2);
QCOMPARE(object->property("r_y").toInt(), 3);
@@ -382,24 +353,20 @@ void tst_qqmlvaluetypes::rect()
QCOMPARE(object->property("r_top").toInt(), 3);
QCOMPARE(object->property("r_bottom").toInt(), 104);
QCOMPARE(object->property("copy"), QVariant(QRect(2, 3, 109, 102)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("rect_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect(), QRect(1234, 7, 56, 63));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("rect_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QRect(2, 3, 109, 102)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -412,8 +379,6 @@ void tst_qqmlvaluetypes::rect()
QCOMPARE(object->property("equalsSelf").toBool(), true);
QCOMPARE(object->property("equalsOther").toBool(), false);
QCOMPARE(object->property("rectEqualsRectf").toBool(), true);
-
- delete object;
}
}
@@ -421,8 +386,8 @@ void tst_qqmlvaluetypes::rectf()
{
{
QQmlComponent component(&engine, testFileUrl("rectf_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(float(object->property("r_x").toDouble()), float(103.8));
QCOMPARE(float(object->property("r_y").toDouble()), float(99.2));
@@ -433,24 +398,20 @@ void tst_qqmlvaluetypes::rectf()
QCOMPARE(float(object->property("r_top").toDouble()), float(99.2));
QCOMPARE(float(object->property("r_bottom").toDouble()), float(176.8));
QCOMPARE(object->property("copy"), QVariant(QRectF(103.8, 99.2, 88.1, 77.6)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("rectf_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rectf(), QRectF(70.1, -113.2, 80924.8, 99.2));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("rectf_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QRectF(103.8, 99.2, 88.1, 77.6)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -463,8 +424,6 @@ void tst_qqmlvaluetypes::rectf()
QCOMPARE(object->property("equalsSelf").toBool(), true);
QCOMPARE(object->property("equalsOther").toBool(), false);
QCOMPARE(object->property("rectfEqualsRect").toBool(), true);
-
- delete object;
}
}
@@ -472,30 +431,26 @@ void tst_qqmlvaluetypes::vector2d()
{
{
QQmlComponent component(&engine, testFileUrl("vector2d_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE((float)object->property("v_x").toDouble(), (float)32.88);
QCOMPARE((float)object->property("v_y").toDouble(), (float)1.3);
QCOMPARE(object->property("copy"), QVariant(QVector2D(32.88f, 1.3f)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector2d_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->vector2(), QVector2D(-0.3f, -12.9f));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector2d_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QVector2D(32.88, 1.3)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -506,16 +461,13 @@ void tst_qqmlvaluetypes::vector2d()
QCOMPARE(object->property("equalsPoint").toBool(), false);
QCOMPARE(object->property("equalsRect").toBool(), false);
QCOMPARE(object->property("equalsSelf").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector2d_invokables.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QVERIFY(object->property("success").toBool());
- delete object;
}
}
@@ -523,31 +475,27 @@ void tst_qqmlvaluetypes::vector3d()
{
{
QQmlComponent component(&engine, testFileUrl("vector3d_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE((float)object->property("v_x").toDouble(), (float)23.88);
QCOMPARE((float)object->property("v_y").toDouble(), (float)3.1);
QCOMPARE((float)object->property("v_z").toDouble(), (float)4.3);
QCOMPARE(object->property("copy"), QVariant(QVector3D(23.88f, 3.1f, 4.3f)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector3d_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->vector(), QVector3D(-0.3f, -12.9f, 907.4f));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector3d_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QVector3D(23.88, 3.1, 4.3)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -559,16 +507,13 @@ void tst_qqmlvaluetypes::vector3d()
QCOMPARE(object->property("equalsRect").toBool(), false);
QCOMPARE(object->property("equalsSelf").toBool(), true);
QCOMPARE(object->property("equalsOther").toBool(), false);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector3d_invokables.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QVERIFY(object->property("success").toBool());
- delete object;
}
}
@@ -576,32 +521,28 @@ void tst_qqmlvaluetypes::vector4d()
{
{
QQmlComponent component(&engine, testFileUrl("vector4d_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE((float)object->property("v_x").toDouble(), (float)54.2);
QCOMPARE((float)object->property("v_y").toDouble(), (float)23.88);
QCOMPARE((float)object->property("v_z").toDouble(), (float)3.1);
QCOMPARE((float)object->property("v_w").toDouble(), (float)4.3);
QCOMPARE(object->property("copy"), QVariant(QVector4D(54.2f, 23.88f, 3.1f, 4.3f)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector4d_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->vector4(), QVector4D(-0.3f, -12.9f, 907.4f, 88.5f));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector4d_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QVector4D(54.2, 23.88, 3.1, 4.3)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -612,16 +553,13 @@ void tst_qqmlvaluetypes::vector4d()
QCOMPARE(object->property("equalsPoint").toBool(), false);
QCOMPARE(object->property("equalsRect").toBool(), false);
QCOMPARE(object->property("equalsSelf").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector4d_invokables.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QVERIFY(object->property("success").toBool());
- delete object;
}
}
@@ -629,32 +567,28 @@ void tst_qqmlvaluetypes::quaternion()
{
{
QQmlComponent component(&engine, testFileUrl("quaternion_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE((float)object->property("v_scalar").toDouble(), (float)4.3);
QCOMPARE((float)object->property("v_x").toDouble(), (float)54.2);
QCOMPARE((float)object->property("v_y").toDouble(), (float)23.88);
QCOMPARE((float)object->property("v_z").toDouble(), (float)3.1);
QCOMPARE(object->property("copy"), QVariant(QQuaternion(4.3f, 54.2f, 23.88f, 3.1f)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("quaternion_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->quaternion(), QQuaternion(88.5f, -0.3f, -12.9f, 907.4f));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("quaternion_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QQuaternion(4.3, 54.2, 23.88, 3.1)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -665,16 +599,13 @@ void tst_qqmlvaluetypes::quaternion()
QCOMPARE(object->property("equalsPoint").toBool(), false);
QCOMPARE(object->property("equalsRect").toBool(), false);
QCOMPARE(object->property("equalsSelf").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("quaternion_invokables.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QVERIFY(object->property("success").toBool());
- delete object;
}
}
@@ -682,8 +613,8 @@ void tst_qqmlvaluetypes::matrix4x4()
{
{
QQmlComponent component(&engine, testFileUrl("matrix4x4_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE((float)object->property("v_m11").toDouble(), (float)1);
QCOMPARE((float)object->property("v_m12").toDouble(), (float)2);
@@ -706,27 +637,23 @@ void tst_qqmlvaluetypes::matrix4x4()
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("matrix4x4_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->matrix(), QMatrix4x4(11, 12, 13, 14,
21, 22, 23, 24,
31, 32, 33, 34,
41, 42, 43, 44));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("matrix4x4_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QMatrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -737,16 +664,13 @@ void tst_qqmlvaluetypes::matrix4x4()
QCOMPARE(object->property("equalsPoint").toBool(), false);
QCOMPARE(object->property("equalsRect").toBool(), false);
QCOMPARE(object->property("equalsSelf").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("matrix4x4_invokables.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("success").toBool(), true);
- delete object;
}
}
@@ -754,9 +678,9 @@ void tst_qqmlvaluetypes::font()
{
{
QQmlComponent component(&engine, testFileUrl("font_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QVERIFY(object != nullptr);
+ QVERIFY(object);
QCOMPARE(object->property("f_family").toString(), object->font().family());
QCOMPARE(object->property("f_bold").toBool(), object->font().bold());
@@ -783,14 +707,12 @@ void tst_qqmlvaluetypes::font()
QCOMPARE(object->property("f_wordSpacing").toDouble(), object->font().wordSpacing());
QCOMPARE(object->property("copy"), QVariant(object->font()));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("font_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QFont font;
font.setFamily("Helvetica");
@@ -815,46 +737,38 @@ void tst_qqmlvaluetypes::font()
QCOMPARE(f.capitalization(), font.capitalization());
QCOMPARE(f.letterSpacing(), font.letterSpacing());
QCOMPARE(f.wordSpacing(), font.wordSpacing());
-
- delete object;
}
// Test pixelSize
{
QQmlComponent component(&engine, testFileUrl("font_write.2.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().pixelSize(), 10);
-
- delete object;
}
// Test pixelSize and pointSize
{
QQmlComponent component(&engine, testFileUrl("font_write.3.qml"));
QTest::ignoreMessage(QtWarningMsg, "Both point size and pixel size set. Using pixel size.");
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().pixelSize(), 10);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("font_write.4.qml"));
QTest::ignoreMessage(QtWarningMsg, "Both point size and pixel size set. Using pixel size.");
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().pixelSize(), 10);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("font_write.5.qml"));
- QObject *object = qobject_cast<QObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { qobject_cast<QObject *>(component.create()) };
+ QVERIFY(object);
MyTypeObject *object1 = object->findChild<MyTypeObject *>("object1");
QVERIFY(object1 != nullptr);
MyTypeObject *object2 = object->findChild<MyTypeObject *>("object2");
@@ -862,14 +776,12 @@ void tst_qqmlvaluetypes::font()
QCOMPARE(object1->font().pixelSize(), 19);
QCOMPARE(object2->font().pointSize(), 14);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("font_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QFont(") + object->font().toString() + QLatin1Char(')');
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -880,8 +792,6 @@ void tst_qqmlvaluetypes::font()
QCOMPARE(object->property("equalsPoint").toBool(), false);
QCOMPARE(object->property("equalsRect").toBool(), false);
QCOMPARE(object->property("equalsSelf").toBool(), true);
-
- delete object;
}
}
@@ -889,8 +799,8 @@ void tst_qqmlvaluetypes::color()
{
{
QQmlComponent component(&engine, testFileUrl("color_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(float(object->property("v_r").toDouble()), 0.2f);
QCOMPARE(float(object->property("v_g").toDouble()), 0.88f);
@@ -916,14 +826,12 @@ void tst_qqmlvaluetypes::color()
comparison.setBlueF(0.6f);
comparison.setAlphaF(0.34f);
QCOMPARE(object->property("copy"), QVariant(comparison));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("color_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QColor newColor;
newColor.setRedF(0.5f);
@@ -931,38 +839,32 @@ void tst_qqmlvaluetypes::color()
newColor.setBlueF(0.3f);
newColor.setAlphaF(0.7f);
QCOMPARE(object->color(), newColor);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("color_write_HSV.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QColor newColor;
newColor.setHsvF(0.43f, 0.77f, 0.88f, 0.7f);
QCOMPARE(object->color(), newColor);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("color_write_HSL.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QColor newColor;
newColor.setHslF(0.43f, 0.74f, 0.54f, 0.7f);
QCOMPARE(object->color(), newColor);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("color_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QColor comparison;
comparison.setRedF(0.2f);
comparison.setGreenF(0.88f);
@@ -990,8 +892,6 @@ void tst_qqmlvaluetypes::color()
QCOMPARE(object->property("equalsColorRHS").toBool(), object->property("equalsColor").toBool());
QCOMPARE(object->property("colorEqualsCopy").toBool(), true);
QCOMPARE(object->property("copyEqualsColor").toBool(), object->property("colorEqualsCopy").toBool());
-
- delete object;
}
}
@@ -1001,8 +901,8 @@ void tst_qqmlvaluetypes::bindingAssignment()
// binding declaration
{
QQmlComponent component(&engine, testFileUrl("bindingAssignment.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect().x(), 10);
QCOMPARE(object->rect().y(), 15);
@@ -1011,8 +911,6 @@ void tst_qqmlvaluetypes::bindingAssignment()
QCOMPARE(object->rect().x(), 92);
QCOMPARE(object->rect().y(), 97);
-
- delete object;
}
// function assignment should fail without crashing
@@ -1022,12 +920,11 @@ void tst_qqmlvaluetypes::bindingAssignment()
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
QQmlComponent component(&engine, testFileUrl("bindingAssignment.2.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect().x(), 5);
object->setProperty("value", QVariant(92));
QCOMPARE(object->rect().x(), 5);
- delete object;
}
}
@@ -1035,42 +932,36 @@ void tst_qqmlvaluetypes::bindingAssignment()
void tst_qqmlvaluetypes::bindingRead()
{
QQmlComponent component(&engine, testFileUrl("bindingRead.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->property("value").toInt(), 2);
object->setRect(QRect(19, 3, 88, 2));
QCOMPARE(object->property("value").toInt(), 19);
-
- delete object;
}
// Test static values can assign to value types
void tst_qqmlvaluetypes::staticAssignment()
{
QQmlComponent component(&engine, testFileUrl("staticAssignment.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect().x(), 9);
-
- delete object;
}
// Test scripts can read/write value types
void tst_qqmlvaluetypes::scriptAccess()
{
QQmlComponent component(&engine, testFileUrl("scriptAccess.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->property("valuePre").toInt(), 2);
QCOMPARE(object->rect().x(), 19);
QCOMPARE(object->property("valuePost").toInt(), 19);
-
- delete object;
}
// Test that assigning a constant from script removes any binding
@@ -1078,8 +969,8 @@ void tst_qqmlvaluetypes::autoBindingRemoval()
{
{
QQmlComponent component(&engine, testFileUrl("autoBindingRemoval.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect().x(), 10);
@@ -1094,14 +985,12 @@ void tst_qqmlvaluetypes::autoBindingRemoval()
object->setProperty("value", QVariant(92));
QCOMPARE(object->rect().x(), 42);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("autoBindingRemoval.2.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect().x(), 10);
@@ -1116,16 +1005,14 @@ void tst_qqmlvaluetypes::autoBindingRemoval()
object->setProperty("value", QVariant(92));
QCOMPARE(object->rect(), QRect(10, 10, 10, 10));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("autoBindingRemoval.3.qml"));
QString warning = component.url().toString() + ":6:5: Unable to assign [undefined] to QRect";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
object->setProperty("value", QVariant(QRect(9, 22, 33, 44)));
@@ -1138,8 +1025,6 @@ void tst_qqmlvaluetypes::autoBindingRemoval()
object->setProperty("value", QVariant(QRect(19, 3, 4, 8)));
QCOMPARE(object->rect(), QRect(44, 22, 33, 44));
-
- delete object;
}
}
@@ -1147,12 +1032,10 @@ void tst_qqmlvaluetypes::autoBindingRemoval()
void tst_qqmlvaluetypes::valueSources()
{
QQmlComponent component(&engine, testFileUrl("valueSources.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect().x(), 3345);
-
- delete object;
}
static void checkNoErrors(QQmlComponent& component)
@@ -1170,17 +1053,15 @@ static void checkNoErrors(QQmlComponent& component)
void tst_qqmlvaluetypes::valueInterceptors()
{
QQmlComponent component(&engine, testFileUrl("valueInterceptors.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
checkNoErrors(component);
- QVERIFY(object != nullptr);
+ QVERIFY(object);
QCOMPARE(object->rect().x(), 13);
object->setProperty("value", 99);
QCOMPARE(object->rect().x(), 112);
-
- delete object;
}
// Test that you can't assign a binding to the "root" value type, and a sub-property
@@ -1192,11 +1073,10 @@ void tst_qqmlvaluetypes::bindingConflict()
#define CPP_TEST(type, v) \
{ \
- type *t = new type; \
+ std::unique_ptr<type> t = std::make_unique<type>(); \
QVariant value(v); \
t->setValue(value); \
QCOMPARE(t->value(), value); \
- delete t; \
}
// Test that accessing a reference to a valuetype after the owning object is deleted
@@ -1205,87 +1085,76 @@ void tst_qqmlvaluetypes::deletedObject()
{
QQmlComponent component(&engine, testFileUrl("deletedObject.qml"));
QTest::ignoreMessage(QtDebugMsg, "Test: 2");
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
- QObject *dObject = qvariant_cast<QObject *>(object->property("object"));
- QVERIFY(dObject != nullptr);
- delete dObject;
+ std::unique_ptr<QObject> dObject { qvariant_cast<QObject *>(object->property("object")) };
+ QVERIFY(dObject);
+ dObject.reset();
QTest::ignoreMessage(QtDebugMsg, "Test: undefined");
object->emitRunScript();
-
- delete object;
}
// Test that value types can be assigned to another value type property in a binding
void tst_qqmlvaluetypes::bindingVariantCopy()
{
QQmlComponent component(&engine, testFileUrl("bindingVariantCopy.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect(), QRect(19, 33, 5, 99));
-
- delete object;
}
// Test that value types can be assigned to another value type property in script
void tst_qqmlvaluetypes::scriptVariantCopy()
{
QQmlComponent component(&engine, testFileUrl("scriptVariantCopy.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect(), QRect(2, 3, 109, 102));
object->emitRunScript();
QCOMPARE(object->rect(), QRect(19, 33, 5, 99));
-
- delete object;
}
void tst_qqmlvaluetypes::enums()
{
{
QQmlComponent component(&engine, testFileUrl("enums.1.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("enums.2.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("enums.3.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("enums.4.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("enums.5.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
- delete object;
}
}
@@ -1295,83 +1164,73 @@ void tst_qqmlvaluetypes::conflictingBindings()
{
{
QQmlComponent component(&engine, testFileUrl("conflicting.1.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
- QMetaObject::invokeMethod(object, "toggle");
+ QMetaObject::invokeMethod(object.get(), "toggle");
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 6);
- QMetaObject::invokeMethod(object, "toggle");
+ QMetaObject::invokeMethod(object.get(), "toggle");
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("conflicting.2.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 6);
- QMetaObject::invokeMethod(object, "toggle");
+ QMetaObject::invokeMethod(object.get(), "toggle");
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
- QMetaObject::invokeMethod(object, "toggle");
+ QMetaObject::invokeMethod(object.get(), "toggle");
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 6);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("conflicting.3.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
- QMetaObject::invokeMethod(object, "toggle");
+ QMetaObject::invokeMethod(object.get(), "toggle");
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 24);
- QMetaObject::invokeMethod(object, "toggle");
+ QMetaObject::invokeMethod(object.get(), "toggle");
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
-
- delete object;
}
}
void tst_qqmlvaluetypes::returnValues()
{
QQmlComponent component(&engine, testFileUrl("returnValues.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test1").toBool(), true);
QCOMPARE(object->property("test2").toBool(), true);
QCOMPARE(object->property("size").toSize(), QSize(13, 14));
-
- delete object;
}
void tst_qqmlvaluetypes::varAssignment()
{
QQmlComponent component(&engine, testFileUrl("varAssignment.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("x").toInt(), 1);
QCOMPARE(object->property("y").toInt(), 2);
QCOMPARE(object->property("z").toInt(), 3);
-
- delete object;
}
// Test bindings splice together correctly
@@ -1379,77 +1238,63 @@ void tst_qqmlvaluetypes::bindingsSpliceCorrectly()
{
{
QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.1.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.2.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.3.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.4.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.5.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test").toBool(), true);
-
- delete object;
}
}
void tst_qqmlvaluetypes::nonValueTypeComparison()
{
QQmlComponent component(&engine, testFileUrl("nonValueTypeComparison.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test1").toBool(), true);
QCOMPARE(object->property("test2").toBool(), true);
-
- delete object;
}
void tst_qqmlvaluetypes::initializeByWrite()
{
QQmlComponent component(&engine, testFileUrl("initializeByWrite.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test").toBool(), true);
-
- delete object;
}
void tst_qqmlvaluetypes::groupedInterceptors_data()
@@ -1483,8 +1328,8 @@ void tst_qqmlvaluetypes::groupedInterceptors()
QFETCH(QColor, expectedFinalColor);
QQmlComponent component(&engine, testFileUrl(qmlfile));
- QObject *object = component.create();
- QVERIFY2(object != nullptr, qPrintable(component.errorString()));
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY2(object.get(), qPrintable(component.errorString()));
QColor initialColor = object->property("color").value<QColor>();
QVERIFY(fuzzyCompare(initialColor.redF(), expectedInitialColor.redF()));
@@ -1499,8 +1344,6 @@ void tst_qqmlvaluetypes::groupedInterceptors()
QVERIFY(fuzzyCompare(finalColor.greenF(), expectedFinalColor.greenF()));
QVERIFY(fuzzyCompare(finalColor.blueF(), expectedFinalColor.blueF()));
QVERIFY(fuzzyCompare(finalColor.alphaF(), expectedFinalColor.alphaF()));
-
- delete object;
}
struct MyDesk
@@ -1990,6 +1833,28 @@ void tst_qqmlvaluetypes::readReferenceOnGetOwnProperty()
QVERIFY(o->property("allo").toBool());
}
+void tst_qqmlvaluetypes::constructors()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("constructors.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("point"), QVariant(QPointF()));
+ QCOMPARE(o->property("size"), QVariant(QSizeF()));
+ QCOMPARE(o->property("rect"), QVariant(QRectF()));
+ QCOMPARE(o->property("color"), QVariant(QColor()));
+ QCOMPARE(o->property("vector2d"), QVariant(QVector2D()));
+ QCOMPARE(o->property("vector3d"), QVariant(QVector3D()));
+ QCOMPARE(o->property("vector4d"), QVariant(QVector4D()));
+ QCOMPARE(o->property("quaternion"), QVariant(QQuaternion()));
+ QCOMPARE(o->property("matrix4x4"), QVariant(QMatrix4x4()));
+ QCOMPARE(o->property("font"), QVariant(QFont()));
+
+}
+
#undef CHECK_TYPE_IS_NOT_VALUETYPE
QTEST_MAIN(tst_qqmlvaluetypes)
diff --git a/tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt b/tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt
index 529840c484..3d93585812 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt
+++ b/tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlxmlhttprequest Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlxmlhttprequest LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.expect b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.expect
index 6dba52d2de..15274c5e58 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.expect
@@ -1,13 +1,13 @@
PROPFIND /container/ HTTP/1.1
-Depth: 1
-Content-Length: 95
-Connection: Keep-Alive, Upgrade, HTTP2-Settings
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-Accept-Language: en-US,*
-Content-type:i application/xml; charset="utf-8"
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+depth: 1
+content-length: 95
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+accept-language: {{Ignore}}
+content-type:i application/xml; charset="utf-8"
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:">
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.expect b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.expect
index dc7217d45c..f7bb57ad89 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.expect
@@ -1,12 +1,12 @@
PROPFIND /file HTTP/1.1
-Content-Length: 192
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-Accept-Language: en-US,*
-Content-type: text/xml; charset="utf-8"
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+content-length: 192
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+accept-language: {{Ignore}}
+content-type: text/xml; charset="utf-8"
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:">
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.collection.allprop.qml b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.collection.allprop.qml
index 5c47a27420..624cdc4a41 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.collection.allprop.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.collection.allprop.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.response.qml b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.response.qml
index dbb57b3b1b..5249ad84c1 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.response.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.response.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.responseXML.qml b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.responseXML.qml
index ecc3627060..eb1dd53a97 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.responseXML.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.responseXML.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/abort.expect b/tests/auto/qml/qqmlxmlhttprequest/data/abort.expect
index 97c1661851..90e15895a6 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/abort.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/abort.expect
@@ -1,11 +1,11 @@
PUT /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Content-Type: text/plain;charset=UTF-8
-Content-Length: 10
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+content-type: text/plain;charset=UTF-8
+content-length: 10
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
Test Data
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/abort.qml b/tests/auto/qml/qqmlxmlhttprequest/data/abort.qml
index c8d8382c8f..f07ba2dbc6 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/abort.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/abort.qml
@@ -13,32 +13,25 @@ QtObject {
var x = new XMLHttpRequest;
x.open("GET", urlDummy);
x.setRequestHeader("Test-header", "TestValue");
- x.setRequestHeader("Accept-Language", "en-US");
x.send();
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
seenDone = true;
- } else if (x.readyState == XMLHttpRequest.UNSENT) {
+ else if (x.readyState == XMLHttpRequest.UNSENT)
didNotSeeUnsent = false;
- }
}
x.abort();
- if (x.readyState == XMLHttpRequest.UNSENT) {
+ if (x.readyState == XMLHttpRequest.UNSENT)
endStateUnsent = true;
- }
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.open("PUT", url);
- x.setRequestHeader("Accept-Language", "en-US");
x.send("Test Data\n");
}
}
-
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml b/tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml
index 7fcbc9367a..5933c3062d 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml
@@ -21,14 +21,10 @@ QtObject {
readyState = true;
x.open("PUT", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
x.abort();
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
@@ -53,8 +49,6 @@ QtObject {
}
}
-
x.send()
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml b/tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml
index 0a85c6b16f..36febc41dc 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml
@@ -21,9 +21,7 @@ QtObject {
readyState = true;
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
@@ -43,13 +41,10 @@ QtObject {
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
-
x.send()
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml b/tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml
index a9066093d4..cf38ca22df 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml
@@ -31,9 +31,7 @@ QtObject {
readyState = true;
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
@@ -43,7 +41,11 @@ QtObject {
openedException = true;
}
- var headers = "connection: close\r\ncontent-type: text/html; charset=UTF-8\r\ntest-header: TestValue\r\nmultitest-header: TestValue, SecondTestValue\r\ncontent-length: 11";
+ var headers = [ "connection: close",
+ "content-type: text/html; charset=UTF-8",
+ "test-header: TestValue",
+ "multitest-header: TestValue, SecondTestValue",
+ "content-length: 11" ].join("\r\n");
// Test to the end
x.onreadystatechange = function() {
@@ -52,7 +54,7 @@ QtObject {
headersReceivedHeader = (x.getAllResponseHeaders() == headers);
} else if (x.readyState == XMLHttpRequest.DONE) {
- doneState = headersReceivedState && true;
+ doneState = headersReceivedState;
doneHeader = (x.getAllResponseHeaders() == headers);
dataOK = (x.responseText == "QML Rocks!\n");
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.expect b/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.expect
index 2270e7f3aa..299bfd4689 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.expect
@@ -1,8 +1,8 @@
GET /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml b/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml
index 0219d7b2fc..02c1b6ef47 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml
@@ -37,9 +37,7 @@ QtObject {
readyState = true;
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
@@ -56,15 +54,20 @@ QtObject {
headersReceivedNullHeader = (x.getResponseHeader("Nonexistant-header") == "");
headersReceivedValidHeader = (x.getResponseHeader("Test-HEAder") == "TestValue");
- headersReceivedMultiValidHeader = (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue");
- headersReceivedCookieHeader = (x.getResponseHeader("Set-Cookie") == "" && x.getResponseHeader("Set-Cookie2") == "");
+ headersReceivedMultiValidHeader =
+ (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue");
+ headersReceivedCookieHeader =
+ (x.getResponseHeader("Set-Cookie") == ""
+ && x.getResponseHeader("Set-Cookie2") == "");
} else if (x.readyState == XMLHttpRequest.DONE) {
- doneState = headersReceivedState && true;
+ doneState = headersReceivedState;
doneNullHeader = (x.getResponseHeader("Nonexistant-header") == "");
doneValidHeader = (x.getResponseHeader("Test-HEAder") == "TestValue");
- doneMultiValidHeader = (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue");
- doneCookieHeader = (x.getResponseHeader("Set-Cookie") == "" && x.getResponseHeader("Set-Cookie2") == "");
+ doneMultiValidHeader =
+ (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue");
+ doneCookieHeader = (x.getResponseHeader("Set-Cookie") == ""
+ && x.getResponseHeader("Set-Cookie2") == "");
dataOK = (x.responseText == "QML Rocks!\n");
}
}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/noqmlcontext.js b/tests/auto/qml/qqmlxmlhttprequest/data/noqmlcontext.js
index adb7269310..4c592bc8de 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/noqmlcontext.js
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/noqmlcontext.js
@@ -1,11 +1,9 @@
(function(url, resultCollector) {
var x = new XMLHttpRequest;
x.open("GET", url);
- x.setRequestHeader("Accept-Language","en-US");
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
resultCollector.responseText = x.responseText
- }
}
x.send()
})
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/open.qml b/tests/auto/qml/qqmlxmlhttprequest/data/open.qml
index 6e7681dfb4..26934fabe9 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/open.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/open.qml
@@ -20,9 +20,7 @@ QtObject {
readyState = true;
x.open("GET", url);
- x.setRequestHeader("Accept-Language","en-US");
-
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
@@ -42,13 +40,10 @@ QtObject {
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
-
x.send()
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/open_network.expect b/tests/auto/qml/qqmlxmlhttprequest/data/open_network.expect
index 2270e7f3aa..299bfd4689 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/open_network.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/open_network.expect
@@ -1,8 +1,8 @@
GET /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/open_sync.qml b/tests/auto/qml/qqmlxmlhttprequest/data/open_sync.qml
index 3c73141954..24711de2b3 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/open_sync.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/open_sync.qml
@@ -7,7 +7,6 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("GET", url, false);
- x.setRequestHeader("Accept-Language", "en-US");
x.send();
responseText = x.responseText;
}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/open_user.qml b/tests/auto/qml/qqmlxmlhttprequest/data/open_user.qml
index 4eaef536b3..f22118a1b0 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/open_user.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/open_user.qml
@@ -20,9 +20,7 @@ QtObject {
readyState = true;
x.open("GET", url, true, "username", "password");
- x.setRequestHeader("Accept-Language","en-US");
-
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
@@ -42,13 +40,10 @@ QtObject {
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
-
x.send()
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/open_username.qml b/tests/auto/qml/qqmlxmlhttprequest/data/open_username.qml
index b8ce5361f3..b62b09097e 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/open_username.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/open_username.qml
@@ -21,7 +21,7 @@ QtObject {
x.open("GET", url, true, "sampleusername", "password");
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.qml b/tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.qml
new file mode 100644
index 0000000000..922147bc4e
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.qml
@@ -0,0 +1,20 @@
+import QtQuick
+
+QtObject {
+ property string url
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ let xhr = new XMLHttpRequest;
+ xhr.open("GET", url);
+ xhr.overrideMimeType('text/xml');
+
+ // Test to the end
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === XMLHttpRequest.DONE)
+ dataOK = xhr.responseXML !== null;
+ }
+
+ xhr.send();
+ }
+}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.reply b/tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.reply
new file mode 100644
index 0000000000..fed050b72d
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.reply
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OK
+Connection: close
+Content-Type: text/plain
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml b/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml
index b9f0ab6e66..15503d1bc6 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml
@@ -4,6 +4,7 @@ QtObject {
property string url
property int readSize: 0
property int status: 0
+ id: object
Component.onCompleted: {
@@ -13,7 +14,7 @@ QtObject {
request.onreadystatechange = function() {
if (request.readyState == XMLHttpRequest.DONE) {
- status = request.status;
+ object.status = request.status;
var arrayBuffer = request.response;
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.expect b/tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.expect
index 35d28ec76d..d18a95c7dd 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.expect
@@ -1,8 +1,8 @@
GET /gml_logo.png HTTP/1.1
-Accept-Language: en-US,*
-Content-Type: image/png
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+content-type: image/png
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect b/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect
index 9784ba4a80..0df27ead2c 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect
@@ -1,8 +1,8 @@
GET /json.data HTTP/1.1
-Accept-Language: en-US,*
-Content-Type: application/jsonrequest
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+content-type: application/jsonrequest
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/responseText.qml b/tests/auto/qml/qqmlxmlhttprequest/data/responseText.qml
index 4b216d9c85..cf06b6fda6 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/responseText.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/responseText.qml
@@ -22,8 +22,6 @@ QtObject {
unsent = (x.responseText == "");
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
opened = (x.responseText == "");
// Test to the end
@@ -40,8 +38,6 @@ QtObject {
dataOK = (x.responseText == expectedText);
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
reset = (x.responseText == "");
}
}
@@ -51,4 +47,3 @@ QtObject {
sent = (x.responseText == "");
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/responseURL.qml b/tests/auto/qml/qqmlxmlhttprequest/data/responseURL.qml
new file mode 100644
index 0000000000..3a35dcc882
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/responseURL.qml
@@ -0,0 +1,21 @@
+import QtQuick 2.0
+
+QtObject {
+ property string url
+ property string expectedURL
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("GET", url);
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState === XMLHttpRequest.DONE)
+ dataOK = (x.responseURL === expectedURL);
+ }
+
+ x.send()
+ }
+}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml
index 65ce90853d..1a3a5285c0 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml
@@ -7,13 +7,11 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("GET", "testdocument.html");
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send();
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.expect
index 64bd2b3818..708aa1a7f0 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.expect
@@ -1,11 +1,11 @@
POST /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Content-Type: text/plain;charset=UTF-8
-Content-Length: 13
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+content-type: text/plain;charset=UTF-8
+content-length: 13
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
My Sent Data
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.qml
index 57203433c0..2f794650ba 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.qml
@@ -2,19 +2,16 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("POST", url);
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send("My Sent Data\n");
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.10.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.10.expect
index 2bf3b5a081..bb82e8ba74 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.10.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.10.expect
@@ -1,11 +1,11 @@
OPTIONS /testdocument.html HTTP/1.1
-Accept-Language: en-US,*
-Content-Type: text/plain;charset=UTF-8
-Content-Length: 13
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+content-type: text/plain;charset=UTF-8
+content-length: 13
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
My Sent Data
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.expect
index 7132819c72..341fb36f2a 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.expect
Binary files differ
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.qml
index 25584a662b..136243bbb2 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.qml
@@ -2,19 +2,16 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("POST", url);
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
var data = new Uint8Array([1, 2, 3, 0, 3, 2, 1, 10])
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.2.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.2.qml
index e63d58fdb6..e3d55889d6 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.2.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.2.qml
@@ -2,23 +2,19 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("POST", url);
x.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send("My Sent Data\n");
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.3.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.3.qml
index cfd67a6a72..eaf5a057ae 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.3.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.3.qml
@@ -2,23 +2,19 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("POST", url);
x.setRequestHeader("Content-Type", "text/plain;charset=latin1");
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send("My Sent Data\n");
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.expect
index 270ee838d9..75e6758f14 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.expect
@@ -1,11 +1,11 @@
POST /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Content-Type: charset=UTF-8;text/plain
-Content-Length: 13
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+content-type: charset=UTF-8;text/plain
+content-length: 13
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
My Sent Data
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.qml
index 808fb3a18d..e65982e6cf 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.qml
@@ -2,23 +2,19 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("POST", url);
x.setRequestHeader("Content-Type", "charset=UTF-8;text/plain");
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send("My Sent Data\n");
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.5.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.5.qml
index c8735173d3..b3c24a5328 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.5.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.5.qml
@@ -2,23 +2,19 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("POST", url);
x.setRequestHeader("Content-Type", "charset=latin1;text/plain");
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send("My Sent Data\n");
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.expect
index f6c8083875..02062e905b 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.expect
@@ -1,11 +1,11 @@
PUT /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Content-Type: text/plain;charset=UTF-8
-Content-Length: 13
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+content-type: text/plain;charset=UTF-8
+content-length: 13
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
My Sent Data
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.qml
index ee6a9caa06..345d486669 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.qml
@@ -2,19 +2,16 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("PUT", url);
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send("My Sent Data\n");
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.7.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.7.qml
index 003a912818..a378624803 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.7.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.7.qml
@@ -2,23 +2,19 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("POST", url);
x.setRequestHeader("Content-Type", "text/plain");
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send("My Sent Data\n");
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.8.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.8.expect
index bcd7e79fc1..c580208eca 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.8.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.8.expect
@@ -1,8 +1,8 @@
OPTIONS / HTTP/1.1
-Content-Length: 0
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-Accept-Language: en-US,*
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+content-length: 0
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+accept-language: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.9.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.9.expect
index 2d4f2c3146..3a7ae3730d 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.9.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.9.expect
@@ -1,8 +1,8 @@
OPTIONS /testdocument.html HTTP/1.1
-Content-Length: 0
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-Accept-Language: en-US,*
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+content-length: 0
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+accept-language: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData.qml
index 336971c919..38fd3800d8 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData.qml
@@ -9,19 +9,14 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open(reqType, url);
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
- if (reqType == "HEAD" || reqType == "DELETE")
- dataOK = (x.responseText == "");
- else
- dataOK = (x.responseText == "QML Rocks!\n");
- }
+ let expect = reqType == "HEAD" || reqType == "DELETE" ? "" : "QML Rocks!\n";
+ if (x.readyState == XMLHttpRequest.DONE)
+ dataOK = (x.responseText == expect);
}
x.send("Data To Ignore");
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_DELETE.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_DELETE.expect
index 7d96c00101..feca475b75 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_DELETE.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_DELETE.expect
@@ -1,8 +1,8 @@
DELETE /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_GET.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_GET.expect
index 2270e7f3aa..299bfd4689 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_GET.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_GET.expect
@@ -1,8 +1,8 @@
GET /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_HEAD.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_HEAD.expect
index 064cf1b6b7..fa757aeac3 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_HEAD.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_HEAD.expect
@@ -1,8 +1,8 @@
HEAD /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.expect
index 55f7f7dceb..d6ff9854a5 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.expect
@@ -1,13 +1,13 @@
PATCH /qqmlxmlhttprequest.cpp HTTP/1.1
-Accept-Language: en-US
-If-Match: "ETagNumber"
-Content-Type: application/example
-Content-Length: 247
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+if-match: "ETagNumber"
+content-type: application/example
+content-length: 247
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
--- a/qqmlxmlhttprequest.cpp
+++ b/qqmlxmlhttprequest.cpp
@@ -15,4 +15,3 @@ Host: {{ServerHostUrl}}
- } else if (m_method == QLatin1String("OPTIONS")) {
+ } else if (m_method == QLatin1String("OPTIONS") ||
+ (m_method == QLatin1String("PATCH"))) {
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.qml
index 35a629fc92..d7d57b445c 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
@@ -12,7 +12,6 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("PATCH", url);
- x.setRequestHeader("Accept-Language","en-US");
x.setRequestHeader("If-Match","\"ETagNumber\"");
// Test to the end
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.expect b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.expect
index 003e54f33c..29d2d22030 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.expect
@@ -1,10 +1,10 @@
GET /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Test-header: value
-Test-header2: value,value2
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+test-header: value
+test-header2: value,value2
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.qml b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.qml
index 4229584af2..1490d0f108 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.qml
@@ -2,14 +2,11 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
-
x.open("GET", url);
- x.setRequestHeader("Accept-Language","en-US");
x.setRequestHeader("Test-header", "value");
x.setRequestHeader("Test-header2", "value");
@@ -25,5 +22,3 @@ QtObject {
x.send();
}
}
-
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_caseInsensitive.qml b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_caseInsensitive.qml
index e03f73431a..015682b5d5 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_caseInsensitive.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_caseInsensitive.qml
@@ -9,12 +9,10 @@ QtObject {
var x = new XMLHttpRequest;
x.open("GET", url);
- x.setRequestHeader("Accept-Language","en-US");
-
x.setRequestHeader("Test-header", "value");
- //Setting headers with just different cases
- //will be treated as the same header, and accepted
- //as the last setting.
+
+ // Setting headers differing only in case will treat them as one header,
+ // and the values are joined with a comma.
x.setRequestHeader("Test-hEADEr2", "value");
x.setRequestHeader("Test-header2", "value2");
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_illegalName.qml b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_illegalName.qml
index cd047cf8dd..23a3c42fcc 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_illegalName.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_illegalName.qml
@@ -21,11 +21,9 @@ QtObject {
readyState = true;
x.open("GET", url);
- x.setRequestHeader("Accept-Language","en-US");
-
x.setRequestHeader(header, "Value");
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
@@ -45,14 +43,10 @@ QtObject {
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
-
x.send()
}
}
-
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_sent.qml b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_sent.qml
index 49888fdac8..2f37006de9 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_sent.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_sent.qml
@@ -8,9 +8,7 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
-
x.open("GET", url);
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
@@ -29,4 +27,3 @@ QtObject {
}
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/status.expect b/tests/auto/qml/qqmlxmlhttprequest/data/status.expect
index 2270e7f3aa..299bfd4689 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/status.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/status.expect
@@ -1,8 +1,8 @@
GET /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/status.qml b/tests/auto/qml/qqmlxmlhttprequest/data/status.qml
index 94908f63c0..ed7268d6b3 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/status.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/status.qml
@@ -30,8 +30,6 @@ QtObject {
}
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
try {
var a = x.status;
} catch (e) {
@@ -54,8 +52,6 @@ QtObject {
dataOK = (x.responseText == "QML Rocks!\n");
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
try {
var a = x.status;
} catch (e) {
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml b/tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml
index b47a0f1af0..cbc15b47f0 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml
@@ -27,8 +27,6 @@ QtObject {
}
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
try {
var a = x.statusText;
} catch (e) {
@@ -51,8 +49,6 @@ QtObject {
dataOK = (x.responseText == "QML Rocks!\n") && (x.response == "QML Rocks!\n");
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
try {
var a = x.statusText;
} catch (e) {
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/text.expect b/tests/auto/qml/qqmlxmlhttprequest/data/text.expect
new file mode 100644
index 0000000000..2b4314273f
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/text.expect
@@ -0,0 +1,6 @@
+GET /text.xml HTTP/1.1
+host: {{ServerHostUrl}}
+connection: Keep-Alive{{Ignore}}
+accept-encoding: {{Ignore}}
+accept-language: {{Ignore}}
+user-agent: {{Ignore}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
index 6517c58670..f908633193 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
+++ b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -75,6 +75,7 @@ private slots:
void statusText_data();
void responseText();
void responseText_data();
+ void responseURL();
void responseXML_invalid();
void invalidMethodUsage();
void redirects();
@@ -89,6 +90,8 @@ private slots:
void sendFileRequestNoRead();
#endif
+ void overrideMime();
+
// WebDAV
void sendPropfind();
void sendPropfind_data();
@@ -637,8 +640,6 @@ void tst_qqmlxmlhttprequest::send_options()
void tst_qqmlxmlhttprequest::send_options_data()
{
- if (QLocale::system() != QLocale(QLocale::English, QLocale::UnitedStates))
- QSKIP("Test is locale dependent");
QTest::addColumn<QString>("url_suffix");
QTest::addColumn<QString>("file_expected");
QTest::addColumn<QString>("file_qml");
@@ -863,8 +864,6 @@ void tst_qqmlxmlhttprequest::getAllResponseHeaders_args()
void tst_qqmlxmlhttprequest::getBinaryData()
{
- if (QLocale::system() != QLocale(QLocale::English, QLocale::UnitedStates))
- QSKIP("Test is locale dependent");
TestHTTPServer server;
QVERIFY2(server.listen(), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("receive_binary_data.expect"),
@@ -877,15 +876,13 @@ void tst_qqmlxmlhttprequest::getBinaryData()
object->setProperty("url", server.urlString("/gml_logo.png"));
component.completeCreate();
- QFileInfo fileInfo("data/qml_logo.png");
+ const QFileInfo fileInfo(testFile("qml_logo.png"));
QTRY_COMPARE(object->property("readSize").toInt(), fileInfo.size());
QCOMPARE(object->property("status").toInt(), 200);
}
void tst_qqmlxmlhttprequest::getJsonData()
{
- if (QLocale::system() != QLocale(QLocale::English, QLocale::UnitedStates))
- QSKIP("Test is locale dependent");
TestHTTPServer server;
QVERIFY2(server.listen(), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("receive_json_data.expect"),
@@ -1025,6 +1022,64 @@ void tst_qqmlxmlhttprequest::responseText_data()
QTest::newRow("Internal server error") << testFileUrl("status.500.reply") << testFileUrl("testdocument.html") << "QML Rocks!\n";
}
+
+void tst_qqmlxmlhttprequest::responseURL()
+{
+ // 200 OK
+ {
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ QVERIFY(server.wait(testFileUrl("status.expect"),
+ testFileUrl("status.200.reply"),
+ testFileUrl("testdocument.html")));
+
+ QQmlComponent component(engine.get(), testFileUrl("responseURL.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
+ QVERIFY(!object.isNull());
+ object->setProperty("url", server.urlString("/testdocument.html"));
+ object->setProperty("expectedURL", server.urlString("/testdocument.html"));
+ component.completeCreate();
+
+ QTRY_VERIFY(object->property("dataOK").toBool());
+ }
+
+ // 200 OK with the exclude fragment flag set
+ {
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ QVERIFY(server.wait(testFileUrl("status.expect"),
+ testFileUrl("status.200.reply"),
+ testFileUrl("testdocument.html")));
+
+ QQmlComponent component(engine.get(), testFileUrl("responseURL.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
+ QVERIFY(!object.isNull());
+ object->setProperty("url", server.urlString("/testdocument.html#fragment"));
+ object->setProperty("expectedURL", server.urlString("/testdocument.html"));
+ component.completeCreate();
+
+ QTRY_VERIFY(object->property("dataOK").toBool());
+ }
+
+ // 302 Found
+ {
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ server.addRedirect("redirect.html", server.urlString("/redirecttarget.html"));
+ server.serveDirectory(dataDirectory());
+
+ QQmlComponent component(engine.get(), testFileUrl("responseURL.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
+ QVERIFY(!object.isNull());
+ object->setProperty("url", server.urlString("/redirect.html"));
+ object->setProperty("expectedURL", server.urlString("/redirecttarget.html"));
+ component.completeCreate();
+
+ QTRY_VERIFY(object->property("dataOK").toBool());
+ }
+}
+
+
void tst_qqmlxmlhttprequest::nonUtf8()
{
QFETCH(QString, fileName);
@@ -1076,7 +1131,7 @@ void tst_qqmlxmlhttprequest::doFileRequest(std::function<void(QObject *component
QTemporaryFile writeFile;
QTemporaryFile readFile;
- writeFile.open();
+ QVERIFY(writeFile.open());
writeFile.close();
QVERIFY(readFile.open());
@@ -1242,8 +1297,6 @@ void tst_qqmlxmlhttprequest::sendFileRequestNoRead() {
void tst_qqmlxmlhttprequest::sendPropfind()
{
- if (QLocale::system() != QLocale(QLocale::English, QLocale::UnitedStates))
- QSKIP("Test is locale dependent");
const QString prefix = "WebDAV//";
QFETCH(QString, qml);
@@ -1277,14 +1330,17 @@ void tst_qqmlxmlhttprequest::sendPropfind_data()
QTest::addColumn<QString>("replyHeader");
QTest::addColumn<QString>("replyBody");
- QTest::newRow("Send PROPFIND for file (bigbox, author, DingALing, Random properties). Get response with responseXML.")
+ QTest::newRow("Send PROPFIND for file (bigbox, author, DingALing, Random properties). "
+ "Get response with responseXML.")
<< "sendPropfind.responseXML.qml" << "/file" << "propfind.file.expect"
<< "propfind.file.reply.header" << "propfind.file.reply.body";
- QTest::newRow("Send PROPFIND for file (bigbox, author, DingALing, Random properties). Get response with response.")
+ QTest::newRow("Send PROPFIND for file (bigbox, author, DingALing, Random properties). "
+ "Get response with response.")
<< "sendPropfind.response.qml" << "/file" << "propfind.file.expect"
<< "propfind.file.reply.header" << "propfind.file.reply.body";
QTest::newRow("Send PROPFIND \"allprop\" request for collection.")
- << "sendPropfind.collection.allprop.qml" << "/container/" << "propfind.collection.allprop.expect"
+ << "sendPropfind.collection.allprop.qml" << "/container/"
+ << "propfind.collection.allprop.expect"
<< "propfind.file.reply.header" << "propfind.collection.allprop.reply.body";
}
@@ -1323,7 +1379,6 @@ void tst_qqmlxmlhttprequest::redirects()
QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/redirect.html"));
- object->setProperty("expectedText", "");
component.completeCreate();
QTRY_VERIFY(object->property("done").toBool());
@@ -1340,7 +1395,6 @@ void tst_qqmlxmlhttprequest::redirects()
QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/redirect.html"));
- object->setProperty("expectedText", "");
component.completeCreate();
QTRY_VERIFY(object->property("done").toBool());
@@ -1357,7 +1411,6 @@ void tst_qqmlxmlhttprequest::redirects()
QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/redirect.html"));
- object->setProperty("expectedText", "");
component.completeCreate();
for (int ii = 0; ii < 60; ++ii) {
@@ -1489,6 +1542,26 @@ void tst_qqmlxmlhttprequest::stateChangeCallingContext()
QTRY_VERIFY(object->property("success").toBool());
}
+void tst_qqmlxmlhttprequest::overrideMime()
+{
+ // overrideMimeType.reply sets the Content-Type to text/plain
+ // overrideMimeType.qml overrides it to text/xml and checks the responseXML property.
+
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ QVERIFY(server.wait(testFileUrl("text.expect"),
+ testFileUrl("overrideMimeType.reply"),
+ testFileUrl("text.xml")));
+
+ QQmlComponent component(engine.get(), testFileUrl("overrideMimeType.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
+ QVERIFY(!object.isNull());
+ object->setProperty("url", server.urlString("/text.xml"));
+ component.completeCreate();
+
+ QTRY_VERIFY(object->property("dataOK").toBool());
+}
+
QTEST_MAIN(tst_qqmlxmlhttprequest)
#include "tst_qqmlxmlhttprequest.moc"
diff --git a/tests/auto/qml/qqmlxmllistmodel/CMakeLists.txt b/tests/auto/qml/qqmlxmllistmodel/CMakeLists.txt
index d0a8270faa..96ae64cd8d 100644
--- a/tests/auto/qml/qqmlxmllistmodel/CMakeLists.txt
+++ b/tests/auto/qml/qqmlxmllistmodel/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlxmllistmodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
data/*)
diff --git a/tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp b/tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp
index 0745853e02..bb6e59cb17 100644
--- a/tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp
+++ b/tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQmlXmlListModel/private/qqmlxmllistmodel_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -321,14 +321,12 @@ void tst_QQmlXmlListModel::headers()
QTRY_COMPARE_WITH_TIMEOUT(qvariant_cast<QQmlXmlListModel::Status>(model->property("status")),
QQmlXmlListModel::Error, 10000);
- QVariantMap expectedHeaders;
- expectedHeaders["Accept"] = "application/xml,*/*";
+ QLatin1String expectedAcceptHeader = "application/xml,*/*"_L1;
- QCOMPARE(factory.lastSentHeaders.size(), expectedHeaders.size());
- for (auto it = expectedHeaders.cbegin(), end = expectedHeaders.cend(); it != end; ++it) {
- QVERIFY(factory.lastSentHeaders.contains(it.key()));
- QCOMPARE(factory.lastSentHeaders[it.key()].toString(), it.value().toString());
- }
+ QCOMPARE(factory.lastSentHeaders.size(), 1);
+ QVariant acceptHeader = factory.lastSentHeaders["accept"];
+ QVERIFY(acceptHeader.isValid());
+ QCOMPARE(acceptHeader.toString(), expectedAcceptHeader);
}
void tst_QQmlXmlListModel::source()
@@ -435,8 +433,8 @@ void tst_QQmlXmlListModel::reload()
QVERIFY(model != nullptr);
QTRY_COMPARE(model->rowCount(), 9);
- QSignalSpy spyInsert(model.get(), SIGNAL(rowsInserted(QModelIndex, int, int)));
- QSignalSpy spyRemove(model.get(), SIGNAL(rowsRemoved(QModelIndex, int, int)));
+ QSignalSpy spyInsert(model.get(), SIGNAL(rowsInserted(QModelIndex,int,int)));
+ QSignalSpy spyRemove(model.get(), SIGNAL(rowsRemoved(QModelIndex,int,int)));
QSignalSpy spyCount(model.get(), SIGNAL(countChanged()));
// reload multiple times to test the xml query aborting
QMetaObject::invokeMethod(model.get(), "reload");
diff --git a/tests/auto/qml/qquickfolderlistmodel/CMakeLists.txt b/tests/auto/qml/qquickfolderlistmodel/CMakeLists.txt
index 37bd47de3a..39abeacbdf 100644
--- a/tests/auto/qml/qquickfolderlistmodel/CMakeLists.txt
+++ b/tests/auto/qml/qquickfolderlistmodel/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickfolderlistmodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickfolderlistmodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
index 6209e62a8f..f246e1af6d 100644
--- a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
+++ b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
#include <QtQml/qqmlengine.h>
diff --git a/tests/auto/qml/qquickworkerscript/CMakeLists.txt b/tests/auto/qml/qquickworkerscript/CMakeLists.txt
index 9ba3446659..e96fc74300 100644
--- a/tests/auto/qml/qquickworkerscript/CMakeLists.txt
+++ b/tests/auto/qml/qquickworkerscript/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickworkerscript Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickworkerscript LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
index 966aac6aaf..e209c3cdde 100644
--- a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
+++ b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtCore/qdebug.h>
#include <QtCore/qtimer.h>
@@ -102,21 +102,20 @@ void tst_QQuickWorkerScript::messaging()
QFETCH(QVariant, value);
QQmlComponent component(&m_engine, testFileUrl("worker.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
- waitForEchoMessage(worker);
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, value)));
+ waitForEchoMessage(worker.get());
const QMetaObject *mo = worker->metaObject();
- QVariant response = mo->property(mo->indexOfProperty("response")).read(worker).value<QVariant>();
+ QVariant response = mo->property(mo->indexOfProperty("response")).read(worker.get()).value<QVariant>();
if (response.userType() == qMetaTypeId<QJSValue>())
response = response.value<QJSValue>().toVariant();
QCOMPARE(response, value);
qApp->processEvents();
- delete worker;
}
void tst_QQuickWorkerScript::messaging_data()
@@ -142,29 +141,28 @@ void tst_QQuickWorkerScript::messaging_sendQObjectList()
// js values.
QQmlComponent component(&m_engine, testFileUrl("worker.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
QVariantList objects;
for (int i=0; i<3; i++)
objects << QVariant::fromValue(new QObject(this));
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, QVariant::fromValue(objects))));
- waitForEchoMessage(worker);
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, QVariant::fromValue(objects))));
+ waitForEchoMessage(worker.get());
const QMetaObject *mo = worker->metaObject();
- QVariantList result = mo->property(mo->indexOfProperty("response")).read(worker).value<QVariantList>();
+ QVariantList result = mo->property(mo->indexOfProperty("response")).read(worker.get()).value<QVariantList>();
QCOMPARE(result, (QVariantList() << QVariant() << QVariant() << QVariant()));
qApp->processEvents();
- delete worker;
}
void tst_QQuickWorkerScript::messaging_sendJsObject()
{
QQmlComponent component(&m_engine, testFileUrl("worker.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
// Properties are in alphabetical order to enable string-based comparison after
// QVariant roundtrip, since the properties will be stored in a QVariantMap.
@@ -175,26 +173,24 @@ void tst_QQuickWorkerScript::messaging_sendJsObject()
map.insert("name", "zyz");
map.insert("spell power", 3101);
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, QVariant::fromValue(map))));
- waitForEchoMessage(worker);
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, QVariant::fromValue(map))));
+ waitForEchoMessage(worker.get());
QVariant result = QVariant::fromValue(false);
- QVERIFY(QMetaObject::invokeMethod(worker, "compareLiteralResponse", Qt::DirectConnection,
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "compareLiteralResponse", Qt::DirectConnection,
Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, jsObject)));
QVERIFY(result.toBool());
qApp->processEvents();
- delete worker;
}
void tst_QQuickWorkerScript::messaging_sendExternalObject()
{
QQmlComponent component(&m_engine, testFileUrl("externalObjectWorker.qml"));
- QObject *obj = component.create();
- QVERIFY(obj);
- QMetaObject::invokeMethod(obj, "testExternalObject");
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj.get());
+ QMetaObject::invokeMethod(obj.get(), "testExternalObject");
QTest::qWait(100); // shouldn't crash.
- delete obj;
}
void tst_QQuickWorkerScript::script_with_pragma()
@@ -202,35 +198,33 @@ void tst_QQuickWorkerScript::script_with_pragma()
QVariant value(100);
QQmlComponent component(&m_engine, testFileUrl("worker_pragma.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
- waitForEchoMessage(worker);
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, value)));
+ waitForEchoMessage(worker.get());
const QMetaObject *mo = worker->metaObject();
- QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).value<QVariant>(), value);
+ QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker.get()).value<QVariant>(), value);
qApp->processEvents();
- delete worker;
}
void tst_QQuickWorkerScript::script_included()
{
QQmlComponent component(&m_engine, testFileUrl("worker_include.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
QString value("Hello");
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
- waitForEchoMessage(worker);
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, value)));
+ waitForEchoMessage(worker.get());
const QMetaObject *mo = worker->metaObject();
- QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).toString(), value + " World");
+ QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker.get()).toString(), value + " World");
qApp->processEvents();
- delete worker;
}
static QString qquickworkerscript_lastWarning;
@@ -245,69 +239,65 @@ void tst_QQuickWorkerScript::scriptError_onLoad()
QQmlComponent component(&m_engine, testFileUrl("worker_error_onLoad.qml"));
QtMessageHandler previousMsgHandler = qInstallMessageHandler(qquickworkerscript_warningsHandler);
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
QTRY_COMPARE(qquickworkerscript_lastWarning,
testFileUrl("script_error_onLoad.js").toString() + QLatin1String(":3:10: SyntaxError: Expected token `,'"));
qInstallMessageHandler(previousMsgHandler);
qApp->processEvents();
- delete worker;
}
void tst_QQuickWorkerScript::scriptError_onCall()
{
QQmlComponent component(&m_engine, testFileUrl("worker_error_onCall.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
QtMessageHandler previousMsgHandler = qInstallMessageHandler(qquickworkerscript_warningsHandler);
QVariant value;
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, value)));
QTRY_COMPARE(qquickworkerscript_lastWarning,
testFileUrl("script_error_onCall.js").toString() + QLatin1String(":4: ReferenceError: getData is not defined"));
qInstallMessageHandler(previousMsgHandler);
qApp->processEvents();
- delete worker;
}
void tst_QQuickWorkerScript::script_function()
{
QQmlComponent component(&m_engine, testFileUrl("worker_function.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
QString value("Hello");
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
- waitForEchoMessage(worker);
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, value)));
+ waitForEchoMessage(worker.get());
const QMetaObject *mo = worker->metaObject();
- QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).toString(), value + " World");
+ QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker.get()).toString(), value + " World");
qApp->processEvents();
- delete worker;
}
void tst_QQuickWorkerScript::script_var()
{
QQmlComponent component(&m_engine, testFileUrl("worker_var.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
QString value("Hello");
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
- waitForEchoMessage(worker);
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, value)));
+ waitForEchoMessage(worker.get());
const QMetaObject *mo = worker->metaObject();
- QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).toString(), value + " World");
+ QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker.get()).toString(), value + " World");
qApp->processEvents();
- delete worker;
}
// Rapidly create and destroy worker scripts to test resources are being disposed
@@ -317,9 +307,8 @@ void tst_QQuickWorkerScript::stressDispose()
for (int ii = 0; ii < 100; ++ii) {
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("stressDispose.qml"));
- QObject *o = component.create();
- QVERIFY(o);
- delete o;
+ std::unique_ptr<QObject> o { component.create() };
+ QVERIFY(o.get());
}
}
diff --git a/tests/auto/qml/qrcqml/CMakeLists.txt b/tests/auto/qml/qrcqml/CMakeLists.txt
index de081545cb..c793f1363c 100644
--- a/tests/auto/qml/qrcqml/CMakeLists.txt
+++ b/tests/auto/qml/qrcqml/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qrcqml Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qrcqml LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qrcqml
SOURCES
tst_qrcqml.cpp
diff --git a/tests/auto/qml/qrcqml/tst_qrcqml.cpp b/tests/auto/qml/qrcqml/tst_qrcqml.cpp
index 5f77083c4e..a9be307c23 100644
--- a/tests/auto/qml/qrcqml/tst_qrcqml.cpp
+++ b/tests/auto/qml/qrcqml/tst_qrcqml.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QObject>
@@ -59,10 +59,9 @@ void tst_qrcqml::basicLoad()
QQmlEngine e;
QQmlComponent c(&e, QUrl(url));
QVERIFY(c.isReady());
- QObject* o = c.create();
- QVERIFY(o);
+ std::unique_ptr<QObject> o { c.create() };
+ QVERIFY(o.get());
QCOMPARE(o->property("tokenProperty").toString(), token);
- delete o;
}
void tst_qrcqml::qrcImport_data()
@@ -88,10 +87,9 @@ void tst_qrcqml::qrcImport()
e.addImportPath(importPath);
QQmlComponent c(&e, QUrl("qrc:///importtest.qml"));
QVERIFY(c.isReady());
- QObject *o = c.create();
- QVERIFY(o);
+ std::unique_ptr<QObject> o { c.create() };
+ QVERIFY(o.get());
QCOMPARE(o->property("tokenProperty").toString(), token);
- delete o;
}
QTEST_MAIN(tst_qrcqml)
diff --git a/tests/auto/qml/qtqmlmodules/CMakeLists.txt b/tests/auto/qml/qtqmlmodules/CMakeLists.txt
index 59033ae690..a6ae2ec9f7 100644
--- a/tests/auto/qml/qtqmlmodules/CMakeLists.txt
+++ b/tests/auto/qml/qtqmlmodules/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qtqmlmodules Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qtqmlmodules LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qtqmlmodules/tst_qtqmlmodules.cpp b/tests/auto/qml/qtqmlmodules/tst_qtqmlmodules.cpp
index 88fd0e6bc0..62637c97ff 100644
--- a/tests/auto/qml/qtqmlmodules/tst_qtqmlmodules.cpp
+++ b/tests/auto/qml/qtqmlmodules/tst_qtqmlmodules.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Research in Motion.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
@@ -23,33 +23,27 @@ void tst_qtqmlmodules::baseTypes()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("base.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QVERIFY(object->property("success").toBool());
-
- delete object;
}
void tst_qtqmlmodules::modelsTypes()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("models.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QVERIFY(object->property("success").toBool());
-
- delete object;
}
void tst_qtqmlmodules::unavailableTypes()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("unavailable.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QVERIFY(object->property("success").toBool());
-
- delete object;
}
QTEST_MAIN(tst_qtqmlmodules)
diff --git a/tests/auto/qml/qv4assembler/CMakeLists.txt b/tests/auto/qml/qv4assembler/CMakeLists.txt
index dfac16468a..8ae3c891d5 100644
--- a/tests/auto/qml/qv4assembler/CMakeLists.txt
+++ b/tests/auto/qml/qv4assembler/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qv4assembler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qv4assembler LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qv4assembler/data/crash.qml b/tests/auto/qml/qv4assembler/data/crash.qml
index ffae69b321..b083497a70 100644
--- a/tests/auto/qml/qv4assembler/data/crash.qml
+++ b/tests/auto/qml/qv4assembler/data/crash.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.2
import Crash 1.0
diff --git a/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp b/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp
index 7e9e070fa6..4be0acd73e 100644
--- a/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp
+++ b/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#if QT_CONFIG(process)
diff --git a/tests/auto/qml/qv4estable/CMakeLists.txt b/tests/auto/qml/qv4estable/CMakeLists.txt
new file mode 100644
index 0000000000..01d2663a04
--- /dev/null
+++ b/tests/auto/qml/qv4estable/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## tst_qv4estable Test:
+#####################################################################
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qv4estable LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qv4estable
+ SOURCES
+ tst_qv4estable.cpp
+ LIBRARIES
+ Qt::Gui
+ Qt::Qml
+ Qt::QmlPrivate
+)
+
+## Scopes:
+#####################################################################
diff --git a/tests/auto/qml/qv4estable/tst_qv4estable.cpp b/tests/auto/qml/qv4estable/tst_qv4estable.cpp
new file mode 100644
index 0000000000..7d137ae7d2
--- /dev/null
+++ b/tests/auto/qml/qv4estable/tst_qv4estable.cpp
@@ -0,0 +1,40 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <qtest.h>
+#include <private/qv4estable_p.h>
+
+class tst_qv4estable : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void checkRemoveAvoidsHeapBufferOverflow();
+};
+
+// QTBUG-123999
+void tst_qv4estable::checkRemoveAvoidsHeapBufferOverflow()
+{
+ QV4::ESTable estable;
+
+ // Fill the ESTable with values so it is at max capacity.
+ QCOMPARE_EQ(estable.m_capacity, 8U);
+ for (uint i = 0; i < estable.m_capacity; ++i) {
+ estable.set(QV4::Value::fromUInt32(i), QV4::Value::fromUInt32(i));
+ }
+ // Our |m_keys| array should now contain eight values.
+ // > [v0, v1, v2, v3, v4, v5, v6, v7]
+ for (uint i = 0; i < estable.m_capacity; ++i) {
+ QVERIFY(estable.m_keys[i].sameValueZero(QV4::Value::fromUInt32(i)));
+ }
+ QCOMPARE_EQ(estable.m_capacity, 8U);
+ QCOMPARE_EQ(estable.m_size, 8U);
+
+ // Remove the first item from the set to verify that asan does not trip.
+ // Relies on the CI platform propagating asan flag to all tests.
+ estable.remove(QV4::Value::fromUInt32(0));
+}
+
+QTEST_MAIN(tst_qv4estable)
+
+#include "tst_qv4estable.moc"
diff --git a/tests/auto/qml/qv4identifiertable/CMakeLists.txt b/tests/auto/qml/qv4identifiertable/CMakeLists.txt
index 5c785b0b74..c0350d6ef7 100644
--- a/tests/auto/qml/qv4identifiertable/CMakeLists.txt
+++ b/tests/auto/qml/qv4identifiertable/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qv4identifiertable Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qv4identifiertable LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qv4identifiertable
SOURCES
tst_qv4identifiertable.cpp
diff --git a/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
index a3f5c4bb70..6222f20c10 100644
--- a/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
+++ b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
@@ -1,6 +1,6 @@
// Copyright (C) 2019 The Qt Company Ltd.
// Copyright (C) 2016 basysKom GmbH.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
diff --git a/tests/auto/qml/qv4mm/CMakeLists.txt b/tests/auto/qml/qv4mm/CMakeLists.txt
index bfafd5819c..7c8a52038e 100644
--- a/tests/auto/qml/qv4mm/CMakeLists.txt
+++ b/tests/auto/qml/qv4mm/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qv4mm Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qv4mm LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qv4mm/data/createdestroy.qml b/tests/auto/qml/qv4mm/data/createdestroy.qml
index fd8a8cb2a2..5cc689b1ea 100644
--- a/tests/auto/qml/qv4mm/data/createdestroy.qml
+++ b/tests/auto/qml/qv4mm/data/createdestroy.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.2
diff --git a/tests/auto/qml/qv4mm/data/createobjects.qml b/tests/auto/qml/qv4mm/data/createobjects.qml
index 4163d34d34..bd1897e04e 100644
--- a/tests/auto/qml/qv4mm/data/createobjects.qml
+++ b/tests/auto/qml/qv4mm/data/createobjects.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.2
diff --git a/tests/auto/qml/qv4mm/data/simpleObject.qml b/tests/auto/qml/qv4mm/data/simpleObject.qml
new file mode 100644
index 0000000000..8fc36a40da
--- /dev/null
+++ b/tests/auto/qml/qv4mm/data/simpleObject.qml
@@ -0,0 +1,3 @@
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qml/qv4mm/data/storeLocal.qml b/tests/auto/qml/qv4mm/data/storeLocal.qml
new file mode 100644
index 0000000000..8d48a8b23c
--- /dev/null
+++ b/tests/auto/qml/qv4mm/data/storeLocal.qml
@@ -0,0 +1,34 @@
+import QtQml
+
+QtObject {
+ id: root
+ property bool wasNotMarkedBefore: false
+ property bool wasMarkedAfter: false
+ property int result: -2
+ function f() {
+ let a = [1, 2, 3];
+ function inner() {
+ a = [4, 5, 6];
+ }
+ __forceJit(inner);
+ __setupGC();
+ root.wasNotMarkedBefore = !__isMarked(a);
+ inner();
+ root.wasMarkedAfter = __isMarked(a);
+ return a[0];
+ }
+ Component.onCompleted: {
+ if (!__forceJit(f)) {
+ root.result = -1;
+ return;
+ }
+ if (f() !== 4)
+ root.result = 1;
+ else if (!wasNotMarkedBefore)
+ root.result = 2;
+ else if (!wasMarkedAfter)
+ root.result = 3;
+ else
+ root.result = 0; // success
+ }
+}
diff --git a/tests/auto/qml/qv4mm/tst_qv4mm.cpp b/tests/auto/qml/qv4mm/tst_qv4mm.cpp
index e5f8951825..7714beb3c7 100644
--- a/tests/auto/qml/qv4mm/tst_qv4mm.cpp
+++ b/tests/auto/qml/qv4mm/tst_qv4mm.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 basysKom GmbH.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -9,6 +9,15 @@
#include <private/qv4mm_p.h>
#include <private/qv4qobjectwrapper_p.h>
#include <private/qjsvalue_p.h>
+#include <private/qqmlengine_p.h>
+#include <private/qv4identifiertable_p.h>
+#include <private/qv4arraydata_p.h>
+#include <private/qqmlcomponentattached_p.h>
+#include <private/qv4mapobject_p.h>
+#include <private/qv4setobject_p.h>
+#if QT_CONFIG(qml_jit)
+#include <private/qv4baselinejit_p.h>
+#endif
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -23,22 +32,153 @@ public:
private slots:
void gcStats();
+ void arrayDataWriteBarrierInteraction();
+ void persistentValueMarking_data();
+ void persistentValueMarking();
void multiWrappedQObjects();
void accessParentOnDestruction();
void cleanInternalClasses();
void createObjectsOnDestruction();
+ void sharedInternalClassDataMarking();
+ void gcTriggeredInOnDestroyed();
+ void weakValuesAssignedAfterThePhaseThatShouldHandleWeakValues();
+ void mapAndSetKeepValuesAlive();
+ void jittedStoreLocalMarksValue();
};
tst_qv4mm::tst_qv4mm()
: QQmlDataTest(QT_QMLTEST_DATADIR)
{
+ QV4::ExecutionEngine engine;
+ QV4::Scope scope(engine.rootContext());
}
void tst_qv4mm::gcStats()
{
QLoggingCategory::setFilterRules("qt.qml.gc.*=true");
QQmlEngine engine;
- engine.collectGarbage();
+ gc(engine);
+ QLoggingCategory::setFilterRules("qt.qml.gc.*=false");
+}
+
+void tst_qv4mm::arrayDataWriteBarrierInteraction()
+{
+ QV4::ExecutionEngine engine;
+ QCOMPARE(engine.memoryManager->gcBlocked, QV4::MemoryManager::Unblocked);
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection;
+ QV4::Heap::Object *unprotectedObject = engine.newObject();
+ QV4::Scope scope(&engine);
+ QV4::ScopedArrayObject array(scope, engine.newArrayObject());
+ constexpr int initialCapacity = 8; // compare qv4arraydata.cpp
+ for (int i = 0; i < initialCapacity; ++i) {
+ array->push_back(unprotectedObject->asReturnedValue());
+ }
+ QVERIFY(!unprotectedObject->isMarked());
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked;
+
+ // initialize gc
+ auto sm = engine.memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::MarkGlobalObject) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+
+ array->push_back(QV4::Value::fromUInt32(42));
+ QVERIFY(!unprotectedObject->isMarked());
+ // we should have pushed the new arraydata on the mark stack
+ // so if we call drain...
+ engine.memoryManager->markStack()->drain();
+ // the unprotectedObject should have been marked
+ QVERIFY(unprotectedObject->isMarked());
+}
+
+enum PVSetOption {
+ CopyCtor,
+ ValueCtor,
+ ObjectCtor,
+ ReturnedValueCtor,
+ WeakValueAssign,
+ ObjectAssign,
+};
+
+void tst_qv4mm::persistentValueMarking_data()
+{
+ QTest::addColumn<PVSetOption>("setOption");
+
+ QTest::addRow("copy") << CopyCtor;
+ QTest::addRow("valueCtor") << ValueCtor;
+ QTest::addRow("ObjectCtor") << ObjectCtor;
+ QTest::addRow("ReturnedValueCtor") << ReturnedValueCtor;
+ QTest::addRow("WeakValueAssign") << WeakValueAssign;
+ QTest::addRow("ObjectAssign") << ObjectAssign;
+}
+
+void tst_qv4mm::persistentValueMarking()
+{
+ QFETCH(PVSetOption, setOption);
+ QV4::ExecutionEngine engine;
+ QV4::PersistentValue persistentOrigin; // used for copy ctor
+ QV4::Heap::Object *unprotectedObject = engine.newObject();
+ {
+ QV4::Scope scope(engine.rootContext());
+ QV4::ScopedObject object {scope, unprotectedObject};
+ persistentOrigin.set(&engine, object);
+ QVERIFY(!unprotectedObject->isMarked());
+ }
+ auto sm = engine.memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::MarkGlobalObject) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QVERIFY(engine.isGCOngoing);
+ QVERIFY(!unprotectedObject->isMarked());
+ switch (setOption) {
+ case CopyCtor: {
+ QV4::PersistentValue persistentCopy(persistentOrigin);
+ QVERIFY(unprotectedObject->isMarked());
+ break;
+ }
+ case ValueCtor: {
+ QV4::Value val = QV4::Value::fromHeapObject(unprotectedObject);
+ QV4::PersistentValue persistent(&engine, val);
+ QVERIFY(unprotectedObject->isMarked());
+ break;
+ }
+ case ObjectCtor: {
+ QV4::Scope scope(&engine);
+ QV4::ScopedObject o(scope, unprotectedObject);
+ // scoped object without scan shouldn't result in marking
+ QVERIFY(!unprotectedObject->isMarked());
+ QV4::PersistentValue persistent(&engine, o.getPointer());
+ QVERIFY(unprotectedObject->isMarked());
+ break;
+ }
+ case ReturnedValueCtor: {
+ QV4::PersistentValue persistent(&engine, unprotectedObject->asReturnedValue());
+ QVERIFY(unprotectedObject->isMarked());
+ break;
+ }
+ case WeakValueAssign: {
+ QV4::WeakValue wv;
+ wv.set(&engine, unprotectedObject);
+ QVERIFY(!unprotectedObject->isMarked());
+ QV4::PersistentValue persistent;
+ persistent = wv;
+ break;
+ }
+ case ObjectAssign: {
+ QV4::Scope scope(&engine);
+ QV4::ScopedObject o(scope, unprotectedObject);
+ // scoped object without scan shouldn't result in marking
+ QVERIFY(!unprotectedObject->isMarked());
+ QV4::PersistentValue persistent;
+ persistent = o;
+ QVERIFY(unprotectedObject->isMarked());
+ break;
+ }
+ }
}
void tst_qv4mm::multiWrappedQObjects()
@@ -48,7 +188,7 @@ void tst_qv4mm::multiWrappedQObjects()
{
QObject object;
for (int i = 0; i < 10; ++i)
- QV4::QObjectWrapper::wrap(i % 2 ? &engine1 : &engine2, &object);
+ QV4::QObjectWrapper::ensureWrapper(i % 2 ? &engine1 : &engine2, &object);
QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
QCOMPARE(engine2.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
@@ -62,27 +202,27 @@ void tst_qv4mm::multiWrappedQObjects()
// The additional WeakValue from m_multiplyWrappedQObjects hasn't been moved
// to m_pendingFreedObjectWrapperValue yet. It's still alive after all.
- engine1.memoryManager->runGC();
+ gc(engine1);
QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 1);
// engine2 doesn't own the object as engine1 was the first to wrap it above.
// Therefore, no effect here.
- engine2.memoryManager->runGC();
+ gc(engine2);
QCOMPARE(engine2.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
}
// Clears m_pendingFreedObjectWrapperValue. Now it's really dead.
- engine1.memoryManager->runGC();
+ gc(engine1);
QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
- engine2.memoryManager->runGC();
+ gc(engine2);
QCOMPARE(engine2.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
}
void tst_qv4mm::accessParentOnDestruction()
{
- QLoggingCategory::setFilterRules("qt.qml.gc.*=false");
QQmlEngine engine;
+
QQmlComponent component(&engine, testFileUrl("createdestroy.qml"));
std::unique_ptr<QObject> obj(component.create());
QVERIFY(obj);
@@ -91,6 +231,9 @@ void tst_qv4mm::accessParentOnDestruction()
QTRY_VERIFY(!timer->property("running").toBool());
QCOMPARE(obj->property("iterations").toInt(), 100);
QCOMPARE(obj->property("creations").toInt(), 100);
+ gc(engine); // ensure incremental gc has finished, and collected all objects
+ // TODO: investigaet whether we really need two gc rounds for incremental gc
+ gc(engine); // ensure incremental gc has finished, and collected all objects
QCOMPARE(obj->property("destructions").toInt(), 100);
}
@@ -181,7 +324,11 @@ void tst_qv4mm::cleanInternalClasses()
}
// Make sure that all dangling ICs are actually gone.
- scope.engine->memoryManager->runGC();
+ gc(engine);
+ // NOTE: If we allocate new ICs during gc (potentially triggered on alloc),
+ // then they will survive the previous gc call
+ // run gc again to ensure that a full gc cycle happens
+ gc(engine);
// Now the GC has removed the ICs we originally added by adding properties.
QVERIFY(prevIC->d()->transitions.empty() || prevIC->d()->transitions.front().lookup == nullptr);
@@ -197,8 +344,8 @@ void tst_qv4mm::cleanInternalClasses()
void tst_qv4mm::createObjectsOnDestruction()
{
- QLoggingCategory::setFilterRules("qt.qml.gc.*=false");
QQmlEngine engine;
+
QQmlComponent component(&engine, testFileUrl("createobjects.qml"));
std::unique_ptr<QObject> obj(component.create());
QVERIFY(obj);
@@ -206,6 +353,383 @@ void tst_qv4mm::createObjectsOnDestruction()
QCOMPARE(obj->property("ok").toBool(), true);
}
+void tst_qv4mm::sharedInternalClassDataMarking()
+{
+ QV4::ExecutionEngine engine;
+ QV4::Scope scope(engine.rootContext());
+ QV4::ScopedObject object(scope, engine.newObject());
+ QVERIFY(!engine.memoryManager->gcBlocked);
+ // no scoped classes, as that would defeat the point of the test
+ // we block the gc instead so that the allocation can't trigger the gc
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection;
+ QV4::Heap::String *s = engine.newString(QString::fromLatin1("test"));
+ QV4::PropertyKey id = engine.identifierTable->asPropertyKeyImpl(s);
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked;
+ QVERIFY(!id.asStringOrSymbol()->isMarked());
+
+ auto sm = engine.memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::MarkGlobalObject) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+
+ // simulate partial marking caused by drain due mark stack running out of space
+ // and running out of time during drain phase for complete marking
+ // the last part is necessary for us to find not-already marked name/value pair to put into
+ // the object
+
+ QVERIFY(engine.memoryManager->markStack()->isEmpty());
+ QVERIFY(!id.asStringOrSymbol()->isMarked());
+ {
+
+ // for simplcity's sake we create a new PropertyKey - if gc were actually ongoing that would
+ // already mark it. In practice we would need to retrieve an existing one from an unmarked
+ // object, and then make that object unreachable afterwards.
+ object->put(id, QV4::Value::fromUInt32(42));
+ engine.memoryManager->markStack()->drain();
+ QVERIFY(id.asStringOrSymbol()->isMarked());
+ }
+ gc(engine);
+ // sanity check that we still can lookup the value
+ QV4::ScopedString s2(scope, engine.newString(QString::fromLatin1("test")));
+ auto val = QV4::Value::fromReturnedValue(object->get(s2->toPropertyKey()));
+ QCOMPARE(val.toUInt32(), 42u);
+}
+
+void tst_qv4mm::gcTriggeredInOnDestroyed()
+{
+ QQmlEngine engine;
+ QV4::ExecutionEngine &v4 = *engine.handle();
+
+ QPointer<QObject> testObject = new QObject; // unparented, will be deleted
+ auto cleanup = qScopeGuard([&]() {
+ if (testObject)
+ testObject->deleteLater();
+ });
+
+ QQmlComponent component(&engine, testFileUrl("simpleObject.qml"));
+ auto toBeCollected = component.create();
+ QVERIFY(toBeCollected);
+ QJSEngine::setObjectOwnership(toBeCollected, QJSEngine::JavaScriptOwnership);
+ QV4::QObjectWrapper::ensureWrapper(&v4, toBeCollected);
+ QVERIFY(qmlEngine(toBeCollected));
+ QQmlComponentAttached *attached = QQmlComponent::qmlAttachedProperties(toBeCollected);
+ QVERIFY(attached);
+
+
+ QV4::Scope scope(v4.rootContext());
+ QCOMPARE(v4.memoryManager->gcBlocked, QV4::MemoryManager::Unblocked);
+
+
+
+ // let the gc run up to CallDestroyObjects
+ auto sm = v4.memoryManager->gcStateMachine.get();
+ sm->reset();
+ v4.memoryManager->gcBlocked = QV4::MemoryManager::NormalBlocked;
+ while (sm->state != QV4::GCState::CallDestroyObjects && sm->state != QV4::GCState::Invalid) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QCOMPARE(sm->state, QV4::GCState::CallDestroyObjects);
+
+ QV4::ScopedValue val(scope);
+ bool calledOnDestroyed = false;
+ auto con = connect(attached, &QQmlComponentAttached::destruction, this, [&]() {
+ calledOnDestroyed = true;
+ // we trigger uncommon code paths:
+ // create ObjectWrapper in destroyed hadnler
+ auto ddata = QQmlData::get(testObject.get(), false);
+ QVERIFY(!ddata); // we don't have ddata yet (otherwise we'd already have an object wrapper)
+ val = QV4::QObjectWrapper::wrap(&v4, testObject.get());
+ QJSEngine::setObjectOwnership(testObject, QJSEngine::JavaScriptOwnership);
+
+ // and also try to trigger a force gc completion
+ bool gcComplete = v4.memoryManager->tryForceGCCompletion();
+ QVERIFY(!gcComplete);
+ });
+ while (!calledOnDestroyed && sm->state != QV4::GCState::Invalid) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QVERIFY(!QTest::currentTestFailed());
+ QObject::disconnect(con);
+ QVERIFY(calledOnDestroyed);
+
+ bool gcComplete = v4.memoryManager->tryForceGCCompletion();
+ QVERIFY(gcComplete);
+ val = QV4::Value::undefinedValue(); // no longer keep a reference on the stack
+ QCOMPARE(sm->state, QV4::GCState::Invalid);
+ QVERIFY(testObject); // must not have be deleted, referenced by val
+
+ gc(v4); // run another gc cycle
+ QVERIFY(!testObject); // now collcted by gc
+}
+void tst_qv4mm::weakValuesAssignedAfterThePhaseThatShouldHandleWeakValues()
+{
+ QObject testObject;
+ QV4::ExecutionEngine v4;
+
+ QCOMPARE(v4.memoryManager->gcBlocked, QV4::MemoryManager::Unblocked);
+
+
+
+ // let the gc run up to CallDestroyObjects
+ auto sm = v4.memoryManager->gcStateMachine.get();
+ sm->reset();
+ v4.memoryManager->gcBlocked = QV4::MemoryManager::NormalBlocked;
+
+
+ // run just before the sweeping face
+ while (sm->state != QV4::GCState::DoSweep && sm->state != QV4::GCState::Invalid) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QCOMPARE(sm->state, QV4::GCState::DoSweep);
+
+ {
+ // simulate code accessing the object wrapper for an object
+ QV4::Scope scope(v4.rootContext());
+ QV4::ScopedValue value(scope);
+ value = QV4::QObjectWrapper::wrap(&v4, &testObject);
+ // let it go out of scope before any stack re-scanning could happen
+ }
+
+ bool gcComplete = v4.memoryManager->tryForceGCCompletion();
+ QVERIFY(gcComplete);
+
+ auto ddata = QQmlData::get(&testObject);
+ QVERIFY(ddata);
+ if (ddata->jsWrapper.isUndefined()) {
+ // it's in principle valid for the wrapper to be reset, though the current
+ // implementation doesn't do it, and it requires some care
+ qWarning("Double-check the handling of weak values and object wrappers in the gc");
+ return;
+ }
+ QVERIFY(ddata->jsWrapper.valueRef()->heapObject()->inUse());
+}
+
+void tst_qv4mm::mapAndSetKeepValuesAlive()
+{
+ {
+ QJSEngine jsEngine;
+ QV4::ExecutionEngine &engine = *jsEngine.handle();
+
+ QV4::Scope scope(&engine);
+ auto map = jsEngine.evaluate("new Map()");
+ QV4::ScopedFunctionObject afunction(scope, engine.memoryManager->alloc<QV4::FunctionObject>()); // hack, we just need about any function object
+ QV4::Value thisObject = QJSValuePrivate::asReturnedValue(&map);
+
+ QVERIFY(!engine.memoryManager->gcBlocked);
+ // no scoped classes, as that would defeat the point of the test
+ // we block the gc instead so that the allocation can't trigger the gc
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection;
+ QV4::Heap::String *key = engine.newString(QString::fromLatin1("key"));
+ QV4::Heap::String *value = engine.newString(QString::fromLatin1("value"));
+ QV4::Value values[2] = { QV4::Value::fromHeapObject(key), QV4::Value::fromHeapObject(value) };
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked;
+ QVERIFY(!key->isMarked());
+ QVERIFY(!value->isMarked());
+
+ auto sm = engine.memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::HandleQObjectWrappers) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QV4::MapPrototype::method_set(afunction.getPointer(), &thisObject, values, 2);
+
+ // check that we can still insert primitve values - they don't get marked
+ // but they also should not casue any corrpution - note that a weak map
+ // only accepts object keys
+ values[0] = QV4::Value::fromInt32(12);
+ values[1] = QV4::Value::fromInt32(13);
+ QV4::MapPrototype::method_set(afunction.getPointer(), &thisObject, values, 2);
+
+ QVERIFY(key->isMarked());
+ QVERIFY(value->isMarked());
+ bool gcComplete = engine.memoryManager->tryForceGCCompletion();
+ QVERIFY(gcComplete);
+ QVERIFY(key->inUse());
+ QVERIFY(value->inUse());
+ gc(engine);
+ QCOMPARE(map.property("size").toInt(), 2);
+ }
+ {
+ QJSEngine jsEngine;
+ QV4::ExecutionEngine &engine = *jsEngine.handle();
+
+ QV4::Scope scope(&engine);
+ auto map = jsEngine.evaluate("new WeakMap()");
+ QV4::ScopedFunctionObject afunction(scope, engine.memoryManager->alloc<QV4::FunctionObject>()); // hack, we just need about any function object
+ QV4::Value thisObject = QJSValuePrivate::asReturnedValue(&map);
+
+ QVERIFY(!engine.memoryManager->gcBlocked);
+ // no scoped classes, as that would defeat the point of the test
+ // we block the gc instead so that the allocation can't trigger the gc
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection;
+ QV4::Heap::Object *key = engine.newObject();
+ QV4::Heap::String *value = engine.newString(QString::fromLatin1("value"));
+ QV4::Value values[2] = { QV4::Value::fromHeapObject(key), QV4::Value::fromHeapObject(value) };
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked;
+ QVERIFY(!key->isMarked());
+ QVERIFY(!value->isMarked());
+
+ auto sm = engine.memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::HandleQObjectWrappers) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QV4::WeakMapPrototype::method_set(afunction.getPointer(), &thisObject, values, 2);
+ QVERIFY(!engine.hasException);
+ QVERIFY(key->isMarked());
+ QVERIFY(value->isMarked());
+ bool gcComplete = engine.memoryManager->tryForceGCCompletion();
+ QVERIFY(gcComplete);
+ QVERIFY(key->inUse());
+ QVERIFY(value->inUse());
+ gc(engine);
+ QCOMPARE(map.property("size").toInt(), 0);
+ }
+ {
+ QJSEngine jsEngine;
+ QV4::ExecutionEngine &engine = *jsEngine.handle();
+
+ QV4::Scope scope(&engine);
+ auto map = jsEngine.evaluate("new Set()");
+ QV4::ScopedFunctionObject afunction(scope, engine.memoryManager->alloc<QV4::FunctionObject>()); // hack, we just need about any function object
+ QV4::Value thisObject = QJSValuePrivate::asReturnedValue(&map);
+
+ QVERIFY(!engine.memoryManager->gcBlocked);
+ // no scoped classes, as that would defeat the point of the test
+ // we block the gc instead so that the allocation can't trigger the gc
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection;
+ QV4::Heap::Object *key = engine.newObject();
+ QV4::Value values[1] = { QV4::Value::fromHeapObject(key) };
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked;
+ QVERIFY(!key->isMarked());
+
+ auto sm = engine.memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::HandleQObjectWrappers) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QV4::SetPrototype::method_add(afunction.getPointer(), &thisObject, values, 1);
+ values[0] = QV4::Value::fromInt32(13);
+ QV4::SetPrototype::method_add(afunction.getPointer(), &thisObject, values, 1);
+ QVERIFY(!engine.hasException);
+ QVERIFY(key->isMarked());
+ bool gcComplete = engine.memoryManager->tryForceGCCompletion();
+ QVERIFY(gcComplete);
+ QVERIFY(key->inUse());
+ gc(engine);
+ QCOMPARE(map.property("size").toInt(), 2);
+ }
+ {
+ QJSEngine jsEngine;
+ QV4::ExecutionEngine &engine = *jsEngine.handle();
+
+ QV4::Scope scope(&engine);
+ auto map = jsEngine.evaluate("new WeakSet()");
+ QV4::ScopedFunctionObject afunction(scope, engine.memoryManager->alloc<QV4::FunctionObject>()); // hack, we just need about any function object
+ QV4::Value thisObject = QJSValuePrivate::asReturnedValue(&map);
+
+ QVERIFY(!engine.memoryManager->gcBlocked);
+ // no scoped classes, as that would defeat the point of the test
+ // we block the gc instead so that the allocation can't trigger the gc
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection;
+ QV4::Heap::Object *key = engine.newObject();
+ QV4::Value values[1] = { QV4::Value::fromHeapObject(key) };
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked;
+ QVERIFY(!key->isMarked());
+
+ auto sm = engine.memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::HandleQObjectWrappers) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QV4::WeakSetPrototype::method_add(afunction.getPointer(), &thisObject, values, 1);
+ QVERIFY(!engine.hasException);
+ QVERIFY(key->isMarked());
+ bool gcComplete = engine.memoryManager->tryForceGCCompletion();
+ QVERIFY(gcComplete);
+ QVERIFY(key->inUse());
+ gc(engine);
+ QCOMPARE(map.property("size").toInt(), 0);
+ }
+}
+
+QV4::ReturnedValue method_force_jit(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *argv, int argc)
+{
+#if QT_CONFIG(qml_jit)
+ auto *v4 =b->engine();
+
+ Q_ASSERT(argc == 1);
+ QV4::Scope scope(v4);
+ QV4::Scoped<QV4::JavaScriptFunctionObject> functionObject(scope, argv[0]);
+ auto *func = static_cast<QV4::Heap::JavaScriptFunctionObject *>(functionObject->heapObject())->function;
+ Q_ASSERT(func);
+ func->interpreterCallCount = std::numeric_limits<int>::max();
+ if (!v4->canJIT(func))
+ return QV4::StaticValue::fromBoolean(false).asReturnedValue();
+ QV4::JIT::BaselineJIT(func).generate();
+ return QV4::StaticValue::fromBoolean(true).asReturnedValue();
+#else
+ return QV4::StaticValue::fromBoolean(false).asReturnedValue();
+#endif
+}
+
+QV4::ReturnedValue method_setup_gc_for_test(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *, int)
+{
+ auto *v4 =b->engine();
+ auto *mm = v4->memoryManager;
+ mm->runFullGC();
+
+ auto sm = v4->memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::MarkGlobalObject) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+
+ return QV4::Encode::undefined();
+}
+
+QV4::ReturnedValue method_is_marked(const QV4::FunctionObject *, const QV4::Value *, const QV4::Value *argv, int argc)
+{
+ Q_ASSERT(argc == 1);
+
+ auto h = argv[0].heapObject();
+ Q_ASSERT(h);
+ return QV4::Encode(h->isMarked());
+}
+
+void tst_qv4mm::jittedStoreLocalMarksValue()
+{
+ QQmlEngine engine;
+
+ auto *v4 = engine.handle();
+ auto globalObject = v4->globalObject;
+ globalObject->defineDefaultProperty(QStringLiteral("__setupGC"), method_setup_gc_for_test);
+ globalObject->defineDefaultProperty(QStringLiteral("__forceJit"), method_force_jit);
+ globalObject->defineDefaultProperty(QStringLiteral("__isMarked"), method_is_marked);
+
+ QQmlComponent comp(&engine, testFileUrl("storeLocal.qml"));
+ QVERIFY(comp.isReady());
+ std::unique_ptr<QObject> root {comp.create()};
+
+ QVERIFY(root);
+ bool ok = false;
+ int result = root->property("result").toInt(&ok);
+ QVERIFY(ok);
+ if (result == -1)
+ QSKIP("Could not run JIT");
+ QCOMPARE(result, 0);
+}
+
QTEST_MAIN(tst_qv4mm)
#include "tst_qv4mm.moc"
diff --git a/tests/auto/qml/qv4regexp/CMakeLists.txt b/tests/auto/qml/qv4regexp/CMakeLists.txt
index bdaf5e52e4..6f2c47c4b2 100644
--- a/tests/auto/qml/qv4regexp/CMakeLists.txt
+++ b/tests/auto/qml/qv4regexp/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qv4regexp Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qv4regexp LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qv4regexp
SOURCES
tst_qv4regexp.cpp
diff --git a/tests/auto/qml/qv4regexp/tst_qv4regexp.cpp b/tests/auto/qml/qv4regexp/tst_qv4regexp.cpp
index 534fa53956..99a91a9b0f 100644
--- a/tests/auto/qml/qv4regexp/tst_qv4regexp.cpp
+++ b/tests/auto/qml/qv4regexp/tst_qv4regexp.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQml/qjsengine.h>
diff --git a/tests/auto/qml/qv4urlobject/CMakeLists.txt b/tests/auto/qml/qv4urlobject/CMakeLists.txt
new file mode 100644
index 0000000000..f255413d84
--- /dev/null
+++ b/tests/auto/qml/qv4urlobject/CMakeLists.txt
@@ -0,0 +1,26 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Generated from qv4urlobject.pro.
+
+#####################################################################
+## tst_qv4urlobject Test:
+#####################################################################
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qv4urlobject LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qv4urlobject
+ SOURCES
+ tst_qv4urlobject.cpp
+ LIBRARIES
+ Qt::Gui
+ Qt::Qml
+ Qt::QmlPrivate
+)
+
+## Scopes:
+#####################################################################
diff --git a/tests/auto/qml/qv4urlobject/tst_qv4urlobject.cpp b/tests/auto/qml/qv4urlobject/tst_qv4urlobject.cpp
new file mode 100644
index 0000000000..992d1ef808
--- /dev/null
+++ b/tests/auto/qml/qv4urlobject/tst_qv4urlobject.cpp
@@ -0,0 +1,153 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <qtest.h>
+#include <QtQml/qjsengine.h>
+
+class tst_urlobject : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void searchParams_set();
+ void searchParams_nullUrlPointer();
+ void urlObject_search();
+ void urlObject_search_data();
+ void urlObject_href();
+ void urlObject_href_data();
+};
+
+void tst_urlobject::searchParams_set()
+{
+ QJSEngine engine;
+ QJSValue result =
+ engine.evaluate(QLatin1String("var url = new URL(\"http://www.google.com/search\");"
+ "url.href"));
+ QVERIFY(!result.isError());
+ QCOMPARE(result.toString(), "http://www.google.com/search");
+
+ result = engine.evaluate(QLatin1String("url.toString()"));
+ QVERIFY(!result.isError());
+ QCOMPARE(result.toString(), "http://www.google.com/search");
+
+ result = engine.evaluate(QLatin1String("url.searchParams.set(\"q\", \"value\");"
+ "url.href;"));
+ QVERIFY(!result.isError());
+ QCOMPARE(result.toString(), "http://www.google.com/search?q=value");
+
+ result = engine.evaluate(QLatin1String("url.toString()"));
+ QVERIFY(!result.isError());
+ QCOMPARE(result.toString(), "http://www.google.com/search?q=value");
+
+ result = engine.evaluate(QLatin1String("url.searchParams.set(\"t\", \"otherValue\");"
+ "url.href;"));
+ QVERIFY(!result.isError());
+ QCOMPARE(result.toString(), "http://www.google.com/search?q=value&t=otherValue");
+
+ result = engine.evaluate(QLatin1String("url.toString()"));
+ QVERIFY(!result.isError());
+ QCOMPARE(result.toString(), "http://www.google.com/search?q=value&t=otherValue");
+}
+
+void tst_urlobject::searchParams_nullUrlPointer()
+{
+ QJSEngine engine;
+ QJSValue result = engine.evaluate(QLatin1String("let params = new URLSearchParams();"
+ "params.set(\"foo\", \"bar\");"));
+ QVERIFY(!result.isError());
+}
+
+void tst_urlobject::urlObject_search()
+{
+ QFETCH(QString, test);
+ QFETCH(QString, expected);
+
+ QJSEngine engine;
+
+ QCOMPARE(engine.evaluate(test).toString(), expected);
+}
+
+void tst_urlobject::urlObject_search_data()
+{
+ QTest::addColumn<QString>("test");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("base case")
+ << "var url = new URL(\"http://www.google.com/search?q=123\");"
+ "url.search"
+ << "?q=123";
+ QTest::newRow("space")
+ << "var url = new URL(\"http://www.google.com/search?a=b ~\");"
+ "url.search"
+ << "?a=b%20~";
+ QTest::newRow("empty search")
+ << "var url = new URL(\"http://www.google.com/search?\");"
+ "url.search"
+ << "";
+ QTest::newRow("no search")
+ << "var url = new URL(\"http://www.google.com/search\");"
+ "url.search"
+ << "";
+ QTest::newRow("Question mark")
+ // the embedded ""'s break trigraph sequences:
+ << "var url = new URL(\"http://www.google.com/search?""?=?\");"
+ "url.search"
+ << "?""?=?";
+ QTest::newRow("equal sign")
+ << "var url = new URL(\"http://www.google.com/search?a==&b=!\");"
+ "url.search"
+ << "?a==&b=!";
+ QTest::newRow("percent sign")
+ << "var url = new URL(\"http://www.google.com/search?a=%20\");"
+ "url.search"
+ << "?a=%20";
+ QTest::newRow("multiple key-value pairs")
+ << "var url = new URL(\"http://www.google.com/search?a=b&c=d\");"
+ "url.search"
+ << "?a=b&c=d";
+ QTest::newRow("unreserved")
+ << "var url = new URL(\"http://www.google.com/search?a=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~\");"
+ "url.search"
+ << "?a=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~";
+ QTest::newRow("reserved + illegal")
+ << "var url = new URL(\"http://google.com/search/?a=!*();:@&=+$,/?#[]\");"
+ "url.search"
+ << "?a=!*();:@&=+$,/?";
+ QTest::newRow("unicode (U+327D)")
+ << "var url = new URL(\"http://google.com/search/?a=㉽\");"
+ "url.search"
+ << "?a=%E3%89%BD";
+ QTest::newRow("backslash")
+ // The JS string in the C++ source ends in 4 backslashes.
+ // The C++ compiler turns that into 2 backslashes.
+ // QV4 receives source code containing a string literal ending in two backslashes.
+ // The resulting JS string ends in a single backslash.
+ << "var url = new URL('http://google.com/search/?q=\\\\');"
+ "url.search"
+ << "?q=\\";
+}
+
+void tst_urlobject::urlObject_href()
+{
+ QFETCH(QString, test);
+ QFETCH(QString, expected);
+
+ QJSEngine engine;
+
+ QCOMPARE(engine.evaluate(test).toString(), expected);
+}
+
+void tst_urlobject::urlObject_href_data()
+{
+ QTest::addColumn<QString>("test");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("QTBUG-110454")
+ << "var url = new URL(\"https://example.com/?a=b ~\");"
+ "url.href"
+ << "https://example.com/?a=b%20~";
+}
+
+QTEST_MAIN(tst_urlobject)
+
+#include "tst_qv4urlobject.moc"
diff --git a/tests/auto/qml/qwidgetsinqml/CMakeLists.txt b/tests/auto/qml/qwidgetsinqml/CMakeLists.txt
index 4daa98889a..d2374997f2 100644
--- a/tests/auto/qml/qwidgetsinqml/CMakeLists.txt
+++ b/tests/auto/qml/qwidgetsinqml/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qwidgetsinqml Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qwidgetsinqml LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qwidgetsinqml
SOURCES
tst_qwidgetsinqml.cpp
@@ -15,6 +21,8 @@ qt_internal_add_test(tst_qwidgetsinqml
Qt::GuiPrivate
Qt::Qml
Qt::Widgets
+ Qt::QuickTestUtilsPrivate
+ TESTDATA "dummy_imports.qml"
)
## Scopes:
diff --git a/tests/auto/qml/qwidgetsinqml/dummy_imports.qml b/tests/auto/qml/qwidgetsinqml/dummy_imports.qml
new file mode 100644
index 0000000000..afe2b33adf
--- /dev/null
+++ b/tests/auto/qml/qwidgetsinqml/dummy_imports.qml
@@ -0,0 +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++.
+
+import QtQml
+
+QtObject { }
diff --git a/tests/auto/qml/qwidgetsinqml/tst_qwidgetsinqml.cpp b/tests/auto/qml/qwidgetsinqml/tst_qwidgetsinqml.cpp
index 15236c20d8..12058fbba2 100644
--- a/tests/auto/qml/qwidgetsinqml/tst_qwidgetsinqml.cpp
+++ b/tests/auto/qml/qwidgetsinqml/tst_qwidgetsinqml.cpp
@@ -1,10 +1,11 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QQmlEngine>
#include <QtQml>
#include <QWidget>
+#include <QtQuickTestUtils/private/qmlutils_p.h>
class tst_QWidgetsInQml : public QObject
{
@@ -20,13 +21,6 @@ private slots:
void widgetAsDefaultPropertyKeptDuringCreation();
};
-static void gc(QQmlEngine &engine)
-{
- engine.collectGarbage();
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
-}
-
// Like QtObject, but with default property
class QObjectContainer : public QObject
{
@@ -40,7 +34,8 @@ public:
{}
QQmlListProperty<QObject> data() {
- return QQmlListProperty<QObject>(this, 0, children_append, children_count, children_at, children_clear);
+ return QQmlListProperty<QObject>(
+ this, nullptr, children_append, children_count, children_at, children_clear);
}
static void children_append(QQmlListProperty<QObject> *prop, QObject *o)
@@ -58,12 +53,12 @@ public:
}
}
- static int children_count(QQmlListProperty<QObject> *prop)
+ static qsizetype children_count(QQmlListProperty<QObject> *prop)
{
return static_cast<QObjectContainer*>(prop->object)->dataChildren.count();
}
- static QObject *children_at(QQmlListProperty<QObject> *prop, int index)
+ static QObject *children_at(QQmlListProperty<QObject> *prop, qsizetype index)
{
return static_cast<QObjectContainer*>(prop->object)->dataChildren.at(index);
}
@@ -71,7 +66,7 @@ public:
static void children_clear(QQmlListProperty<QObject> *prop)
{
QObjectContainer *that = static_cast<QObjectContainer*>(prop->object);
- foreach (QObject *c, that->dataChildren)
+ for (QObject *c : std::as_const(that->dataChildren))
QObject::disconnect(c, SIGNAL(destroyed(QObject*)), that, SLOT(childDestroyed(QObject*)));
that->dataChildren.clear();
}
diff --git a/tests/auto/qml/registrationmacros/CMakeLists.txt b/tests/auto/qml/registrationmacros/CMakeLists.txt
index 3f2b7411ac..4cae044adf 100644
--- a/tests/auto/qml/registrationmacros/CMakeLists.txt
+++ b/tests/auto/qml/registrationmacros/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_registrationmacros LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_registrationmacros
SOURCES
tst_registrationmacros.cpp
diff --git a/tests/auto/qml/registrationmacros/tst_registrationmacros.cpp b/tests/auto/qml/registrationmacros/tst_registrationmacros.cpp
index 77798af24f..a94e045277 100644
--- a/tests/auto/qml/registrationmacros/tst_registrationmacros.cpp
+++ b/tests/auto/qml/registrationmacros/tst_registrationmacros.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QObject>
diff --git a/tests/auto/qml/registrationmacros/types.cpp b/tests/auto/qml/registrationmacros/types.cpp
index 4ca801e7f7..57d565c525 100644
--- a/tests/auto/qml/registrationmacros/types.cpp
+++ b/tests/auto/qml/registrationmacros/types.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "types.h"
bool Test::check() const
diff --git a/tests/auto/qml/registrationmacros/types.h b/tests/auto/qml/registrationmacros/types.h
index 3c365cc2fd..5579edd2d3 100644
--- a/tests/auto/qml/registrationmacros/types.h
+++ b/tests/auto/qml/registrationmacros/types.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPES_H
#define TYPES_H
diff --git a/tests/auto/qml/v4misc/CMakeLists.txt b/tests/auto/qml/v4misc/CMakeLists.txt
index 81ae948cf1..1390fe9e0f 100644
--- a/tests/auto/qml/v4misc/CMakeLists.txt
+++ b/tests/auto/qml/v4misc/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_v4misc Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_v4misc LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_v4misc
SOURCES
tst_v4misc.cpp
diff --git a/tests/auto/qml/v4misc/tst_v4misc.cpp b/tests/auto/qml/v4misc/tst_v4misc.cpp
index 201bdb2f95..956b87d5f2 100644
--- a/tests/auto/qml/v4misc/tst_v4misc.cpp
+++ b/tests/auto/qml/v4misc/tst_v4misc.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <private/qv4instr_moth_p.h>
diff --git a/tests/auto/qmldom/CMakeLists.txt b/tests/auto/qmldom/CMakeLists.txt
index 7e2a0b885f..f3186e2263 100644
--- a/tests/auto/qmldom/CMakeLists.txt
+++ b/tests/auto/qmldom/CMakeLists.txt
@@ -10,4 +10,3 @@ add_subdirectory(stringdumper)
add_subdirectory(merging)
add_subdirectory(reformatter)
add_subdirectory(combined)
-add_subdirectory(standalone)
diff --git a/tests/auto/qmldom/combined/CMakeLists.txt b/tests/auto/qmldom/combined/CMakeLists.txt
index 6903f89eff..add44acf0b 100644
--- a/tests/auto/qmldom/combined/CMakeLists.txt
+++ b/tests/auto/qmldom/combined/CMakeLists.txt
@@ -5,6 +5,13 @@
## tst_dom_all Binary executing all tests together
## (simpler to verify coverage)
#####################################################################
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_dom_all LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/..
@@ -20,7 +27,6 @@ qt_internal_add_test(tst_dom_all
../domitem/tst_qmldomitem.h
../merging/tst_dommerging.h
../reformatter/tst_reformatter.h
- ../standalone/tst_standalone.h
INCLUDE_DIRECTORIES
..
DEFINES
diff --git a/tests/auto/qmldom/combined/tst_dom_all.cpp b/tests/auto/qmldom/combined/tst_dom_all.cpp
index b3920f8e41..6e3e0bd851 100644
--- a/tests/auto/qmldom/combined/tst_dom_all.cpp
+++ b/tests/auto/qmldom/combined/tst_dom_all.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "stringdumper/tst_qmldomstringdumper.h"
#include "errormessage/tst_qmldomerrormessage.h"
@@ -7,7 +7,6 @@
#include "merging/tst_dommerging.h"
#include "path/tst_qmldompath.h"
#include "reformatter/tst_reformatter.h"
-#include "standalone/tst_standalone.h"
#include <QtCore/qdebug.h>
@@ -38,10 +37,6 @@ int main(int argc, char *argv[])
QQmlJS::Dom::TestReformatter test;
status |= QTest::qExec(&test, argc, argv);
}
- {
- QQmlJS::Dom::TestStandalone test;
- status |= QTest::qExec(&test, argc, argv);
- }
if (status)
qWarning() << "Combined test failed!";
return status;
diff --git a/tests/auto/qmldom/domdata/domitem/Base.qml b/tests/auto/qmldom/domdata/domitem/Base.qml
new file mode 100644
index 0000000000..919619ffe6
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/Base.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int a
+}
diff --git a/tests/auto/qmldom/domdata/domitem/Derived.qml b/tests/auto/qmldom/domdata/domitem/Derived.qml
new file mode 100644
index 0000000000..8a6ce158c3
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/Derived.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Base {
+ property int b
+}
diff --git a/tests/auto/qmldom/domdata/domitem/ImportMeImplicitly.ui.qml b/tests/auto/qmldom/domdata/domitem/ImportMeImplicitly.ui.qml
new file mode 100644
index 0000000000..169d162469
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/ImportMeImplicitly.ui.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ property int helloProperty
+
+}
diff --git a/tests/auto/qmldom/domdata/domitem/WithImplicitImport.qml b/tests/auto/qmldom/domdata/domitem/WithImplicitImport.qml
new file mode 100644
index 0000000000..5560aee727
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/WithImplicitImport.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+
+}
diff --git a/tests/auto/qmldom/domdata/domitem/Yyy.qml b/tests/auto/qmldom/domdata/domitem/Yyy.qml
new file mode 100644
index 0000000000..b2235ff9cc
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/Yyy.qml
@@ -0,0 +1,35 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.0
+import QtQuick as QQ
+
+Zzz {
+ id: root
+ width: height
+ Rectangle {
+ color: "green"
+ anchors.fill: parent
+ height: root.foo.height
+ width: root.height
+
+ }
+
+ function lala() {}
+ property Rectangle foo: Rectangle{ height: 200 }
+ function longfunction(a, b, c = "c", d = "d"): string {
+ return "hehe: " + c + d
+ }
+
+ // documentedFunction: is documented
+ // returns 'Good'
+ function documentedFunction(arg1, arg2 = "Qt"): string {
+ return "Good"
+ }
+ QQ.Rectangle {
+ color:"red"
+ }
+
+ component IC: Zzz { property SomeBase data }
+ property SomeBase mySomeBase
+}
diff --git a/tests/auto/qmldom/domdata/domitem/aliasProperties.qml b/tests/auto/qmldom/domdata/domitem/aliasProperties.qml
index c8653e3446..e2521b7afe 100644
--- a/tests/auto/qmldom/domdata/domitem/aliasProperties.qml
+++ b/tests/auto/qmldom/domdata/domitem/aliasProperties.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
Item {
diff --git a/tests/auto/qmldom/domdata/domitem/astComments.qml b/tests/auto/qmldom/domdata/domitem/astComments.qml
new file mode 100644
index 0000000000..6fca4c69e5
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/astComments.qml
@@ -0,0 +1,12 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function ninja() {
+ // tst comment
+ const patron = 34;
+/*Ast Comment*/ const ppp = 23;
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/attachedOrGroupedProperties.qml b/tests/auto/qmldom/domdata/domitem/attachedOrGroupedProperties.qml
new file mode 100644
index 0000000000..ff7720506c
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/attachedOrGroupedProperties.qml
@@ -0,0 +1,34 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Text {
+ id: grouped
+
+ // Dot notation
+ Binding {
+ grouped.font.family: "mono"
+ }
+
+ // Group notation
+ Test {
+ id: test
+ myText {
+ font {
+ pixelSize: 12
+ }
+ }
+ }
+
+ component Test : Rectangle {
+ property Text myText: text1
+ Text {
+ id: text1
+ }
+ }
+
+ Keys.onPressed: (event)=> {
+
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/breakStatement.qml b/tests/auto/qmldom/domdata/domitem/breakStatement.qml
new file mode 100644
index 0000000000..212fe095c0
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/breakStatement.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+Item {
+ function f() {
+ break helloWorld;
+ break;
+ }
+
+}
diff --git a/tests/auto/qmldom/domdata/domitem/callExpressions.qml b/tests/auto/qmldom/domdata/domitem/callExpressions.qml
new file mode 100644
index 0000000000..d0de350fae
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/callExpressions.qml
@@ -0,0 +1,61 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ property var p: f()
+ // crash if arguments are wrongly collected, e.g. because they are stolen from other unimplemented scriptelements
+ property var p2: f(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
+
+ // dummy test: if these ones fail, then the deconstructing parameters cannot possibly work (they share some
+ // common code).
+ function deconstruct() {
+ let { a } = { a: 32, b: 42}, { b, c } = { b: 32, c: 42}, [ d, e, f ] = [ 111, 222, 333 ];
+ let x = [,,,,[1,2,3],,];
+ }
+
+ function f(q,w,e,r,t,y) {
+ let helloF = 32
+ return 42
+ }
+
+ function fWithDefault(q = 1, w = 2, e, r = 4, t, y = 6) {
+ let helloFWithDefault = {}
+ return 42
+ }
+
+ function marmelade(...onTheBread) {
+ let helloMarmelade = 123
+ return 42
+ }
+
+ function marmelade2(spread, it,...onTheBread) {
+ let helloMarmelade2 = 123
+ return 42
+ }
+
+ // check if nothing crashes for empty stuff
+ function empty({}, []) {
+ let {} = {};
+ let [] = [];
+ }
+
+ component MyType: Item{}
+
+ function withTypes(a: int, b: MyType) {}
+ function empty() {}
+ signal mySignal()
+
+
+ property var p3: evil({ hello: "World", y: "yyy"}, [1,2,3], { is: {a: 111, lot: 222, of: 333, fun: 444, really: ["!",]}})
+
+ function evil({ hello = "world", x = 42 },
+ [n = 42, m = 43, o = 44],
+ { destructuring, is = {a, lot, of}, fun = 42 } = {destructuring : 123, is : {x : 123}, fun : 456}) {
+ const helloEvil = "asdf"
+ return 42
+ }
+
+
+}
diff --git a/tests/auto/qmldom/domdata/domitem/checkScopes.qml b/tests/auto/qmldom/domdata/domitem/checkScopes.qml
new file mode 100644
index 0000000000..39903e9d90
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/checkScopes.qml
@@ -0,0 +1,11 @@
+import QtQuick
+
+Item {
+ id: root
+ property int myInt
+ property int myInt2
+
+ myInt: 42
+ myInt2: 123
+
+}
diff --git a/tests/auto/qmldom/domdata/domitem/commaExpression.qml b/tests/auto/qmldom/domdata/domitem/commaExpression.qml
new file mode 100644
index 0000000000..c6576b5dad
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/commaExpression.qml
@@ -0,0 +1,8 @@
+import QtQuick
+
+Item {
+ function f(a, b, c) {
+ a, b, c;
+ }
+
+}
diff --git a/tests/auto/qmldom/domdata/domitem/conditionalExpression.qml b/tests/auto/qmldom/domdata/domitem/conditionalExpression.qml
new file mode 100644
index 0000000000..027078b0ef
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/conditionalExpression.qml
@@ -0,0 +1,8 @@
+import QtQuick
+
+Item {
+ function f(a, b, c) {
+ a?b:c;
+ }
+
+}
diff --git a/tests/auto/qmldom/domdata/domitem/continueStatement.qml b/tests/auto/qmldom/domdata/domitem/continueStatement.qml
new file mode 100644
index 0000000000..735ded4bda
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/continueStatement.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+Item {
+ function f() {
+ continue helloWorld;
+ continue;
+ }
+
+}
diff --git a/tests/auto/qmldom/domdata/domitem/crashes/bracketsInBinding.qml b/tests/auto/qmldom/domdata/domitem/crashes/bracketsInBinding.qml
new file mode 100644
index 0000000000..bef28ffc45
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/crashes/bracketsInBinding.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int foo: {}
+}
diff --git a/tests/auto/qmldom/domdata/domitem/crashes/lambda.qml b/tests/auto/qmldom/domdata/domitem/crashes/lambda.qml
new file mode 100644
index 0000000000..cab0fec143
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/crashes/lambda.qml
@@ -0,0 +1,7 @@
+import QtQuick.Controls
+
+Action {
+ onTriggered: foo(Bla.Bar, function() {
+ console.log("Hello")
+ })
+}
diff --git a/tests/auto/qmldom/domdata/domitem/crashes/templateStrings.qml b/tests/auto/qmldom/domdata/domitem/crashes/templateStrings.qml
new file mode 100644
index 0000000000..feb5646496
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/crashes/templateStrings.qml
@@ -0,0 +1,10 @@
+import QtQuick
+
+
+Item {
+ property string verbatim1: 'A "verbatim" string!'
+ property string verbatim2: "A 'verbatim' string\u2757"
+ property string verbatim3: `400 + 300 is ${400 + 300}.
+
+mutliline`
+}
diff --git a/tests/auto/qmldom/domdata/domitem/ecmaScriptClass.qml b/tests/auto/qmldom/domdata/domitem/ecmaScriptClass.qml
new file mode 100644
index 0000000000..e86ea737e5
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/ecmaScriptClass.qml
@@ -0,0 +1,44 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+
+function f() {
+
+var count = 0;
+
+class Person {
+ constructor(name) {
+ this._name = name
+ }
+}
+
+class Employee extends Person{
+
+
+ constructor(name, age) {
+ super(name);
+ this._name = name;
+ this._age = age;
+ ++count;
+ }
+
+ get /* do we get the comment? */ name() {
+ return this._name.toUpperCase();
+ }
+
+ set name(newName){
+ if (newName) {
+ this._name = newName;
+ }
+ }
+
+ static get count() { return count;}
+}
+
+
+}
+
+}
diff --git a/tests/auto/qmldom/domdata/domitem/emptyMethodBody.qml b/tests/auto/qmldom/domdata/domitem/emptyMethodBody.qml
new file mode 100644
index 0000000000..d987d3e649
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/emptyMethodBody.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ function f(x) {}
+
+}
diff --git a/tests/auto/qmldom/domdata/domitem/enumDeclarations.qml b/tests/auto/qmldom/domdata/domitem/enumDeclarations.qml
new file mode 100644
index 0000000000..260f079fd6
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/enumDeclarations.qml
@@ -0,0 +1,7 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+Item {
+ enum Cats { Patron, Mafya, Kivrik = -1 }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/fieldMemberExpression.qml b/tests/auto/qmldom/domdata/domitem/fieldMemberExpression.qml
new file mode 100644
index 0000000000..8890a0c8cb
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/fieldMemberExpression.qml
@@ -0,0 +1,32 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ id: root
+
+ property int p: 42
+
+ property Item property1: Item {
+ property bool p: 44
+ property Item property2: Item {
+ property string p: "Hello World"
+ property Item property3: Item {
+ property real p: 123
+ }
+ }
+ }
+
+ property var p1: p
+ property var p1Qualified: root.p
+ property var p1Bracket: root["p"]
+ property var p1Index: root[42]
+ property var p1Key: root[p]
+
+ property var p2: property1.p
+ property var p2Qualified: root.property1.p
+
+ property var p3: property1.property2.p
+ property var p3Qualified: root.property1.property2.p
+}
diff --git a/tests/auto/qmldom/domdata/domitem/fileLocationRegion.qml b/tests/auto/qmldom/domdata/domitem/fileLocationRegion.qml
new file mode 100644
index 0000000000..f441efb5e2
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/fileLocationRegion.qml
@@ -0,0 +1,8 @@
+import QtQuick
+
+Item {
+ property int helloWorld
+
+ // before helloWorld binding
+ helloWorld: 42 // after helloWorld binding
+}
diff --git a/tests/auto/qmldom/domdata/domitem/fileLocationRegions/comments.qml b/tests/auto/qmldom/domdata/domitem/fileLocationRegions/comments.qml
new file mode 100644
index 0000000000..a69505c544
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/fileLocationRegions/comments.qml
@@ -0,0 +1,12 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+/*
+splitting
+multiline
+*/
+// single line
+/* another comment */
+QtObject {}
diff --git a/tests/auto/qmldom/domdata/domitem/fileLocationRegions/enums.qml b/tests/auto/qmldom/domdata/domitem/fileLocationRegions/enums.qml
new file mode 100644
index 0000000000..e6e0f7a205
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/fileLocationRegions/enums.qml
@@ -0,0 +1,12 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ enum OSC {
+ sin = 1,
+ saw,
+ tri = 16
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/fileLocationRegions/functions.qml b/tests/auto/qmldom/domdata/domitem/fileLocationRegions/functions.qml
new file mode 100644
index 0000000000..e045e5a4cc
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/fileLocationRegions/functions.qml
@@ -0,0 +1,15 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function a() : int {}
+
+ component A : Item {
+ function b(k: int) : int {}
+ }
+
+ signal k(int a)
+ signal kk(a: int)
+}
diff --git a/tests/auto/qmldom/domdata/domitem/fileLocationRegions/imports.qml b/tests/auto/qmldom/domdata/domitem/fileLocationRegions/imports.qml
new file mode 100644
index 0000000000..ccf012bc63
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/fileLocationRegions/imports.qml
@@ -0,0 +1,11 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQml 2.15
+import QtQuick.Controls as Patron
+import "../cats"
+
+Item {
+
+}
diff --git a/tests/auto/qmldom/domdata/domitem/fileLocationRegions/pragmas.qml b/tests/auto/qmldom/domdata/domitem/fileLocationRegions/pragmas.qml
new file mode 100644
index 0000000000..5f34f9ae33
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/fileLocationRegions/pragmas.qml
@@ -0,0 +1,11 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+pragma Singleton
+pragma ComponentBehavior: Bound
+pragma FunctionSignatureBehavior: Enforced
+pragma ValueTypeBehavior: Copy,Addressable
+
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qmldom/domdata/domitem/finalizeScriptExpressions.qml b/tests/auto/qmldom/domdata/domitem/finalizeScriptExpressions.qml
new file mode 100644
index 0000000000..5a0c811396
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/finalizeScriptExpressions.qml
@@ -0,0 +1,29 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ property var binding
+ binding: 42
+
+ property var bindingInPropertyDefinition: 123
+
+ function return42(aa: Item = 33, bb: string = "Hello", cc = binding): int {
+ return 42
+ }
+ function empty(aa: Item, bb: string, cc) {}
+ function full(aa: Item, bb: string, cc)
+ {
+ const x = 42;
+ const formula = (x + 5) * 2 + 10 - x
+ return formula;
+ }
+
+ id: idBinding
+
+ property var arrayBinding
+ arrayBinding:[]
+ property var objectBinding
+ objectBinding: Item {}
+}
diff --git a/tests/auto/qmldom/domdata/domitem/forStatements.qml b/tests/auto/qmldom/domdata/domitem/forStatements.qml
new file mode 100644
index 0000000000..6c06098309
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/forStatements.qml
@@ -0,0 +1,15 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function f() {
+ let sum = 0, helloWorld = "hello"
+ for (let i = 0; i < 100; i = i + 1) {
+ sum = sum + 1
+ for (;;)
+ i = 42
+ }
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/ifStatements.qml b/tests/auto/qmldom/domdata/domitem/ifStatements.qml
new file mode 100644
index 0000000000..90d1bd3ac8
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/ifStatements.qml
@@ -0,0 +1,27 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ function conditional() {
+ let i = 5
+ if (i)
+ i = 42
+
+ if (i == 55)
+ i = 32
+ else
+ i = i - 1
+
+ if (i == 42) {
+ i = 111
+ }
+
+ if (i == 746) {
+ i = 123
+ } else {
+ i = 456
+ }
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/import.js b/tests/auto/qmldom/domdata/domitem/import.js
new file mode 100644
index 0000000000..e13db4c1a4
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/import.js
@@ -0,0 +1,2 @@
+.import "main.js" as Main
+console.log(Main.a);
diff --git a/tests/auto/qmldom/domdata/domitem/inactiveVisitorMarkerCrash.qml b/tests/auto/qmldom/domdata/domitem/inactiveVisitorMarkerCrash.qml
new file mode 100644
index 0000000000..c706251e47
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/inactiveVisitorMarkerCrash.qml
@@ -0,0 +1,13 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Window {
+ width: 640
+ height: 480
+ visible: true
+ title: qsTr("Hello World")
+
+ HelloWorld { myP: 55; myPPP: 55 }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/inlineComponents.qml b/tests/auto/qmldom/domdata/domitem/inlineComponents.qml
new file mode 100644
index 0000000000..5ae0af4eb1
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/inlineComponents.qml
@@ -0,0 +1,17 @@
+import QtQuick
+
+Item {
+ id: mainComponent
+
+ component IC1: Item { property string firstIC }
+ component IC2: Item { property string secondIC }
+
+ Item {
+ Item {
+ Item {
+ component IC3: Item { property string thirdIC }
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/qmldom/domdata/domitem/inlineObject.qml b/tests/auto/qmldom/domdata/domitem/inlineObject.qml
new file mode 100644
index 0000000000..2f5941f4da
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/inlineObject.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ component IC: Item {}
+ property var myItem: Item {}
+ property var myItem2: IC {}
+}
diff --git a/tests/auto/qmldom/domdata/domitem/invalidAliasProperties.qml b/tests/auto/qmldom/domdata/domitem/invalidAliasProperties.qml
index 266e4139b7..7998642ef5 100644
--- a/tests/auto/qmldom/domdata/domitem/invalidAliasProperties.qml
+++ b/tests/auto/qmldom/domdata/domitem/invalidAliasProperties.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
Item {
diff --git a/tests/auto/qmldom/domdata/domitem/iterationStatements.qml b/tests/auto/qmldom/domdata/domitem/iterationStatements.qml
new file mode 100644
index 0000000000..e75eeb2d7d
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/iterationStatements.qml
@@ -0,0 +1,64 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+
+ function whileStatement() {
+ const i = 10;
+ while (i > 0) {
+ i = i -1;
+ while ( i > 100) {}
+ }
+
+ while (i > 0) i = i-1
+ }
+
+ function doWhile() {
+ let a = 7;
+ do {
+ const b = a;
+ a = a - 1;
+ } while (a > 0)
+
+ do a = a-1; while (a > 0)
+ }
+
+ function forOf() {
+ const iterable = [[1,2], [3,4],]
+ for (var [a,b] of iterable) {
+
+ let t;
+ for (const [a1, , a2, ...rest] of array) {
+
+ }
+ for (const k of [1,2,3,4,,,]) {
+ t += k;
+ }
+ for (t of a) {
+ {}
+ }
+ for (t of a) t += k
+ }
+ }
+
+ function forIn() {
+ const enumerable = {
+ list: [1, 2, 3, 4, 5],
+ name: 'John',
+ age: 25
+ };
+
+ for (var [a,b,c,d] in enumerable) {
+ let t;
+ for (t in enumerable) {
+ {}
+ }
+ for (const [a1, , a2, ...rest] in enumerable.list) {
+
+ }
+ for (let t in enumerable) t += k
+ }
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/lambdas.qml b/tests/auto/qmldom/domdata/domitem/lambdas.qml
new file mode 100644
index 0000000000..c241bb77ae
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/lambdas.qml
@@ -0,0 +1,41 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ signal helloSignal
+
+ function method() {
+ console.log("helloMethod");
+ let myLambda = function(a, b) { return a + b };
+ let myArrow = (v, w) => a + b;
+ }
+
+ onHelloSignal: function(x, y, z) { console.log("HelloLambda"); }
+
+ function testNestedFunctions() {
+ function nested(tic, tac, toe) { return tic + tac/3 + toe/2}
+ nested()
+ }
+
+ function generators() {
+ function *myGeneratorDeclaration(a, b) { yield 5 };
+ let myGenerator = function*(tic, tac, toe) { yield tic + tac - toe };
+ }
+
+ function *generatorInQmlObject() {
+ function nested(q,w,e,r) { return q + w + e - r; }
+ function *nested2(a,z,e,r) { yield a + z + e - r; yield 42; }
+ yield 4;
+ yield* nested2(1,2,3,4);
+ const t = (function (a) {
+ return a + 100;
+ });
+ }
+ function traditionalLambda() {
+ const tradition = (function (a) {
+ return a + 100;
+ });
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/module.mjs b/tests/auto/qmldom/domdata/domitem/module.mjs
new file mode 100644
index 0000000000..6838766329
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/module.mjs
@@ -0,0 +1,6 @@
+
+import { helper } from "utils.mjs"
+
+export function entry() {
+ return helper()
+}
diff --git a/tests/auto/qmldom/domdata/domitem/nullStatements.qml b/tests/auto/qmldom/domdata/domitem/nullStatements.qml
new file mode 100644
index 0000000000..f4be9b30de
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/nullStatements.qml
@@ -0,0 +1,14 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function testForNull() {
+ for (;;)
+ {}
+ for (;;)
+ x
+ {} {} {} {}
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/objectBindings.qml b/tests/auto/qmldom/domdata/domitem/objectBindings.qml
new file mode 100644
index 0000000000..c02a7113a5
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/objectBindings.qml
@@ -0,0 +1,13 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick as QQ
+
+Item {
+ id: root
+ Item {}
+ QQ.Item {}
+ property var x: root.
+ QQ.Drag {}
+}
diff --git a/tests/auto/qmldom/domdata/domitem/propertyBindings.qml b/tests/auto/qmldom/domdata/domitem/propertyBindings.qml
new file mode 100644
index 0000000000..3c2931cb5d
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/propertyBindings.qml
@@ -0,0 +1,13 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ property int a: 42
+ property int b
+
+ b: a
+
+ id: root
+}
diff --git a/tests/auto/qmldom/domdata/domitem/returnStatements.qml b/tests/auto/qmldom/domdata/domitem/returnStatements.qml
new file mode 100644
index 0000000000..4f503244fb
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/returnStatements.qml
@@ -0,0 +1,14 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ // TODO: Add a test for returning void
+ function returningFunction(i) {
+ if (i)
+ return 123;
+ else
+ return 1 + 2;
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/simplestJSStatement.js b/tests/auto/qmldom/domdata/domitem/simplestJSStatement.js
new file mode 100644
index 0000000000..d954a87fc0
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/simplestJSStatement.js
@@ -0,0 +1 @@
+let v=1;
diff --git a/tests/auto/qmldom/domdata/domitem/simplestJSmodule.mjs b/tests/auto/qmldom/domdata/domitem/simplestJSmodule.mjs
new file mode 100644
index 0000000000..401b25314b
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/simplestJSmodule.mjs
@@ -0,0 +1 @@
+export function entry() {}
diff --git a/tests/auto/qmldom/domdata/domitem/switchStatement.qml b/tests/auto/qmldom/domdata/domitem/switchStatement.qml
new file mode 100644
index 0000000000..b2bacec8c0
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/switchStatement.qml
@@ -0,0 +1,28 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ function switchStatement(){
+ const animals = "cat";
+ const no = 0;
+ switch (animals) {
+ case "cat":
+ switch (no) {
+ case 0: return "patron";
+ case 1: return "mafik";
+ default: return "none";
+ }
+ case "dog": {
+ // check if qqmljsscope is created for this case
+ const name = "tekila";
+ let another = "mutantx";
+ return name;
+ }
+ default: return "monster";
+ case "moreCases!":
+ return "moreCaseClauses?"
+ }
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/tryStatements.qml b/tests/auto/qmldom/domdata/domitem/tryStatements.qml
new file mode 100644
index 0000000000..5bd29db058
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/tryStatements.qml
@@ -0,0 +1,10 @@
+import QtQuick
+
+Item {
+ function f() {
+ try { insideTry; } catch(catchExpression) { insideCatch; } finally { insideFinally; }
+ try { insideTry; } catch(catchExpression) { insideCatch; }
+ try { insideTry; } finally { insideFinally; }
+ }
+
+}
diff --git a/tests/auto/qmldom/domdata/domitem/unaryExpressions/decrement.qml b/tests/auto/qmldom/domdata/domitem/unaryExpressions/decrement.qml
new file mode 100644
index 0000000000..fb9fe6f252
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/unaryExpressions/decrement.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ function f(a) {
+ --a;
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/unaryExpressions/delete.qml b/tests/auto/qmldom/domdata/domitem/unaryExpressions/delete.qml
new file mode 100644
index 0000000000..39063b8c2f
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/unaryExpressions/delete.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ function f(a) {
+ delete a;
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/unaryExpressions/increment.qml b/tests/auto/qmldom/domdata/domitem/unaryExpressions/increment.qml
new file mode 100644
index 0000000000..e7acd3dfe5
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/unaryExpressions/increment.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ function f(a) {
+ ++a;
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/unaryExpressions/not.qml b/tests/auto/qmldom/domdata/domitem/unaryExpressions/not.qml
new file mode 100644
index 0000000000..6c3a1aa035
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/unaryExpressions/not.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ function f(a) {
+ !a;
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/unaryExpressions/postDecrement.qml b/tests/auto/qmldom/domdata/domitem/unaryExpressions/postDecrement.qml
new file mode 100644
index 0000000000..52d170fae0
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/unaryExpressions/postDecrement.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ function f(a) {
+ a--;
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/unaryExpressions/postIncrement.qml b/tests/auto/qmldom/domdata/domitem/unaryExpressions/postIncrement.qml
new file mode 100644
index 0000000000..30b4da8c8f
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/unaryExpressions/postIncrement.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ function f(a) {
+ a++;
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/unaryExpressions/tilde.qml b/tests/auto/qmldom/domdata/domitem/unaryExpressions/tilde.qml
new file mode 100644
index 0000000000..b35a00bd79
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/unaryExpressions/tilde.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ function f(a) {
+ ~a;
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/unaryExpressions/typeof.qml b/tests/auto/qmldom/domdata/domitem/unaryExpressions/typeof.qml
new file mode 100644
index 0000000000..1696c5bd27
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/unaryExpressions/typeof.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ function f(a) {
+ typeof a;
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/unaryExpressions/unaryMinus.qml b/tests/auto/qmldom/domdata/domitem/unaryExpressions/unaryMinus.qml
new file mode 100644
index 0000000000..e711c4d2f5
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/unaryExpressions/unaryMinus.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ function f(a) {
+ -a;
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/unaryExpressions/unaryPlus.qml b/tests/auto/qmldom/domdata/domitem/unaryExpressions/unaryPlus.qml
new file mode 100644
index 0000000000..1b9ecbf5b5
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/unaryExpressions/unaryPlus.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ function f(a) {
+ +a;
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/unaryExpressions/void.qml b/tests/auto/qmldom/domdata/domitem/unaryExpressions/void.qml
new file mode 100644
index 0000000000..d9396e1b39
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/unaryExpressions/void.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ function f(a) {
+ void a;
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/variableDeclarations.qml b/tests/auto/qmldom/domdata/domitem/variableDeclarations.qml
new file mode 100644
index 0000000000..7d5d2ac9a5
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/variableDeclarations.qml
@@ -0,0 +1,23 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function count() {
+ let one = 1, two = 2, three = 3, four = 4, five = 5, six = 6
+ let testMe = 123
+ }
+ // for now only numeric literal and string literal is supported
+ function f() {
+ let sum = 0, helloWorld = "hello"
+ const a = 3;
+ const b = "patron";
+ var aa = helloWorld, bb = aa;
+
+ const bool1 = true;
+ let bool2 = false;
+ var nullVar = null;
+ return sum;
+ }
+}
diff --git a/tests/auto/qmldom/domdata/domitem/visitTreeFilter.qml b/tests/auto/qmldom/domdata/domitem/visitTreeFilter.qml
new file mode 100644
index 0000000000..5d0b06f91f
--- /dev/null
+++ b/tests/auto/qmldom/domdata/domitem/visitTreeFilter.qml
@@ -0,0 +1,4 @@
+
+QtObject {
+ property int helloProperty
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted.qml b/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted.qml
index 0911f0e102..ab722f94be 100644
--- a/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted.qml
+++ b/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted.qml
@@ -26,8 +26,10 @@ Item {
// before zz
zz - // after z + zz
/*before (a b)*/(/* before a */ a * /* after a */ b * /*after b*/ c); // after (a * b * c)
+
if (y == 6) // if comment
console.log("pippo");
+
a + b; // comment
// footer
diff --git a/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted2.qml b/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted2.qml
index 522cbbc777..c6e33f9389 100644
--- a/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted2.qml
+++ b/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted2.qml
@@ -26,8 +26,10 @@ Item {
// before zz
zz - // after z + zz
/*before (a b)*/(/* before a */ a * /* after a */ b * /*after b*/ c); // after (a * b * c)
+
if (y == 6) // if comment
console.log("pippo");
+
a + b; // comment
// footer
diff --git a/tests/auto/qmldom/domdata/reformatter/file1.qml b/tests/auto/qmldom/domdata/reformatter/file1.qml
index 36819b9998..e0382bf57c 100644
--- a/tests/auto/qmldom/domdata/reformatter/file1.qml
+++ b/tests/auto/qmldom/domdata/reformatter/file1.qml
@@ -14,6 +14,8 @@ Window {
Rectangle {
anchors.fill: parent
+ Behavior on opacity {}
+
ListView {
width: parent.width
model: {
diff --git a/tests/auto/qmldom/domdata/reformatter/file1Reformatted.qml b/tests/auto/qmldom/domdata/reformatter/file1Reformatted.qml
index 361d054f9c..6a24f907d1 100644
--- a/tests/auto/qmldom/domdata/reformatter/file1Reformatted.qml
+++ b/tests/auto/qmldom/domdata/reformatter/file1Reformatted.qml
@@ -14,6 +14,9 @@ Window {
Rectangle {
anchors.fill: parent
+ Behavior on opacity {
+ }
+
ListView {
model: {
MySingleton.mySignal();
@@ -38,7 +41,7 @@ Window {
function f(v = 4) {
let c = 0;
return {
- "a": function () {
+ a: function () {
if (b == 0)
c += 78 * 5 * v;
}()
diff --git a/tests/auto/qmldom/domdata/reformatter/file1Reformatted2.qml b/tests/auto/qmldom/domdata/reformatter/file1Reformatted2.qml
index 18c719020c..2e7483f453 100644
--- a/tests/auto/qmldom/domdata/reformatter/file1Reformatted2.qml
+++ b/tests/auto/qmldom/domdata/reformatter/file1Reformatted2.qml
@@ -14,6 +14,8 @@ Window {
Rectangle {
anchors.fill: parent
+ Behavior on opacity {}
+
ListView {
width: parent.width
model: {
@@ -32,7 +34,7 @@ Window {
function f(v = 4) {
let c = 0;
return {
- "a": function () {
+ a: function () {
if (b == 0)
c += 78 * 5 * v;
}()
diff --git a/tests/auto/qmldom/domdata/reformatter/file1Unindented.qml b/tests/auto/qmldom/domdata/reformatter/file1Unindented.qml
index 224f1c1dce..4085b91e6e 100644
--- a/tests/auto/qmldom/domdata/reformatter/file1Unindented.qml
+++ b/tests/auto/qmldom/domdata/reformatter/file1Unindented.qml
@@ -14,6 +14,8 @@ property var arrTrailingComma: [1,2,3,]
Rectangle {
anchors.fill: parent
+Behavior on opacity {}
+
ListView {
width: parent.width
model: {
diff --git a/tests/auto/qmldom/domdata/reformatter/file2Reformatted.qml b/tests/auto/qmldom/domdata/reformatter/file2Reformatted.qml
index 48a961930d..3ed3aa208c 100644
--- a/tests/auto/qmldom/domdata/reformatter/file2Reformatted.qml
+++ b/tests/auto/qmldom/domdata/reformatter/file2Reformatted.qml
@@ -52,7 +52,7 @@ Window {
function f(v) {
let c = 0;
return {
- "a": function () {
+ a: function () {
if (b == 0)
c += 78 * 5 * v;
}()
diff --git a/tests/auto/qmldom/domdata/reformatter/requiredReformatted2.qml b/tests/auto/qmldom/domdata/reformatter/requiredReformatted2.qml
index cb84168307..7473283605 100644
--- a/tests/auto/qmldom/domdata/reformatter/requiredReformatted2.qml
+++ b/tests/auto/qmldom/domdata/reformatter/requiredReformatted2.qml
@@ -8,7 +8,7 @@ Item {
function foo() {
theItem.foo("The issue is exacerbated if the object literal is wrapped onto the next line like so:", {
- "foo": theFoo
- });
+ "foo": theFoo
+ });
}
}
diff --git a/tests/auto/qmldom/domdata/reformatter/spreadReformatted.qml b/tests/auto/qmldom/domdata/reformatter/spreadReformatted.qml
index b01eca88d3..fde8ffd686 100644
--- a/tests/auto/qmldom/domdata/reformatter/spreadReformatted.qml
+++ b/tests/auto/qmldom/domdata/reformatter/spreadReformatted.qml
@@ -4,7 +4,7 @@ Item {
function foo() {
iterableObj = [1, 2];
obj = {
- "a": 42
+ a: 42
};
let x = (console.log("bla\n"), 3);
myFunction(...iterableObj); // pass all elements of iterableObj as arguments to function myFunction
diff --git a/tests/auto/qmldom/domitem/CMakeLists.txt b/tests/auto/qmldom/domitem/CMakeLists.txt
index bf12ad866c..e6f8117902 100644
--- a/tests/auto/qmldom/domitem/CMakeLists.txt
+++ b/tests/auto/qmldom/domitem/CMakeLists.txt
@@ -6,6 +6,13 @@
#####################################################################
## tst_qmldomitem Test:
#####################################################################
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmldomitem LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/..
diff --git a/tests/auto/qmldom/domitem/tst_qmldomitem.cpp b/tests/auto/qmldom/domitem/tst_qmldomitem.cpp
index ea450e6969..97b7dcc3ed 100644
--- a/tests/auto/qmldom/domitem/tst_qmldomitem.cpp
+++ b/tests/auto/qmldom/domitem/tst_qmldomitem.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_qmldomitem.h"
QTEST_MAIN(QQmlJS::Dom::TestDomItem)
diff --git a/tests/auto/qmldom/domitem/tst_qmldomitem.h b/tests/auto/qmldom/domitem/tst_qmldomitem.h
index 433a92a2b2..6c74b7f746 100644
--- a/tests/auto/qmldom/domitem/tst_qmldomitem.h
+++ b/tests/auto/qmldom/domitem/tst_qmldomitem.h
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TST_QMLDOMITEM_H
#define TST_QMLDOMITEM_H
@@ -9,6 +9,7 @@
#include <QtQmlDom/private/qqmldommock_p.h>
#include <QtQmlDom/private/qqmldomcompare_p.h>
#include <QtQmlDom/private/qqmldomfieldfilter_p.h>
+#include <QtQmlDom/private/qqmldomscriptelements_p.h>
#include <QtTest/QtTest>
#include <QtCore/QCborValue>
@@ -16,14 +17,18 @@
#include <QtCore/QLibraryInfo>
#include <QtCore/QFileInfo>
+#include <deque>
#include <memory>
+#include <utility>
+#include <variant>
+#include <vector>
QT_BEGIN_NAMESPACE
namespace QQmlJS {
namespace Dom {
-inline DomItem wrapInt(DomItem &self, const PathEls::PathComponent &p, const int &i)
+inline DomItem wrapInt(const DomItem &self, const PathEls::PathComponent &p, const int &i)
{
return self.subDataItem(p, i);
}
@@ -51,8 +56,9 @@ private slots:
qmltypeDirs = QStringList({ baseDir, QLibraryInfo::path(QLibraryInfo::QmlImportsPath) });
universePtr =
std::shared_ptr<DomUniverse>(new DomUniverse(QStringLiteral(u"dummyUniverse")));
- envPtr = std::shared_ptr<DomEnvironment>(new DomEnvironment(
- QStringList(), DomEnvironment::Option::SingleThreaded, universePtr));
+ envPtr = std::shared_ptr<DomEnvironment>(
+ new DomEnvironment(QStringList(), DomEnvironment::Option::SingleThreaded,
+ DomCreationOption::None, universePtr));
env = DomItem(envPtr);
testOwnerPtr = std::shared_ptr<MockOwner>(new MockOwner(
Path::Root(u"env").field(u"testOwner"), 0,
@@ -363,7 +369,7 @@ private slots:
auto tOwner3 = tOwner.path(u"$env.testOwner");
QCOMPARE(tOwner3.internalKind(), DomType::MockOwner);
QList<qint64> values;
- tOwner.visitTree(Path(), [&values](Path p, DomItem i, bool) {
+ tOwner.visitTree(Path(), [&values](const Path &p, DomItem i, bool) {
if (i.pathFromOwner() != p)
myErrors()
.error(QStringLiteral(u"unexpected path %1 %2")
@@ -403,18 +409,15 @@ private slots:
qmltypeDirs,
QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
| QQmlJS::Dom::DomEnvironment::Option::NoDependencies,
- univPtr));
+ DomCreationOption::None, univPtr));
QQmlJS::Dom::DomItem env(envPtr);
QVERIFY(env);
QString testFile1 = baseDir + QLatin1String("/test1.qml");
DomItem tFile;
- // env.loadBuiltins();
- env.loadFile(
- testFile1, QString(),
- [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; },
- LoadOption::DefaultLoad);
- env.loadFile(baseDir, QString(), {}, LoadOption::DefaultLoad);
- env.loadPendingDependencies();
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, testFile1),
+ [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; });
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, baseDir), {});
+ envPtr->loadPendingDependencies();
QVERIFY(tFile);
tFile = tFile.field(Fields::currentItem);
@@ -424,7 +427,7 @@ private slots:
DomItem obj1 = comp1.field(Fields::objects).index(0);
QVERIFY(obj1);
- tFile.visitTree(Path(), [&tFile](Path p, DomItem i, bool) {
+ tFile.visitTree(Path(), [&tFile](const Path &p, DomItem i, bool) {
if (!(i == i.path(i.canonicalPath()))) {
DomItem i2 = i.path(i.canonicalPath());
qDebug() << p << i.canonicalPath() << i.internalKindStr() << i2.internalKindStr()
@@ -489,18 +492,16 @@ private slots:
auto univPtr = std::shared_ptr<QQmlJS::Dom::DomUniverse>(
new QQmlJS::Dom::DomUniverse(QLatin1String("univ1")));
auto envPtr = std::shared_ptr<QQmlJS::Dom::DomEnvironment>(new QQmlJS::Dom::DomEnvironment(
- qmltypeDirs, QQmlJS::Dom::DomEnvironment::Option::SingleThreaded, univPtr));
+ qmltypeDirs, QQmlJS::Dom::DomEnvironment::Option::SingleThreaded, {}, univPtr));
QQmlJS::Dom::DomItem env(envPtr);
QVERIFY(env);
QString testFile1 = baseDir + QLatin1String("/test1.qml");
DomItem tFile;
- env.loadBuiltins();
- env.loadFile(
- testFile1, QString(),
- [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; },
- LoadOption::DefaultLoad);
- env.loadFile(baseDir, QString(), {}, LoadOption::DefaultLoad);
- env.loadPendingDependencies();
+ envPtr->loadBuiltins();
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, testFile1),
+ [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; });
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, baseDir), {});
+ envPtr->loadPendingDependencies();
QVERIFY(tFile);
tFile = tFile.field(Fields::currentItem);
@@ -531,13 +532,13 @@ private slots:
QList<DomItem> rects;
obj1.resolve(
Path::Current(PathCurrent::Lookup).field(Fields::type).key(u"Rectangle"_s),
- [&rects](Path, DomItem &el) {
+ [&rects](Path, const DomItem &el) {
rects.append(el);
return true;
},
{});
QVERIFY(rects.size() == 1);
- for (DomItem &el : rects) {
+ for (const DomItem &el : rects) {
QCOMPARE(rect.first(), el);
}
}
@@ -548,6 +549,13 @@ private slots:
DomItem f2 = env.path(p2);
QVERIFY2(f2, "Directory dependencies did not load MySingleton.qml");
}
+ {
+ QString fPath = tFile.canonicalFilePath();
+ QString fPath2 = fPath.mid(0, fPath.lastIndexOf(u'/')) % u"/ImportMeImplicitly.ui.qml";
+ Path p2 = Paths::qmlFileObjectPath(fPath2);
+ DomItem f2 = env.path(p2);
+ QVERIFY2(f2, "Directory dependencies did not load .ui.qml file!");
+ }
}
void testImports()
@@ -558,17 +566,17 @@ private slots:
using namespace Qt::StringLiterals;
QString testFile1 = baseDir + QLatin1String("/TestImports.qml");
- DomItem env = DomEnvironment::create(
+ auto envPtr = DomEnvironment::create(
QStringList(),
QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
| QQmlJS::Dom::DomEnvironment::Option::NoDependencies);
DomItem tFile;
- env.loadFile(
- testFile1, QString(),
- [&tFile](Path, DomItem &, DomItem &newIt) { tFile = newIt.fileObject(); },
- LoadOption::DefaultLoad);
- env.loadPendingDependencies();
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, testFile1),
+ [&tFile](Path, const DomItem &, const DomItem &newIt) {
+ tFile = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
QVERIFY(tFile);
QList<QmlUri> importedModules;
@@ -601,17 +609,15 @@ private slots:
{
QString testFile = baseDir + QLatin1String("/test1.qml");
- DomItem env = DomEnvironment::create(
+ auto envPtr = DomEnvironment::create(
qmltypeDirs,
QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
| QQmlJS::Dom::DomEnvironment::Option::NoDependencies);
DomItem tFile; // place where to store the loaded file
- env.loadFile(
- testFile, QString(),
- [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; },
- LoadOption::DefaultLoad);
- env.loadPendingDependencies();
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, testFile),
+ [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; });
+ envPtr->loadPendingDependencies();
DomItem f = tFile.fileObject();
QString dump1;
f.dump([&dump1](QStringView v) { dump1.append(v); });
@@ -626,6 +632,7 @@ private slots:
if (!diffs.isEmpty())
qDebug() << "testDeepCopy.diffs:" << diffs;
QVERIFY(diffs.isEmpty());
+ DomItem env(envPtr);
DomItem univFile = env.universe().path(f.canonicalPath());
MutableDomItem univFileCopy = univFile.makeCopy();
QStringList univFileDiffs =
@@ -645,11 +652,12 @@ private slots:
void testInMemory()
{
DomItem res = DomItem::fromCode("MyItem{}");
+ QCOMPARE(res.qmlObject(GoTo::Strict), DomItem());
DomItem obj = res.qmlObject(GoTo::MostLikely);
QCOMPARE(obj.name(), u"MyItem");
}
- static void checkAliases(DomItem &qmlObj)
+ static void checkAliases(const DomItem &qmlObj)
{
using namespace Qt::StringLiterals;
@@ -714,7 +722,7 @@ private slots:
}
++i;
}
- for (DomItem obj : qmlObj.children().values()) {
+ for (const DomItem &obj : qmlObj.children().values()) {
if (obj.as<QmlObject>())
checkAliases(obj);
}
@@ -734,22 +742,3185 @@ private slots:
QFETCH(QString, inFile);
QString testFile1 = baseDir + u"/"_s + inFile;
- DomItem env = DomEnvironment::create(
+ auto envPtr = DomEnvironment::create(
QStringList(),
QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
| QQmlJS::Dom::DomEnvironment::Option::NoDependencies);
DomItem tFile;
- env.loadFile(
- testFile1, QString(),
- [&tFile](Path, DomItem &, DomItem &newIt) { tFile = newIt.fileObject(); },
- LoadOption::DefaultLoad);
- env.loadPendingDependencies();
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, testFile1),
+ [&tFile](Path, const DomItem &, const DomItem &newIt) {
+ tFile = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
DomItem rootObj = tFile.qmlObject(GoTo::MostLikely);
checkAliases(rootObj);
}
+ void inlineComponents()
+ {
+ using namespace Qt::StringLiterals;
+
+ QString testFile = baseDir + u"/inlineComponents.qml"_s;
+
+ DomCreationOptions options{ DomCreationOption::WithScriptExpressions };
+ auto envPtr = DomEnvironment::create(
+ QStringList(),
+ QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
+ | QQmlJS::Dom::DomEnvironment::Option::NoDependencies, options);
+
+ DomItem tFile;
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, testFile),
+ [&tFile](Path, const DomItem &, const DomItem &newIt) {
+ tFile = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
+
+ auto rootQmlObject = tFile.rootQmlObject(GoTo::MostLikely);
+
+ // check if the lookup can find the inline components correctly, to see if the
+ // visitScopeChain also visit them.
+ auto ic3 = rootQmlObject.lookup("IC3", LookupType::Type, LookupOption::Normal,
+ [](const ErrorMessage &) {});
+
+ QCOMPARE(ic3.size(), 1);
+ QCOMPARE(ic3.front().name(), "inlineComponents.IC3");
+ QCOMPARE(ic3.front().field(Fields::nameIdentifiers).internalKind(), DomType::ScriptType);
+ QCOMPARE(ic3.front()
+ .field(Fields::nameIdentifiers)
+ .field(Fields::typeName)
+ .value()
+ .toString(),
+ u"IC3"_s);
+
+ auto ic1 = rootQmlObject.lookup("IC1", LookupType::Type, LookupOption::Normal,
+ [](const ErrorMessage &) {});
+
+ QCOMPARE(ic1.size(), 1);
+ QCOMPARE(ic1.front().name(), "inlineComponents.IC1");
+ }
+
+ void inlineObject()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/inlineObject.qml"_s;
+
+ auto envPtr = DomEnvironment::create(
+ QStringList(),
+ QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
+ | QQmlJS::Dom::DomEnvironment::Option::NoDependencies);
+
+ DomItem tFile;
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, testFile),
+ [&tFile](Path, const DomItem &, const DomItem &newIt) {
+ tFile = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
+
+ auto rootQmlObject = tFile.rootQmlObject(GoTo::MostLikely);
+
+ // check that the inline objects have their prototypes set.
+
+ {
+ auto prototypes = rootQmlObject.propertyInfos()
+ .key(u"myItem"_s)
+ .field(Fields::bindings)
+ .index(0)
+ .field(Fields::value)
+ .field(Fields::prototypes);
+ QVERIFY(prototypes.internalKind() != DomType::Empty);
+ QCOMPARE(prototypes.indexes(), 1);
+ QCOMPARE(prototypes.index(0)
+ .field(Fields::referredObjectPath)
+ .as<ConstantData>()
+ ->value()
+ .toString(),
+ u"@lookup.type[\"Item\"]"_s);
+ }
+
+ {
+ auto prototypes2 = rootQmlObject.propertyInfos()
+ .key(u"myItem2"_s)
+ .field(Fields::bindings)
+ .index(0)
+ .field(Fields::value)
+ .field(Fields::prototypes);
+ QVERIFY(prototypes2.internalKind() != DomType::Empty);
+ QCOMPARE(prototypes2.indexes(), 1);
+ QCOMPARE(prototypes2.index(0)
+ .field(Fields::referredObjectPath)
+ .as<ConstantData>()
+ ->value()
+ .toString(),
+ u"@lookup.type[\"IC\"]"_s);
+ }
+ }
+
+ void scopesInDom()
+ {
+ QString fileName = baseDir + u"/checkScopes.qml"_s;
+
+ const QStringList importPaths = {
+ QLibraryInfo::path(QLibraryInfo::QmlImportsPath),
+ };
+
+ DomItem tFile;
+
+ auto envPtr = DomEnvironment::create(
+ importPaths,
+ QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
+ | QQmlJS::Dom::DomEnvironment::Option::NoDependencies,
+ WithSemanticAnalysis);
+
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, fileName),
+ [&tFile](Path, const DomItem &, const DomItem &newIt) {
+ tFile = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
+
+ auto root = tFile.rootQmlObject(GoTo::MostLikely);
+
+ {
+ auto rootQmlObject = root.as<QmlObject>();
+ QVERIFY(rootQmlObject);
+ auto rootScope = rootQmlObject->semanticScope();
+ QVERIFY(rootScope);
+ QVERIFY(rootScope->hasOwnProperty("myInt"));
+ QVERIFY(rootScope->hasOwnProperty("myInt2"));
+ QVERIFY(rootScope->hasOwnPropertyBindings("myInt"));
+ QVERIFY(rootScope->hasOwnPropertyBindings("myInt2"));
+ }
+ }
+
+ void propertyBindings()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/propertyBindings.qml"_s;
+ DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ // check the binding to a and b
+ DomItem a = rootQmlObject.path(".bindings[\"a\"][0].value.scriptElement.value");
+ QCOMPARE(a.value().toDouble(), 42);
+
+ DomItem b = rootQmlObject.path(".bindings[\"b\"][0].value.scriptElement.identifier");
+ QCOMPARE(b.value().toString(), "a");
+
+ DomItem root = rootQmlObject.path(".idStr");
+ QCOMPARE(root.value().toString(), "root");
+
+ DomItem componentIds = rootQmlObject.component().path(".ids");
+ QCOMPARE(componentIds.keys(), QSet<QString>({ "root" }));
+
+ DomItem idScriptExpression =
+ componentIds.key("root").index(0).field(Fields::value).field(Fields::scriptElement);
+ QCOMPARE(idScriptExpression.internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(idScriptExpression.field(Fields::identifier).value().toString(), "root");
+ }
+
+ void variableDeclarations()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/variableDeclarations.qml"_s;
+ DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ DomItem block = rootQmlObject.path(".methods[\"f\"][0].body.scriptElement");
+
+ // check that variabledeclarationlists and statement lists are correctly collected
+ {
+ // let one = 1, two = 2, three = 3, four = 4, five = 5, six = 6
+ std::vector<QString> data = { u"one"_s, u"two"_s, u"three"_s,
+ u"four"_s, u"five"_s, u"six"_s };
+ DomItem block =
+ rootQmlObject.path(".methods[\"count\"][0].body.scriptElement.statements");
+ DomItem variableDeclaration = block.index(0).field(Fields::declarations);
+ QCOMPARE((size_t)variableDeclaration.indexes(), data.size());
+ for (size_t i = 0; i < data.size(); ++i) {
+ DomItem variableDeclarationEntry = variableDeclaration.index(i);
+ QCOMPARE(variableDeclarationEntry.field(Fields::identifier).value().toString(),
+ data[i]);
+ QCOMPARE((size_t)variableDeclarationEntry.field(Fields::initializer)
+ .value()
+ .toInteger(),
+ i + 1);
+ }
+ // let testMe = 123
+ DomItem testDeclaration = block.index(1).field(Fields::declarations);
+ QCOMPARE(testDeclaration.indexes(), 1);
+ QCOMPARE(testDeclaration.index(0).field(Fields::identifier).value().toString(),
+ u"testMe"_s);
+ QCOMPARE(testDeclaration.index(0).field(Fields::initializer).value().toInteger(),
+ 123ll);
+ }
+
+ // if there is a failure in the following line, then thats because either the
+ // variabledeclarationlist or the statement list was wrongly collected and the
+ // domcreator gave up on creating the Dom (unexpected DomType: DomType::ScriptExpression
+ // means that no Dom was constructed for f's body)
+
+ // This block should have a semantic scope that defines sum and helloWorld
+ auto blockSemanticScope = block.semanticScope();
+ QVERIFY(blockSemanticScope);
+ QVERIFY(blockSemanticScope);
+ QVERIFY(blockSemanticScope->ownJSIdentifier(u"sum"_s));
+ QVERIFY(blockSemanticScope->ownJSIdentifier(u"helloWorld"_s));
+ QVERIFY(blockSemanticScope->ownJSIdentifier(u"a"_s));
+ QVERIFY(blockSemanticScope->ownJSIdentifier(u"b"_s));
+ QVERIFY(blockSemanticScope->ownJSIdentifier(u"aa"_s));
+ QVERIFY(blockSemanticScope->ownJSIdentifier(u"bb"_s));
+ QVERIFY(blockSemanticScope->ownJSIdentifier(u"bool1"_s));
+ QVERIFY(blockSemanticScope->ownJSIdentifier(u"bool2"_s));
+ QVERIFY(blockSemanticScope->ownJSIdentifier(u"nullVar"_s));
+ DomItem statements = block.field(Fields::statements);
+ QCOMPARE(statements.indexes(), 8);
+
+ // avoid that toInteger calls return 0 on error, which sometimes is the correct response.
+ const int invalidEnumValue = 9999;
+
+ {
+ // let sum = 0, helloWorld = "hello"
+ DomItem variableDeclaration = statements.index(0).field(Fields::declarations);
+ QCOMPARE(variableDeclaration.indexes(), 2);
+ DomItem sumInitialization = variableDeclaration.index(0);
+ QEXPECT_FAIL(0, "ScopeTypes not implmented yet, as not needed by qmlls for now!",
+ Continue);
+ QCOMPARE(sumInitialization.field(Fields::scopeType).value().toInteger(invalidEnumValue),
+ ScriptElements::VariableDeclarationEntry::ScopeType::Let);
+ QCOMPARE(sumInitialization.field(Fields::identifier).value().toString(), "sum");
+ QCOMPARE(sumInitialization.field(Fields::initializer)
+ .field(Fields::value)
+ .value()
+ .toDouble(),
+ 0);
+
+ DomItem helloWorldInitialization = variableDeclaration.index(1);
+ QEXPECT_FAIL(0, "ScopeTypes not implmented yet, as not needed by qmlls for now!",
+ Continue);
+ QCOMPARE(helloWorldInitialization.field(Fields::scopeType)
+ .value()
+ .toInteger(invalidEnumValue),
+ ScriptElements::VariableDeclarationEntry::ScopeType::Let);
+ QCOMPARE(helloWorldInitialization.field(Fields::identifier).value().toString(),
+ "helloWorld");
+ QCOMPARE(helloWorldInitialization.field(Fields::initializer)
+ .field(Fields::value)
+ .value()
+ .toString(),
+ "hello");
+ }
+ {
+ // const a = 3
+ DomItem a = statements.index(1).field(Fields::declarations).index(0);
+ QEXPECT_FAIL(0, "ScopeTypes not implmented yet, as not needed by qmlls for now!",
+ Continue);
+ QCOMPARE(a.field(Fields::scopeType).value().toInteger(invalidEnumValue),
+ ScriptElements::VariableDeclarationEntry::ScopeType::Const);
+ QCOMPARE(a.field(Fields::identifier).value().toString(), "a");
+ QCOMPARE(a.field(Fields::initializer).internalKind(), DomType::ScriptLiteral);
+ QCOMPARE(a.field(Fields::initializer).field(Fields::value).value().toInteger(), 3);
+ }
+ {
+ // const b = "patron"
+ DomItem b = statements.index(2).field(Fields::declarations).index(0);
+ QEXPECT_FAIL(0, "ScopeTypes not implmented yet, as not needed by qmlls for now!",
+ Continue);
+ QCOMPARE(b.field(Fields::scopeType).value().toInteger(invalidEnumValue),
+ ScriptElements::VariableDeclarationEntry::ScopeType::Const);
+ QCOMPARE(b.field(Fields::identifier).value().toString(), "b");
+ QCOMPARE(b.field(Fields::initializer).internalKind(), DomType::ScriptLiteral);
+ QCOMPARE(b.field(Fields::initializer).field(Fields::value).value().toString(),
+ "patron");
+ }
+ {
+ // var aa = helloWorld
+ DomItem aa = statements.index(3).field(Fields::declarations).index(0);
+ QEXPECT_FAIL(0, "ScopeTypes not implmented yet, as not needed by qmlls for now!",
+ Continue);
+ QCOMPARE(aa.field(Fields::scopeType).value().toInteger(invalidEnumValue),
+ ScriptElements::VariableDeclarationEntry::ScopeType::Var);
+ QCOMPARE(aa.field(Fields::identifier).value().toString(), "aa");
+ QCOMPARE(aa.field(Fields::initializer).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(aa.field(Fields::initializer).field(Fields::identifier).value().toString(),
+ "helloWorld");
+ // var bb = aa
+ DomItem bb = statements.index(3).field(Fields::declarations).index(1);
+ QEXPECT_FAIL(0, "ScopeTypes not implmented yet, as not needed by qmlls for now!",
+ Continue);
+ QCOMPARE(bb.field(Fields::scopeType).value().toInteger(invalidEnumValue),
+ ScriptElements::VariableDeclarationEntry::ScopeType::Var);
+ QCOMPARE(bb.field(Fields::identifier).value().toString(), "bb");
+ QCOMPARE(bb.field(Fields::initializer).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(bb.field(Fields::initializer).field(Fields::identifier).value().toString(),
+ "aa");
+ }
+ {
+ // const bool1 = true
+ DomItem bool1 = statements.index(4).field(Fields::declarations).index(0);
+ QEXPECT_FAIL(0, "ScopeTypes not implmented yet, as not needed by qmlls for now!",
+ Continue);
+ QCOMPARE(bool1.field(Fields::scopeType).value().toInteger(invalidEnumValue),
+ ScriptElements::VariableDeclarationEntry::ScopeType::Const);
+ QCOMPARE(bool1.field(Fields::identifier).value().toString(), "bool1");
+ QCOMPARE(bool1.field(Fields::initializer).internalKind(), DomType::ScriptLiteral);
+ QVERIFY(bool1.field(Fields::initializer).field(Fields::value).value().isTrue());
+ }
+ {
+ // let bool2 = false
+ DomItem bool2 = statements.index(5).field(Fields::declarations).index(0);
+ QEXPECT_FAIL(0, "ScopeTypes not implmented yet, as not needed by qmlls for now!",
+ Continue);
+ QCOMPARE(bool2.field(Fields::scopeType).value().toInteger(invalidEnumValue),
+ ScriptElements::VariableDeclarationEntry::ScopeType::Let);
+ QCOMPARE(bool2.field(Fields::identifier).value().toString(), "bool2");
+ QCOMPARE(bool2.field(Fields::initializer).internalKind(), DomType::ScriptLiteral);
+ QVERIFY(bool2.field(Fields::initializer).field(Fields::value).value().isFalse());
+ }
+ {
+ // var nullVar = null
+ DomItem nullVar = statements.index(6).field(Fields::declarations).index(0);
+ QEXPECT_FAIL(0, "ScopeTypes not implmented yet, as not needed by qmlls for now!",
+ Continue);
+ QCOMPARE(nullVar.field(Fields::scopeType).value().toInteger(invalidEnumValue),
+ ScriptElements::VariableDeclarationEntry::ScopeType::Var);
+ QCOMPARE(nullVar.field(Fields::identifier).value().toString(), "nullVar");
+ QCOMPARE(nullVar.field(Fields::initializer).internalKind(), DomType::ScriptLiteral);
+ QVERIFY(nullVar.field(Fields::initializer).field(Fields::value).value().isNull());
+ }
+ }
+
+ void ifStatements()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/ifStatements.qml"_s;
+ DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ DomItem block = rootQmlObject.path(".methods[\"conditional\"][0].body.scriptElement");
+ auto blockSemanticScope = block.semanticScope();
+ QVERIFY(blockSemanticScope);
+
+ DomItem statements = block.field(Fields::statements);
+ QCOMPARE(statements.indexes(), 5);
+
+ // let i = 5
+ DomItem iDeclaration = statements.index(0);
+ QCOMPARE(iDeclaration.internalKind(), DomType::ScriptVariableDeclaration);
+
+ {
+ // if (i)
+ // i = 42
+ DomItem conditional = statements.index(1);
+ DomItem condition = conditional.field(Fields::condition);
+ QCOMPARE(condition.internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(condition.field(Fields::identifier).value().toString(), u"i"_s);
+
+ DomItem consequence = conditional.field(Fields::consequence);
+ auto nonBlockSemanticScope = consequence.semanticScope();
+ QVERIFY(!nonBlockSemanticScope); // because there is no block
+
+ QCOMPARE(consequence.internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(consequence.field(Fields::left).field(Fields::identifier).value().toString(),
+ u"i"_s);
+ QCOMPARE(consequence.field(Fields::right).field(Fields::value).value().toDouble(), 42);
+
+ QCOMPARE(conditional.field(Fields::alternative).internalKind(), DomType::Empty);
+ }
+ {
+ // if (i == 55)
+ // i = 32
+ // else
+ // i = i - 1
+ DomItem conditional = statements.index(2);
+ DomItem condition = conditional.field(Fields::condition);
+ QCOMPARE(condition.internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(condition.field(Fields::right).field(Fields::value).value().toDouble(), 55);
+
+ DomItem consequence = conditional.field(Fields::consequence);
+ auto nonBlockSemanticScope = consequence.semanticScope();
+ QVERIFY(!nonBlockSemanticScope);
+
+ QCOMPARE(consequence.internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(consequence.field(Fields::left).field(Fields::identifier).value().toString(),
+ u"i"_s);
+ QCOMPARE(consequence.field(Fields::right).field(Fields::value).value().toDouble(), 32);
+
+ DomItem alternative = conditional.field(Fields::alternative);
+ QCOMPARE(alternative.internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(alternative.field(Fields::left).field(Fields::identifier).value().toString(),
+ u"i"_s);
+ QCOMPARE(alternative.field(Fields::right).internalKind(),
+ DomType::ScriptBinaryExpression);
+ }
+ {
+ // if (i == 42) {
+ // i = 111
+ // }
+ DomItem conditional = statements.index(3);
+ DomItem condition = conditional.field(Fields::condition);
+ QCOMPARE(condition.internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(condition.field(Fields::right).field(Fields::value).value().toDouble(), 42);
+
+ DomItem consequence = conditional.field(Fields::consequence);
+ auto blockSemanticScope = consequence.semanticScope();
+ QVERIFY(blockSemanticScope);
+
+ QCOMPARE(consequence.internalKind(), DomType::ScriptBlockStatement);
+ QCOMPARE(consequence.field(Fields::statements).indexes(), 1);
+ DomItem consequence1 = consequence.field(Fields::statements).index(0);
+ QCOMPARE(consequence1.field(Fields::left).field(Fields::identifier).value().toString(),
+ u"i"_s);
+ QCOMPARE(consequence1.field(Fields::right).field(Fields::value).value().toDouble(),
+ 111);
+
+ QCOMPARE(conditional.field(Fields::alternative).internalKind(), DomType::Empty);
+ }
+ {
+ // if (i == 746) {
+ // i = 123
+ // } else {
+ // i = 456
+ // }
+
+ DomItem conditional = statements.index(4);
+ DomItem condition = conditional.field(Fields::condition);
+ QCOMPARE(condition.internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(condition.field(Fields::right).field(Fields::value).value().toDouble(), 746);
+
+ {
+ DomItem consequence = conditional.field(Fields::consequence);
+ QCOMPARE(consequence.internalKind(), DomType::ScriptBlockStatement);
+ QCOMPARE(consequence.field(Fields::statements).indexes(), 1);
+ DomItem consequence1 = consequence.field(Fields::statements).index(0);
+ QCOMPARE(consequence1.field(Fields::left)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"i"_s);
+ QCOMPARE(consequence1.field(Fields::right).field(Fields::value).value().toDouble(),
+ 123);
+ }
+
+ {
+ DomItem alternative = conditional.field(Fields::alternative);
+ auto blockSemanticScope = alternative.semanticScope();
+ QVERIFY(blockSemanticScope);
+
+ QCOMPARE(alternative.internalKind(), DomType::ScriptBlockStatement);
+ QCOMPARE(alternative.field(Fields::statements).indexes(), 1);
+ DomItem alternative1 = alternative.field(Fields::statements).index(0);
+ QCOMPARE(alternative1.field(Fields::left)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"i"_s);
+ QCOMPARE(alternative1.field(Fields::right).field(Fields::value).value().toDouble(),
+ 456);
+ }
+ }
+ }
+
+ void returnStatement()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/returnStatements.qml"_s;
+ DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ DomItem block = rootQmlObject.path(".methods[\"returningFunction\"][0].body.scriptElement");
+ QCOMPARE(block.internalKind(), DomType::ScriptBlockStatement);
+ QCOMPARE(block.field(Fields::statements).indexes(), 1);
+ DomItem conditional = block.field(Fields::statements).index(0);
+ DomItem consequence = conditional.field(Fields::consequence);
+ QCOMPARE(consequence.internalKind(), DomType::ScriptReturnStatement);
+ {
+ DomItem returnValue = consequence.field(Fields::expression);
+ QCOMPARE(returnValue.internalKind(), DomType::ScriptLiteral);
+ QCOMPARE(returnValue.field(Fields::value).value().toDouble(), 123);
+ }
+ DomItem alternative = conditional.field(Fields::alternative);
+ QCOMPARE(alternative.internalKind(), DomType::ScriptReturnStatement);
+ {
+ DomItem returnValue = alternative.field(Fields::expression);
+ QCOMPARE(returnValue.internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(returnValue.field(Fields::left).field(Fields::value).value().toDouble(), 1);
+ QCOMPARE(returnValue.field(Fields::right).field(Fields::value).value().toDouble(), 2);
+ }
+ }
+
+ void forStatements()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/forStatements.qml"_s;
+ DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ DomItem block = rootQmlObject.path(".methods[\"f\"][0].body.scriptElement");
+ DomItem statements = block.field(Fields::statements);
+ DomItem forLoop = statements.index(1);
+ {
+ // for ( >> let i = 0 << ; i < 100; i = i + 1) {
+ DomItem declarationList =
+ forLoop.field(Fields::declarations).field(Fields::declarations);
+ QCOMPARE(declarationList.internalKind(), DomType::List);
+
+ QCOMPARE(declarationList.indexes(), 1);
+ DomItem declaration = declarationList.index(0);
+
+ QCOMPARE(declaration.internalKind(), DomType::ScriptVariableDeclarationEntry);
+ QCOMPARE(declaration.field(Fields::initializer).internalKind(), DomType::ScriptLiteral);
+
+ QCOMPARE(declaration.field(Fields::identifier).value().toString(), "i");
+ QCOMPARE(declaration.field(Fields::initializer).field(Fields::value).value().toDouble(),
+ 0);
+ }
+ {
+ // for ( let i = 0; >> i < 100 <<; i = i + 1) {
+ DomItem condition = forLoop.field(Fields::condition);
+ QCOMPARE(condition.internalKind(), DomType::ScriptBinaryExpression);
+
+ QCOMPARE(condition.field(Fields::left).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(condition.field(Fields::left).field(Fields::identifier).value().toString(),
+ "i");
+
+ QCOMPARE(condition.field(Fields::right).internalKind(), DomType::ScriptLiteral);
+ QCOMPARE(condition.field(Fields::right).field(Fields::value).value().toDouble(), 100);
+ }
+ {
+ // for ( let i = 0; i < 100; >> i = i + 1 << ) {
+ DomItem expression = forLoop.field(Fields::expression);
+ QCOMPARE(expression.internalKind(), DomType::ScriptBinaryExpression);
+ DomItem left = expression.field(Fields::left);
+ QCOMPARE(left.internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(left.field(Fields::identifier).value().toString(), "i");
+
+ // for ( let i = 0; i < 100; i = >> i + 1 << ) {
+ DomItem right = expression.field(Fields::right);
+ QCOMPARE(right.internalKind(), DomType::ScriptBinaryExpression);
+ DomItem left2 = right.field(Fields::left);
+ QCOMPARE(left2.internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(left2.field(Fields::identifier).value().toString(), "i");
+
+ DomItem right2 = right.field(Fields::right);
+ QCOMPARE(right2.internalKind(), DomType::ScriptLiteral);
+ QCOMPARE(right2.field(Fields::value).value().toDouble(), 1);
+ }
+ {
+ // test the body of the for-loop
+ DomItem body = forLoop.field(Fields::body);
+ QCOMPARE(body.internalKind(), DomType::ScriptBlockStatement);
+ auto blockSemanticScope = body.semanticScope();
+ QVERIFY(blockSemanticScope);
+
+ DomItem statementList = body.field(Fields::statements);
+ QCOMPARE(statementList.indexes(), 2);
+ {
+ // >> sum = sum + 1 <<
+ DomItem binaryExpression = statementList.index(0);
+ QCOMPARE(binaryExpression.internalKind(), DomType::ScriptBinaryExpression);
+
+ DomItem left = binaryExpression.field(Fields::left);
+ QCOMPARE(left.internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(left.field(Fields::identifier).value().toString(), "sum");
+
+ // sum = >> sum + 1 <<
+ DomItem right = binaryExpression.field(Fields::right);
+ QCOMPARE(right.internalKind(), DomType::ScriptBinaryExpression);
+
+ DomItem left2 = right.field(Fields::left);
+ QCOMPARE(left2.internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(left2.field(Fields::identifier).value().toString(), "sum");
+
+ DomItem right2 = right.field(Fields::right);
+ QCOMPARE(right2.internalKind(), DomType::ScriptLiteral);
+ QCOMPARE(right2.field(Fields::value).value().toDouble(), 1);
+ }
+
+ {
+ // >> for (;;) <<
+ // i = 42
+ DomItem innerForLoop = statementList.index(1);
+ QCOMPARE(innerForLoop.internalKind(), DomType::ScriptForStatement);
+ QCOMPARE(innerForLoop.field(Fields::declarations).indexes(), 0);
+ QVERIFY(!innerForLoop.field(Fields::initializer));
+ QVERIFY(!innerForLoop.field(Fields::condition));
+ QVERIFY(!innerForLoop.field(Fields::expression));
+ QVERIFY(innerForLoop.field(Fields::body));
+
+ // for (;;)
+ // >> i = 42 <<
+ DomItem expression = innerForLoop.field(Fields::body);
+ QCOMPARE(expression.internalKind(), DomType::ScriptBinaryExpression);
+
+ DomItem left = expression.field(Fields::left);
+ QCOMPARE(left.internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(left.field(Fields::identifier).value().toString(), "i");
+
+ DomItem right = expression.field(Fields::right);
+ QCOMPARE(right.internalKind(), DomType::ScriptLiteral);
+ QCOMPARE(right.field(Fields::value).value().toDouble(), 42);
+ }
+ }
+ }
+
+ void nullStatements()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/nullStatements.qml"_s;
+ DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ DomItem block = rootQmlObject.methods()
+ .key(u"testForNull"_s)
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement);
+
+ QVERIFY(block);
+ // First for
+ DomItem statements = block.field(Fields::statements);
+ QCOMPARE(statements.internalKind(), DomType::List);
+ QVERIFY(statements.index(0).field(Fields::body).field(Fields::statements).internalKind()
+ != DomType::Empty);
+ QCOMPARE(statements.index(0).field(Fields::body).field(Fields::statements).length(), 0);
+
+ // Second for
+ DomItem secondFor = statements.index(1).field(Fields::body);
+ QVERIFY(secondFor.internalKind() == DomType::ScriptIdentifierExpression);
+ QCOMPARE(secondFor.field(Fields::identifier).value().toString(), u"x"_s);
+
+ // Empty block
+ QVERIFY(statements.index(3).field(Fields::statements).internalKind() != DomType::Empty);
+ QCOMPARE(statements.index(3).field(Fields::statements).length(), 0);
+ }
+
+ void deconstruction()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/callExpressions.qml"_s;
+ DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+
+ DomItem method = rootQmlObject.field(Fields::methods).key(u"deconstruct"_s).index(0);
+ DomItem statement = method.field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements)
+ .index(0);
+ QCOMPARE(statement.internalKind(), DomType::ScriptVariableDeclaration);
+ QCOMPARE(statement.field(Fields::declarations).indexes(), 3);
+
+ {
+ DomItem entry = statement.field(Fields::declarations).index(0);
+ QVERIFY(!entry.field(Fields::identifier));
+ DomItem deconstructedProperty =
+ entry.field(Fields::bindingElement).field(Fields::properties);
+
+ QCOMPARE(deconstructedProperty.indexes(), 1);
+ QCOMPARE(deconstructedProperty.index(0).field(Fields::name).value().toString(), u"a"_s);
+
+ DomItem initializer = entry.field(Fields::initializer).field(Fields::properties);
+ QCOMPARE(initializer.indexes(), 2);
+
+ DomItem a32 = initializer.index(0);
+ QCOMPARE(a32.field(Fields::initializer).value().toInteger(), 32);
+ QCOMPARE(a32.field(Fields::name).value().toString(), "a");
+
+ DomItem b42 = initializer.index(1);
+ QCOMPARE(b42.field(Fields::initializer).value().toInteger(), 42);
+ QCOMPARE(b42.field(Fields::name).value().toString(), "b");
+ }
+ {
+ DomItem entry = statement.field(Fields::declarations).index(1);
+ QVERIFY(!entry.field(Fields::identifier));
+ DomItem deconstructedProperty =
+ entry.field(Fields::bindingElement).field(Fields::properties);
+
+ QCOMPARE(deconstructedProperty.indexes(), 2);
+ QCOMPARE(deconstructedProperty.index(0).field(Fields::name).value().toString(), u"b"_s);
+ QCOMPARE(deconstructedProperty.index(1).field(Fields::name).value().toString(), u"c"_s);
+
+ DomItem initializer = entry.field(Fields::initializer).field(Fields::properties);
+ QCOMPARE(initializer.indexes(), 2);
+
+ DomItem a32 = initializer.index(0);
+ QCOMPARE(a32.field(Fields::initializer).value().toInteger(), 32);
+ QCOMPARE(a32.field(Fields::name).value().toString(), "b");
+
+ DomItem b42 = initializer.index(1);
+ QCOMPARE(b42.field(Fields::initializer).value().toInteger(), 42);
+ QCOMPARE(b42.field(Fields::name).value().toString(), "c");
+ }
+ {
+ DomItem entry = statement.field(Fields::declarations).index(2);
+ QVERIFY(!entry.field(Fields::identifier));
+ DomItem deconstructedProperty =
+ entry.field(Fields::bindingElement).field(Fields::elements);
+
+ QCOMPARE(deconstructedProperty.indexes(), 3);
+ QCOMPARE(deconstructedProperty.index(0).field(Fields::identifier).value().toString(),
+ u"d"_s);
+ QCOMPARE(deconstructedProperty.index(1).field(Fields::identifier).value().toString(),
+ u"e"_s);
+ QCOMPARE(deconstructedProperty.index(2).field(Fields::identifier).value().toString(),
+ u"f"_s);
+
+ DomItem initializer = entry.field(Fields::initializer).field(Fields::elements);
+ QCOMPARE(initializer.indexes(), 3);
+
+ for (int i = 0; i < initializer.indexes(); ++i) {
+ QCOMPARE(initializer.index(i).field(Fields::initializer).value().toInteger(),
+ (i + 1) * 111);
+ }
+ }
+ {
+ DomItem statement = method.field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements)
+ .index(1);
+ DomItem listWithElision = statement.field(Fields::declarations)
+ .index(0)
+ .field(Fields::initializer)
+ .field(Fields::elements);
+ const int listElements = 6;
+ const int elisionCount = 4;
+ QCOMPARE(listWithElision.indexes(), listElements);
+ for (int i = 0; i < elisionCount; ++i) {
+ QCOMPARE(listWithElision.index(i).internalKind(), DomType::ScriptElision);
+ }
+ QCOMPARE(listWithElision.index(elisionCount).internalKind(), DomType::ScriptArrayEntry);
+ QCOMPARE(listWithElision.index(elisionCount + 1).internalKind(),
+ DomType::ScriptElision);
+ }
+ }
+
+ void callExpressions()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/callExpressions.qml"_s;
+ DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+
+ {
+ DomItem p1 = rootQmlObject.path(".bindings[\"p\"][0].value.scriptElement");
+ QCOMPARE(p1.internalKind(), DomType::ScriptCallExpression);
+ QCOMPARE(p1.field(Fields::callee).internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(p1.field(Fields::callee).field(Fields::identifier).value().toString(), "f");
+ QCOMPARE(p1.field(Fields::arguments).internalKind(), DomType::List);
+ QCOMPARE(p1.field(Fields::arguments).indexes(), 0);
+ }
+
+ {
+ DomItem p2 = rootQmlObject.path(".bindings[\"p2\"][0].value.scriptElement");
+ QCOMPARE(p2.internalKind(), DomType::ScriptCallExpression);
+ QCOMPARE(p2.field(Fields::callee).internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(p2.field(Fields::callee).field(Fields::identifier).value().toString(), "f");
+
+ DomItem p2List = p2.field(Fields::arguments);
+ QCOMPARE(p2List.indexes(), 20);
+ for (int i = 0; i < p2List.indexes(); ++i) {
+ QCOMPARE(p2List.index(i).internalKind(), DomType::ScriptLiteral);
+ QCOMPARE(p2List.index(i).field(Fields::value).value().toInteger(), i + 1);
+ }
+ }
+
+ {
+ DomItem p3 = rootQmlObject.path(".bindings[\"p3\"][0].value.scriptElement");
+ QCOMPARE(p3.internalKind(), DomType::ScriptCallExpression);
+ QCOMPARE(p3.field(Fields::callee).internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(p3.field(Fields::callee).field(Fields::identifier).value().toString(), "evil");
+
+ DomItem p3List = p3.field(Fields::arguments);
+ QCOMPARE(p3List.indexes(), 3);
+
+ DomItem firstArg = p3List.index(0);
+ QCOMPARE(firstArg.internalKind(), DomType::ScriptObject);
+
+ {
+ DomItem helloWorld = firstArg.field(Fields::properties).index(0);
+ QCOMPARE(helloWorld.internalKind(), DomType::ScriptProperty);
+ QCOMPARE(helloWorld.field(Fields::initializer).value().toString(), "World");
+ QCOMPARE(helloWorld.field(Fields::name).value().toString(), "hello");
+ }
+
+ {
+ DomItem yyyy = firstArg.field(Fields::properties).index(1);
+ QCOMPARE(yyyy.internalKind(), DomType::ScriptProperty);
+ QCOMPARE(yyyy.field(Fields::initializer).value().toString(), "yyy");
+ QCOMPARE(yyyy.field(Fields::name).value().toString(), "y");
+ }
+
+ DomItem secondArg = p3List.index(1);
+ QCOMPARE(secondArg.internalKind(), DomType::ScriptArray);
+ {
+ for (int i = 0; i < 3; ++i) {
+ DomItem current = secondArg.field(Fields::elements).index(i);
+ QCOMPARE(current.internalKind(), DomType::ScriptArrayEntry);
+ QCOMPARE(current.field(Fields::initializer).value().toInteger(), i + 1);
+ }
+ }
+
+ DomItem thirdArg = p3List.index(2);
+ QCOMPARE(thirdArg.internalKind(), DomType::ScriptObject);
+ {
+ DomItem is = thirdArg.field(Fields::properties).index(0);
+ QCOMPARE(is.internalKind(), DomType::ScriptProperty);
+ QCOMPARE(is.field(Fields::name).value().toString(), "is");
+ DomItem initializer = is.field(Fields::initializer).field(Fields::properties);
+
+ QCOMPARE(initializer.index(0).field(Fields::name).value().toString(), "a");
+ QCOMPARE(initializer.index(0).field(Fields::initializer).value().toInteger(), 111);
+
+ QCOMPARE(initializer.index(1).field(Fields::name).value().toString(), "lot");
+ QCOMPARE(initializer.index(1).field(Fields::initializer).value().toInteger(), 222);
+
+ QCOMPARE(initializer.index(2).field(Fields::name).value().toString(), "of");
+ QCOMPARE(initializer.index(2).field(Fields::initializer).value().toInteger(), 333);
+
+ QCOMPARE(initializer.index(3).field(Fields::name).value().toString(), "fun");
+ QCOMPARE(initializer.index(3).field(Fields::initializer).value().toInteger(), 444);
+
+ QCOMPARE(initializer.index(4).field(Fields::name).value().toString(), "really");
+ QCOMPARE(initializer.index(4)
+ .field(Fields::initializer)
+ .field(Fields::elements)
+ .index(0)
+ .field(Fields::initializer)
+ .value()
+ .toString(),
+ "!");
+ }
+ }
+
+ {
+ DomItem functionFs = rootQmlObject.field(Fields::methods).key(u"f");
+ QCOMPARE(functionFs.indexes(), 1);
+ DomItem functionF = functionFs.index(0);
+
+ QVERIFY(!functionF.semanticScope().isNull());
+ QVERIFY(functionF.semanticScope()->ownJSIdentifier("helloF").has_value());
+ DomItem parameters = functionF.field(Fields::parameters);
+ std::vector<QString> parameterNames = {
+ u"q"_s, u"w"_s, u"e"_s, u"r"_s, u"t"_s, u"y"_s
+ };
+ QCOMPARE(parameterNames.size(), (size_t)parameters.indexes());
+
+ for (size_t i = 0; i < parameterNames.size(); ++i) {
+ DomItem currentParameter = parameters.index(i);
+ QCOMPARE(currentParameter.field(Fields::name).value().toString(),
+ parameterNames[i]);
+ }
+ }
+
+ {
+ DomItem functionFWithDefaults =
+ rootQmlObject.field(Fields::methods).key(u"fWithDefault");
+ QCOMPARE(functionFWithDefaults.indexes(), 1);
+ DomItem functionFWithDefault = functionFWithDefaults.index(0);
+ QVERIFY(!functionFWithDefault.semanticScope().isNull());
+ QVERIFY(functionFWithDefault.semanticScope()->ownJSIdentifier(u"helloFWithDefault"_s));
+ DomItem parameters = functionFWithDefault.field(Fields::parameters);
+
+ const std::vector<QString> parameterNames = { u"q"_s, u"w"_s, u"e"_s,
+ u"r"_s, u"t"_s, u"y"_s };
+ const QSet<QString> parameterWithoutDefault = { u"e"_s, u"t"_s };
+
+ QCOMPARE(parameterNames.size(), (size_t)parameters.indexes());
+
+ for (size_t i = 0; i < parameterNames.size(); ++i) {
+ DomItem currentParameter = parameters.index(i);
+ QCOMPARE(currentParameter.field(Fields::name).value().toString(),
+ parameterNames[i]);
+
+ DomItem scriptElement =
+ currentParameter.field(Fields::value).field(Fields::scriptElement);
+ QCOMPARE(scriptElement.internalKind(), DomType::ScriptFormalParameter);
+ QCOMPARE(scriptElement.field(Fields::identifier).value().toString(),
+ parameterNames[i]);
+ if (!parameterWithoutDefault.contains(parameterNames[i])) {
+ QCOMPARE((size_t)scriptElement.field(Fields::initializer).value().toInteger(),
+ i + 1);
+ }
+ }
+ }
+
+ {
+ // note: no need to check the inside of ScriptObject and ScriptArray as those are
+ // already tested in deconstruction().
+ DomItem method = rootQmlObject.field(Fields::methods).key(u"evil"_s).index(0);
+ QVERIFY(!method.semanticScope().isNull());
+ QVERIFY(method.semanticScope()->ownJSIdentifier("helloEvil").has_value());
+ DomItem parameters = method.field(Fields::parameters);
+ QCOMPARE(parameters.indexes(), 3);
+
+ {
+ DomItem parameter1 =
+ parameters.index(0).field(Fields::value).field(Fields::scriptElement);
+ QCOMPARE(parameter1.internalKind(), DomType::ScriptFormalParameter);
+
+ DomItem objectPattern = parameter1.field(Fields::bindingElement);
+ QCOMPARE(objectPattern.internalKind(), DomType::ScriptObject);
+ QCOMPARE(objectPattern.field(Fields::properties).indexes(), 2);
+ }
+ {
+ DomItem parameter2 =
+ parameters.index(1).field(Fields::value).field(Fields::scriptElement);
+ QCOMPARE(parameter2.internalKind(), DomType::ScriptFormalParameter);
+
+ DomItem objectPattern = parameter2.field(Fields::bindingElement);
+ QCOMPARE(objectPattern.internalKind(), DomType::ScriptArray);
+ QCOMPARE(objectPattern.field(Fields::elements).indexes(), 3);
+ }
+ {
+ DomItem parameter3 =
+ parameters.index(2).field(Fields::value).field(Fields::scriptElement);
+ QCOMPARE(parameter3.internalKind(), DomType::ScriptFormalParameter);
+
+ DomItem objectPattern = parameter3.field(Fields::bindingElement);
+ QCOMPARE(objectPattern.internalKind(), DomType::ScriptObject);
+ QCOMPARE(objectPattern.field(Fields::properties).indexes(), 3);
+
+ DomItem parameter3DefaultValue = parameter3.field(Fields::initializer);
+ QCOMPARE(parameter3DefaultValue.internalKind(), DomType::ScriptObject);
+
+ DomItem objectPatternDefaultValue =
+ parameter3DefaultValue.field(Fields::properties);
+ QCOMPARE(objectPatternDefaultValue.indexes(), 3);
+ }
+ }
+ {
+ DomItem method = rootQmlObject.field(Fields::methods).key(u"marmelade"_s).index(0);
+ QVERIFY(!method.semanticScope().isNull());
+ QVERIFY(method.semanticScope()->ownJSIdentifier(u"helloMarmelade"_s));
+ DomItem parameters = method.field(Fields::parameters);
+ QCOMPARE(parameters.indexes(), 1);
+ {
+ DomItem parameter1 =
+ parameters.index(0).field(Fields::value).field(Fields::scriptElement);
+ QCOMPARE(parameter1.internalKind(), DomType::ScriptFormalParameter);
+ QCOMPARE(parameter1.field(Fields::identifier).value().toString(), "onTheBread");
+ }
+ }
+ {
+ DomItem method = rootQmlObject.field(Fields::methods).key(u"marmelade2"_s).index(0);
+ QVERIFY(!method.semanticScope().isNull());
+ QVERIFY(method.semanticScope()->ownJSIdentifier(u"helloMarmelade2"_s));
+ DomItem parameters = method.field(Fields::parameters);
+ QCOMPARE(parameters.indexes(), 3);
+ {
+ DomItem parameter3 =
+ parameters.index(2).field(Fields::value).field(Fields::scriptElement);
+ QCOMPARE(parameter3.internalKind(), DomType::ScriptFormalParameter);
+ QCOMPARE(parameter3.field(Fields::identifier).value().toString(), "onTheBread");
+ }
+ }
+ {
+ DomItem method = rootQmlObject.field(Fields::methods).key(u"withTypes"_s).index(0);
+ QVERIFY(!method.semanticScope().isNull());
+ QCOMPARE(method.semanticScope()->scopeType(),
+ QQmlJSScope::ScopeType::JSFunctionScope);
+ DomItem parameters = method.field(Fields::parameters);
+ QCOMPARE(parameters.indexes(), 2);
+ QCOMPARE(parameters.index(0)
+ .field(Fields::value)
+ .field(Fields::scriptElement)
+ .field(Fields::type)
+ .field(Fields::typeName)
+ .value()
+ .toString(),
+ "int");
+ QCOMPARE(parameters.index(1)
+ .field(Fields::value)
+ .field(Fields::scriptElement)
+ .field(Fields::type)
+ .field(Fields::typeName)
+ .value()
+ .toString(),
+ "MyType");
+ }
+ {
+ DomItem method = rootQmlObject.field(Fields::methods).key(u"empty"_s).index(0);
+ QVERIFY(!method.semanticScope().isNull());
+ QCOMPARE(method.semanticScope()->scopeType(),
+ QQmlJSScope::ScopeType::JSFunctionScope);
+ }
+ {
+ DomItem method = rootQmlObject.field(Fields::methods).key(u"mySignal"_s).index(0);
+ // signals contain the scope of the QML object owning them
+ QVERIFY(!method.semanticScope().isNull());
+ QCOMPARE(method.semanticScope()->scopeType(), QQmlJSScope::ScopeType::QMLScope);
+ }
+ }
+
+ void fieldMemberExpression()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/fieldMemberExpression.qml"_s;
+ DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+
+ {
+ DomItem p1 = rootQmlObject.path(".bindings[\"p1\"][0].value.scriptElement");
+ QCOMPARE(p1.internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(p1.field(Fields::identifier).value().toString(), "p");
+ }
+
+ {
+ DomItem p1Qualified =
+ rootQmlObject.path(".bindings[\"p1Qualified\"][0].value.scriptElement");
+ fieldMemberExpressionHelper(p1Qualified, QStringList{ u"p"_s });
+ QCOMPARE(p1Qualified.field(Fields::left).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(p1Qualified.field(Fields::left).field(Fields::identifier).value().toString(),
+ "root");
+ }
+ {
+ // property var p1Bracket: root["p"]
+ DomItem p1 = rootQmlObject.path(".bindings[\"p1Bracket\"][0].value.scriptElement");
+ QCOMPARE(p1.internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(p1.field(Fields::operation).value().toInteger(),
+ ScriptElements::BinaryExpression::ArrayMemberAccess);
+
+ QCOMPARE(p1.field(Fields::left).internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(p1.field(Fields::left).field(Fields::identifier).value().toString(), "root");
+
+ QCOMPARE(p1.field(Fields::right).internalKind(), DomType::ScriptLiteral);
+ QCOMPARE(p1.field(Fields::right).field(Fields::value).value().toString(), "p");
+ }
+ {
+ // property var p1Index: root[42]
+ DomItem p1 = rootQmlObject.path(".bindings[\"p1Index\"][0].value.scriptElement");
+ QCOMPARE(p1.internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(p1.field(Fields::operation).value().toInteger(),
+ ScriptElements::BinaryExpression::ArrayMemberAccess);
+
+ QCOMPARE(p1.field(Fields::left).internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(p1.field(Fields::left).field(Fields::identifier).value().toString(), "root");
+
+ QCOMPARE(p1.field(Fields::right).internalKind(), DomType::ScriptLiteral);
+ QCOMPARE(p1.field(Fields::right).field(Fields::value).value().toInteger(), 42);
+ }
+ {
+ // property var p1Key: root[p]
+ DomItem p1 = rootQmlObject.path(".bindings[\"p1Key\"][0].value.scriptElement");
+ QCOMPARE(p1.internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(p1.field(Fields::operation).value().toInteger(),
+ ScriptElements::BinaryExpression::ArrayMemberAccess);
+
+ QCOMPARE(p1.field(Fields::left).internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(p1.field(Fields::left).field(Fields::identifier).value().toString(), "root");
+
+ QCOMPARE(p1.field(Fields::right).internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(p1.field(Fields::right).field(Fields::identifier).value().toString(), "p");
+ }
+ {
+ DomItem p1Qualified =
+ rootQmlObject.path(".bindings[\"p1Qualified\"][0].value.scriptElement");
+ fieldMemberExpressionHelper(p1Qualified, QStringList{ u"p"_s });
+ QCOMPARE(p1Qualified.field(Fields::left).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(p1Qualified.field(Fields::left).field(Fields::identifier).value().toString(),
+ "root");
+ }
+
+ {
+ DomItem p3 = rootQmlObject.path(".bindings[\"p3\"][0].value.scriptElement");
+ fieldMemberExpressionHelper(p3, QStringList{ u"property2"_s, u"p"_s });
+ DomItem p3Left = p3.field(Fields::left).field(Fields::left);
+ QCOMPARE(p3Left.internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(p3Left.field(Fields::identifier).value().toString(), "property1");
+ }
+
+ {
+ DomItem p3Qualified =
+ rootQmlObject.path(".bindings[\"p3Qualified\"][0].value.scriptElement");
+ fieldMemberExpressionHelper(p3Qualified,
+ QStringList{ u"property1"_s, u"property2"_s, u"p"_s });
+ DomItem p3Left =
+ p3Qualified.field(Fields::left).field(Fields::left).field(Fields::left);
+ QCOMPARE(p3Left.internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(p3Left.field(Fields::identifier).value().toString(), "root");
+ }
+ }
+
+ void switchStatement()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/switchStatement.qml"_s;
+ DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ QVERIFY(rootQmlObject);
+
+ {
+ DomItem statements = rootQmlObject.methods()
+ .key(u"switchStatement")
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements);
+ QVERIFY(statements);
+ QCOMPARE(statements.index(0).internalKind(), DomType::ScriptVariableDeclaration);
+ QCOMPARE(statements.index(1).internalKind(), DomType::ScriptVariableDeclaration);
+
+ DomItem firstSwitch = statements.index(2);
+ QVERIFY(firstSwitch);
+ QCOMPARE(firstSwitch.internalKind(), DomType::ScriptSwitchStatement);
+ QCOMPARE(firstSwitch.field(Fields::caseBlock).internalKind(), DomType::ScriptCaseBlock);
+ QCOMPARE(firstSwitch.field(Fields::expression).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(firstSwitch.field(Fields::expression)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"animals");
+
+ DomItem caseClauses = firstSwitch.field(Fields::caseBlock).field(Fields::caseClauses);
+ QVERIFY(caseClauses);
+ QCOMPARE(caseClauses.index(0).internalKind(), DomType::ScriptCaseClause);
+ QCOMPARE(caseClauses.index(0).field(Fields::expression).internalKind(),
+ DomType::ScriptLiteral);
+ QCOMPARE(caseClauses.index(0).field(Fields::expression).value().toString(), u"cat");
+
+ DomItem innerSwitch = caseClauses.index(0).field(Fields::statements).index(0);
+ QVERIFY(innerSwitch);
+ QCOMPARE(innerSwitch.internalKind(), DomType::ScriptSwitchStatement);
+ QCOMPARE(innerSwitch.field(Fields::expression).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(innerSwitch.field(Fields::expression).value().toString(), u"no");
+
+ QCOMPARE(innerSwitch.field(Fields::caseBlock)
+ .field(Fields::caseClauses)
+ .index(0)
+ .internalKind(),
+ DomType::ScriptCaseClause);
+ QCOMPARE(innerSwitch.field(Fields::caseBlock)
+ .field(Fields::caseClauses)
+ .index(0)
+ .field(Fields::expression)
+ .internalKind(),
+ DomType::ScriptLiteral);
+ QCOMPARE(innerSwitch.field(Fields::caseBlock)
+ .field(Fields::caseClauses)
+ .index(0)
+ .field(Fields::expression)
+ .value()
+ .toInteger(),
+ 0);
+ QCOMPARE(innerSwitch.field(Fields::caseBlock)
+ .field(Fields::caseClauses)
+ .index(0)
+ .field(Fields::statements)
+ .index(0)
+ .field(Fields::expression)
+ .value()
+ .toString(),
+ u"patron");
+ QCOMPARE(innerSwitch.field(Fields::caseBlock)
+ .field(Fields::caseClauses)
+ .index(1)
+ .internalKind(),
+ DomType::ScriptCaseClause);
+ QCOMPARE(innerSwitch.field(Fields::caseBlock)
+ .field(Fields::caseClauses)
+ .index(1)
+ .field(Fields::statements)
+ .index(0)
+ .field(Fields::expression)
+ .value()
+ .toString(),
+ u"mafik");
+ QCOMPARE(innerSwitch.field(Fields::caseBlock)
+ .field(Fields::defaultClause)
+ .internalKind(),
+ DomType::ScriptDefaultClause);
+ QCOMPARE(innerSwitch.field(Fields::caseBlock)
+ .field(Fields::defaultClause)
+ .field(Fields::statements)
+ .index(0)
+ .field(Fields::expression)
+ .value()
+ .toString(),
+ u"none");
+
+ // case "dog"
+ DomItem caseDogBlock = firstSwitch.field(Fields::caseBlock)
+ .field(Fields::caseClauses)
+ .index(1)
+ .field(Fields::statements)
+ .index(0);
+ QVERIFY(caseDogBlock);
+ // Check if semantic scope is correctly created for the CaseClause
+ auto blockSemanticScope = caseDogBlock.semanticScope();
+ QVERIFY(blockSemanticScope);
+ QVERIFY(blockSemanticScope->ownJSIdentifier(u"name"_s));
+ QVERIFY(blockSemanticScope->ownJSIdentifier(u"another"_s));
+
+ // Default clause
+ DomItem defaultClause =
+ firstSwitch.field(Fields::caseBlock).field(Fields::defaultClause);
+ QVERIFY(defaultClause);
+ QCOMPARE(defaultClause.internalKind(), DomType::ScriptDefaultClause);
+ QCOMPARE(defaultClause.field(Fields::statements).index(0).internalKind(),
+ DomType::ScriptReturnStatement);
+ QCOMPARE(defaultClause.field(Fields::statements)
+ .index(0)
+ .field(Fields::expression)
+ .internalKind(),
+ DomType::ScriptLiteral);
+ QCOMPARE(defaultClause.field(Fields::statements)
+ .index(0)
+ .field(Fields::expression)
+ .value()
+ .toString(),
+ u"monster");
+
+ // case "moreCases!"
+ const DomItem moreCases = firstSwitch.field(Fields::caseBlock)
+ .field(Fields::moreCaseClauses)
+ .index(0)
+ .field(Fields::statements)
+ .index(0);
+
+ QCOMPARE(moreCases.internalKind(),
+ DomType::ScriptReturnStatement);
+ QCOMPARE(moreCases.field(Fields::expression).value().toString(), u"moreCaseClauses?");
+ }
+ }
+
+ void iterationStatements()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/iterationStatements.qml"_s;
+ DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+
+ QVERIFY(rootQmlObject);
+ DomItem methods = rootQmlObject.methods();
+ QVERIFY(methods);
+
+ {
+ // while statement
+ DomItem whileTest = methods.key("whileStatement")
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements)
+ .index(1);
+ QVERIFY(whileTest);
+ QCOMPARE(whileTest.internalKind(), DomType::ScriptWhileStatement);
+ auto whileScope = whileTest.semanticScope();
+ QVERIFY(whileScope);
+ DomItem whileBody = whileTest.field(Fields::body);
+ QVERIFY(whileBody);
+ QCOMPARE(whileBody.internalKind(), DomType::ScriptBlockStatement);
+ auto scope = whileBody.semanticScope();
+ QVERIFY(scope);
+ QCOMPARE(whileBody.field(Fields::statements).index(0).internalKind(),
+ DomType::ScriptBinaryExpression); // i = i - 1
+ QCOMPARE(
+ whileBody.field(Fields::statements).index(0).field(Fields::left).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(whileBody.field(Fields::statements)
+ .index(0)
+ .field(Fields::left)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"i");
+ DomItem whileExpression = whileTest.field(Fields::expression);
+ QVERIFY(whileExpression);
+ QCOMPARE(whileExpression.internalKind(), DomType::ScriptBinaryExpression); // i > 0
+ QCOMPARE(whileExpression.field(Fields::left).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(whileExpression.field(Fields::left)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"i");
+ QCOMPARE(whileExpression.field(Fields::right).internalKind(), DomType::ScriptLiteral);
+ QCOMPARE(whileExpression.field(Fields::right)
+ .field(Fields::identifier)
+ .value()
+ .toInteger(),
+ 0);
+
+ DomItem singleLineWhile = methods.key("whileStatement")
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements)
+ .index(2);
+ QVERIFY(singleLineWhile);
+ QCOMPARE(singleLineWhile.internalKind(), DomType::ScriptWhileStatement);
+ DomItem singleLineWhileBody = singleLineWhile.field(Fields::body);
+ QVERIFY(singleLineWhileBody);
+ QCOMPARE(singleLineWhileBody.internalKind(), DomType::ScriptBinaryExpression);
+ auto singleLineWhileScope = singleLineWhile.semanticScope();
+ QVERIFY(singleLineWhileScope);
+ QVERIFY(singleLineWhileScope->jsIdentifier("i")); // i is in the parent scope
+ }
+
+ {
+ // do-while statement
+ DomItem doWhile = methods.key("doWhile")
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements)
+ .index(1);
+ QVERIFY(doWhile);
+ QCOMPARE(doWhile.internalKind(), DomType::ScriptDoWhileStatement);
+
+ auto doWhileScope = doWhile.semanticScope();
+ QVERIFY(doWhileScope);
+ DomItem doWhileBody = doWhile.field(Fields::body);
+ QVERIFY(doWhileBody);
+ auto doWhileBodyScope = doWhileBody.semanticScope();
+ QVERIFY(doWhileBodyScope);
+ QVERIFY(doWhileBodyScope->ownJSIdentifier("b")); // const b = a
+ QCOMPARE(doWhileBody.internalKind(), DomType::ScriptBlockStatement);
+ QCOMPARE(doWhileBody.field(Fields::statements).index(0).internalKind(),
+ DomType::ScriptVariableDeclaration); // const b = a
+ QCOMPARE(doWhileBody.field(Fields::statements).index(1).internalKind(),
+ DomType::ScriptBinaryExpression); // a = a - 1
+
+ DomItem doWhileExpression = doWhile.field(Fields::expression);
+ QVERIFY(doWhileExpression);
+ QCOMPARE(doWhileExpression.internalKind(), DomType::ScriptBinaryExpression); // a > 0
+ QCOMPARE(doWhileExpression.field(Fields::left).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(doWhileExpression.field(Fields::left)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"a");
+ QCOMPARE(doWhileExpression.field(Fields::right).internalKind(), DomType::ScriptLiteral);
+ QCOMPARE(doWhileExpression.field(Fields::right)
+ .field(Fields::identifier)
+ .value()
+ .toInteger(),
+ 0);
+ DomItem singleDoWhile = methods.key("doWhile")
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements)
+ .index(2);
+ auto singleDoWhileScope = singleDoWhile.semanticScope();
+ QVERIFY(singleDoWhileScope);
+ QVERIFY(singleDoWhileScope->jsIdentifier("a")); // a = a - 1
+ }
+
+ {
+ // for..of
+ DomItem statements = methods.key("forOf")
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements);
+ QVERIFY(statements);
+ QCOMPARE(statements.index(0).internalKind(), DomType::ScriptVariableDeclaration);
+ DomItem outerForEach = statements.index(1);
+ QVERIFY(outerForEach);
+ QCOMPARE(outerForEach.internalKind(), DomType::ScriptForEachStatement);
+ DomItem bindingElements =
+ outerForEach.field(Fields::bindingElement).field(Fields::bindingElement);
+ QVERIFY(bindingElements);
+ QCOMPARE(bindingElements.internalKind(), DomType::ScriptArray);
+ QCOMPARE(bindingElements.field(Fields::elements).length(), 2);
+ QCOMPARE(bindingElements.field(Fields::elements)
+ .index(1)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ "b");
+ QCOMPARE(outerForEach.field(Fields::expression).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(outerForEach.field(Fields::expression)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"iterable");
+ DomItem forEachStatements = outerForEach.field(Fields::body).field(Fields::statements);
+ QCOMPARE(forEachStatements.index(0).internalKind(), DomType::ScriptVariableDeclaration);
+ QCOMPARE(forEachStatements.index(1).internalKind(), DomType::ScriptForEachStatement);
+ QCOMPARE(forEachStatements.index(2).internalKind(), DomType::ScriptForEachStatement);
+ QCOMPARE(forEachStatements.index(3).internalKind(), DomType::ScriptForEachStatement);
+ DomItem firstForEach = forEachStatements.index(1);
+ QVERIFY(firstForEach);
+ DomItem bindingElement =
+ firstForEach.field(Fields::bindingElement).field(Fields::bindingElement);
+ QCOMPARE(bindingElement.internalKind(), DomType::ScriptArray);
+
+ QCOMPARE(bindingElement.field(Fields::elements).length(), 4);
+ QCOMPARE(bindingElement.field(Fields::elements)
+ .index(0)
+ .field(Fields::identifier)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ "a1");
+ DomItem secondForEach = forEachStatements.index(2);
+ QCOMPARE(secondForEach.field(Fields::bindingElement).internalKind(),
+ DomType::ScriptPattern);
+ QCOMPARE(secondForEach.field(Fields::bindingElement)
+ .field(Fields::identifier)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ "k");
+ QCOMPARE(secondForEach.internalKind(), DomType::ScriptForEachStatement);
+ QCOMPARE(secondForEach.field(Fields::expression).internalKind(), DomType::ScriptArray);
+ QVERIFY(secondForEach.field(Fields::body));
+ QCOMPARE(secondForEach.field(Fields::body).internalKind(),
+ DomType::ScriptBlockStatement);
+ DomItem thirdForEach = forEachStatements.index(3);
+ QCOMPARE(thirdForEach.field(Fields::bindingElement).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(thirdForEach.field(Fields::bindingElement).value().toString(), "t");
+
+ QCOMPARE(thirdForEach.internalKind(), DomType::ScriptForEachStatement);
+ QCOMPARE(thirdForEach.field(Fields::expression).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(thirdForEach.field(Fields::expression)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"a");
+ QVERIFY(thirdForEach.field(Fields::body));
+ QCOMPARE(thirdForEach.field(Fields::body).internalKind(),
+ DomType::ScriptBlockStatement);
+
+ DomItem forthForEach = forEachStatements.index(3);
+ QVERIFY(forthForEach);
+ auto forthForEachScope = forthForEach.semanticScope();
+ QVERIFY(forthForEachScope);
+ QVERIFY(forthForEachScope->jsIdentifier("t")); // t lives in parent scope
+ }
+
+ {
+ // for..in
+ DomItem statements = methods.key("forIn")
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements);
+ QVERIFY(statements);
+ QCOMPARE(statements.index(0).internalKind(), DomType::ScriptVariableDeclaration);
+ DomItem outerForEach = statements.index(1);
+ QVERIFY(outerForEach);
+ auto outerForEachScope = outerForEach.semanticScope();
+ QVERIFY(outerForEachScope);
+ QVERIFY(outerForEachScope->jsIdentifier("a")); // var [a,b,c,d]
+ QVERIFY(outerForEachScope->jsIdentifier("b"));
+ QVERIFY(outerForEachScope->jsIdentifier("c"));
+ QVERIFY(outerForEachScope->jsIdentifier("d"));
+ QCOMPARE(outerForEach.internalKind(), DomType::ScriptForEachStatement);
+ QCOMPARE(statements.index(1).internalKind(), DomType::ScriptForEachStatement);
+ QCOMPARE(outerForEach.field(Fields::expression)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ "enumerable");
+ auto outerForEachBodyScope = outerForEach.field(Fields::body).semanticScope();
+ QVERIFY(outerForEachBodyScope);
+ QVERIFY(outerForEachBodyScope->ownJSIdentifier("t")); // let t
+ DomItem forInStatements = outerForEach.field(Fields::body).field(Fields::statements);
+ QCOMPARE(forInStatements.index(0).internalKind(), DomType::ScriptVariableDeclaration);
+ QCOMPARE(forInStatements.index(1).internalKind(), DomType::ScriptForEachStatement);
+ QCOMPARE(forInStatements.index(2).internalKind(), DomType::ScriptForEachStatement);
+ DomItem firstForEach = forInStatements.index(1);
+ QVERIFY(firstForEach);
+ auto firstForEachScope = firstForEach.semanticScope();
+ QVERIFY(firstForEachScope);
+ QVERIFY(firstForEachScope->jsIdentifier("t"));
+ QCOMPARE(firstForEach.field(Fields::bindingElement).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(firstForEach.field(Fields::bindingElement)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ "t");
+ QCOMPARE(firstForEach.internalKind(), DomType::ScriptForEachStatement);
+ QCOMPARE(firstForEach.field(Fields::expression).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(firstForEach.field(Fields::expression)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ "enumerable");
+ QVERIFY(firstForEach.field(Fields::body));
+ QCOMPARE(firstForEach.field(Fields::body).internalKind(),
+ DomType::ScriptBlockStatement);
+
+ DomItem secondForEach = forInStatements.index(2);
+ QVERIFY(secondForEach);
+ auto secondForEachScope = secondForEach.semanticScope();
+ QVERIFY(secondForEachScope);
+ QVERIFY(secondForEachScope->ownJSIdentifier("a1")); // const [a1,,a2,...rest]
+ QVERIFY(secondForEachScope->ownJSIdentifier("a2"));
+ QVERIFY(secondForEachScope->ownJSIdentifier("rest"));
+
+ DomItem bindingElement =
+ secondForEach.field(Fields::bindingElement).field(Fields::bindingElement);
+ QCOMPARE(bindingElement.internalKind(), DomType::ScriptArray);
+ QCOMPARE(bindingElement.field(Fields::elements)
+ .index(3)
+ .field(Fields::identifier)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ "rest");
+ QCOMPARE(secondForEach.internalKind(), DomType::ScriptForEachStatement);
+ QCOMPARE(secondForEach.field(Fields::expression).internalKind(),
+ DomType::ScriptBinaryExpression);
+ QVERIFY(secondForEach.field(Fields::body));
+ QCOMPARE(secondForEach.field(Fields::body).internalKind(),
+ DomType::ScriptBlockStatement);
+ DomItem thirdForEach = forInStatements.index(3);
+ QVERIFY(thirdForEach);
+ auto thirdForEachScope = thirdForEach.semanticScope();
+ QVERIFY(thirdForEachScope);
+ QVERIFY(thirdForEachScope->ownJSIdentifier("t"));
+ }
+ }
+
+ void doNotCrashEcmaScriptClass()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/ecmaScriptClass.qml"_s;
+ DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ QVERIFY(rootQmlObject);
+ }
+
+ void bindingAttachedOrGroupedProperties()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/attachedOrGroupedProperties.qml"_s;
+ DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ QVERIFY(rootQmlObject);
+
+ DomItem dotNotation = rootQmlObject.path(u".children[0].bindings[\"grouped.font.family\"][0].bindingIdentifiers");
+ QVERIFY(dotNotation);
+ QCOMPARE(dotNotation.internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(dotNotation.field(Fields::left).internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(dotNotation.field(Fields::right).field(Fields::identifier).value().toString(), u"family");
+ QCOMPARE(dotNotation.field(Fields::right).internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(dotNotation.field(Fields::left).field(Fields::left).internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(dotNotation.field(Fields::left).field(Fields::left).field(Fields::identifier).value().toString(), u"grouped");
+ QCOMPARE(dotNotation.field(Fields::left).field(Fields::right).internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(dotNotation.field(Fields::left).field(Fields::right).field(Fields::identifier).value().toString(), u"font");
+ auto dotNotationScope = dotNotation.semanticScope();
+ QVERIFY(!dotNotationScope);
+
+ DomItem groupNotationChild1 = rootQmlObject.path(u".children[1].children[0]");
+ QVERIFY(groupNotationChild1);
+ QCOMPARE(groupNotationChild1.internalKind(), DomType::QmlObject);
+ QCOMPARE(groupNotationChild1.field(Fields::name).value().toString(), u"myText");
+ auto myTextScope = groupNotationChild1.semanticScope();
+ QVERIFY(myTextScope);
+ QCOMPARE(myTextScope->scopeType(), QQmlJSScope::ScopeType::GroupedPropertyScope);
+ QVERIFY(myTextScope->hasProperty("font"));
+
+ DomItem groupNotationChild2 = groupNotationChild1.path(u".children[0]");
+ QCOMPARE(groupNotationChild2.internalKind(), DomType::QmlObject);
+ QCOMPARE(groupNotationChild2.field(Fields::name).value().toString(), u"font");
+
+ auto fontScope = groupNotationChild2.semanticScope();
+ QVERIFY(fontScope);
+ QCOMPARE(fontScope->scopeType(), QQmlJSScope::ScopeType::GroupedPropertyScope);
+ QVERIFY(fontScope->hasProperty("pixelSize"));
+
+ DomItem pixelSize = groupNotationChild2.path(u".bindings[\"pixelSize\"][0].bindingIdentifiers");
+ QCOMPARE(pixelSize.internalKind(), DomType::ScriptIdentifierExpression);
+ QCOMPARE(pixelSize.field(Fields::identifier).value().toString(), u"pixelSize");
+
+ DomItem attached = rootQmlObject.path(u".bindings[\"Keys.onPressed\"][0].bindingIdentifiers");
+ QVERIFY(attached);
+ QCOMPARE(attached.internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(attached.field(Fields::left).field(Fields::identifier).value().toString(), u"Keys");
+ QCOMPARE(attached.field(Fields::right).field(Fields::identifier).value().toString(), u"onPressed");
+ }
+
+ void enumDeclarations()
+ {
+ using namespace Qt::StringLiterals;
+ QString testFile = baseDir + u"/enumDeclarations.qml"_s;
+ DomItem fileObject = rootQmlObjectFromFile(testFile, qmltypeDirs).fileObject();
+ QVERIFY(fileObject);
+ DomItem enums = fileObject.path(u".components[\"\"][0].enumerations");
+ QVERIFY(enums);
+
+ DomItem catsEnum = enums.key("Cats").index(0);
+ QVERIFY(catsEnum);
+ QCOMPARE(catsEnum.internalKind(), DomType::EnumDecl);
+ QCOMPARE(catsEnum.name(), u"Cats");
+
+ auto values = catsEnum.field(Fields::values);
+ QCOMPARE(values.length(), 3);
+ QCOMPARE(values.index(0).internalKind(), DomType::EnumItem);
+ QCOMPARE(values.index(0).name(), u"Patron");
+ QCOMPARE(values.index(0).field(Fields::value).value().toInteger(), 0);
+ QCOMPARE(values.index(1).internalKind(), DomType::EnumItem);
+ QCOMPARE(values.index(1).name(), u"Mafya");
+ QCOMPARE(values.index(1).field(Fields::value).value().toInteger(), 1);
+ QCOMPARE(values.index(2).internalKind(), DomType::EnumItem);
+ QCOMPARE(values.index(2).name(), u"Kivrik");
+ QCOMPARE(values.index(2).field(Fields::value).value().toInteger(), -1);
+ }
+
+ void tryStatements()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/tryStatements.qml"_s;
+ const DomItem root = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ QVERIFY(root);
+ const DomItem statements = root.path(u".methods[\"f\"][0].body.scriptElement.statements");
+ QCOMPARE(statements.indexes(), 3);
+
+ // test the try blocks
+ for (int i = 0; i < 3; ++i) {
+ const DomItem statement = statements.index(i).field(Fields::block);
+ QVERIFY(statement);
+ QCOMPARE(statement.internalKind(), DomType::ScriptBlockStatement);
+ QCOMPARE(statement.field(Fields::statements)
+ .index(0)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"insideTry"_s);
+ }
+
+ // test the catch blocks
+ for (int i = 0; i < 3; ++i) {
+ const DomItem statement = statements.index(i).field(Fields::catchBlock);
+ if (i == 2) {
+ QVERIFY(!statement); // no catch in last statement
+ continue;
+ }
+
+ QVERIFY(statement);
+ QCOMPARE(statement.internalKind(), DomType::ScriptBlockStatement);
+ QCOMPARE(statement.field(Fields::statements)
+ .index(0)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"insideCatch"_s);
+
+ const DomItem expression = statements.index(i).field(Fields::catchParameter);
+ QVERIFY(expression);
+ QCOMPARE(expression.field(Fields::identifier)
+ .value()
+ .toString(),
+ u"catchExpression"_s);
+ }
+
+ // test the finally blocks
+ for (int i = 0; i < 3; ++i) {
+ const DomItem statement = statements.index(i).field(Fields::finallyBlock);
+ if (i == 1) {
+ QVERIFY(!statement); // no finally in last statement
+ continue;
+ }
+
+ QVERIFY(statement);
+ QCOMPARE(statement.internalKind(), DomType::ScriptBlockStatement);
+ QCOMPARE(statement.field(Fields::statements)
+ .index(0)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"insideFinally"_s);
+ }
+ }
+
+ void plainJSDOM_data()
+ {
+ QTest::addColumn<QString>("filename");
+ QTest::addColumn<QString>("content");
+
+ QTest::newRow("simplestJSStatement")
+ << "simplestJSStatement.js" << QString(u"let v=1;\n"_s);
+ QTest::newRow("import")
+ << "import.js"
+ << QString(u".import \"main.js\" as Main\nconsole.log(Main.a);\n"_s);
+ QTest::newRow("simplestJSmodule")
+ << "simplestJSmodule.mjs" << QString(u"export function entry() {}\n"_s);
+ }
+
+ // Verifies that DOM can load .js and .mjs files and
+ // parse / store the content inside the ScriptExpression
+ void plainJSDOM()
+ {
+ using namespace Qt::StringLiterals;
+ QFETCH(QString, filename);
+ QFETCH(QString, content);
+
+ QString testFile = baseDir + "/" + filename;
+ auto dom = parse(testFile, qmltypeDirs);
+ QVERIFY(dom);
+ QCOMPARE(dom.internalKind(), DomType::JsFile);
+ auto filePtr = dom.fileObject().ownerAs<JsFile>();
+ QVERIFY(filePtr && filePtr->isValid());
+ auto exprAsString = dom.field(Fields::expression)
+ .field(Fields::code)
+ .value()
+ .toString();
+ QVERIFY(!exprAsString.isEmpty());
+ exprAsString.replace("\r\n", "\n");
+ QCOMPARE(exprAsString, content);
+ }
+
+private:
+ struct DomItemWithLocation
+ {
+ DomItem item;
+ FileLocations::Tree tree;
+ };
+private slots:
+
+ void fileLocations_data()
+ {
+ QTest::addColumn<QString>("fileName");
+ QDir dir(baseDir);
+ for (const QString &file : dir.entryList(QDir::Files, QDir::Name)) {
+ if (!file.endsWith(".qml"))
+ continue;
+ QTest::addRow("%s", file.toStdString().c_str()) << baseDir + QDir::separator() + file;
+ }
+ }
+
+ /*!
+ \internal
+ Check if finalizeScriptExpression() was called with the correct FileLocations::Tree
+ argument when this test fails.
+ */
+ void fileLocations()
+ {
+ QFETCH(QString, fileName);
+
+ DomItem rootQmlObject = rootQmlObjectFromFile(fileName, qmltypeDirs);
+ std::deque<DomItemWithLocation> queue;
+
+ DomItem fileDomItem = rootQmlObject.containingFile();
+ std::shared_ptr<QmlFile> file = fileDomItem.ownerAs<QmlFile>();
+ QVERIFY(file);
+
+ DomItemWithLocation root{ fileDomItem, file->fileLocationsTree() };
+ queue.push_back(root);
+
+ while (!queue.empty()) {
+ DomItemWithLocation current = queue.front();
+ queue.pop_front();
+
+ auto subEls = current.tree->subItems();
+ for (auto it = subEls.begin(); it != subEls.end(); ++it) {
+ DomItem childItem = current.item.path(it.key());
+ FileLocations::Tree childTree =
+ std::static_pointer_cast<AttachedInfoT<FileLocations>>(it.value());
+ if (!childItem) {
+ const auto attachedInfo = FileLocations::findAttachedInfo(current.item);
+ const DomItem treeItem = current.item.path(attachedInfo.foundTreePath);
+ qDebug() << current.item.internalKindStr()
+ << "has incorrect FileLocations! Make sure that "
+ "finalizeScriptExpression is called with the right arguments. It "
+ "should print out some debugging information with the "
+ "qt.qmldom.astcreator.debug logging rule.";
+ qDebug() << "Current FileLocations has keys:"
+ << treeItem.field(Fields::subItems).keys()
+ << "but current Item of type" << current.item.internalKindStr()
+ << "has fields: " << current.item.fields()
+ << "and keys: " << current.item.keys()
+ << "and indexes: " << current.item.indexes();
+ }
+ QVERIFY(childItem.internalKind() != DomType::Empty);
+ queue.push_back({ childItem, childTree });
+ }
+ }
+ }
+
+private slots:
+ void finalizeScriptExpressions()
+ {
+ QString fileName = baseDir + u"/finalizeScriptExpressions.qml"_s;
+ DomItem rootQmlObject = rootQmlObjectFromFile(fileName, qmltypeDirs);
+
+ /*
+ Check if the path obtained by the filelocations is the same as the DomItem path. Both
+ need to be equal to find DomItem's from their location in the source code.
+ */
+ auto compareFileLocationsPathWithCanonicalPath = [](const DomItem &item) {
+ Path canonical = item.canonicalPath();
+ QVERIFY(canonical.length() > 0);
+ if (canonical.length() > 0)
+ QCOMPARE(canonical.toString(),
+ FileLocations::treeOf(item)->canonicalPathForTesting());
+ };
+
+ /*
+ for all places, where scriptelements are attached to Qml elements in the Dom, check if:
+ a) scriptelement is accessible from the DomItem (is it correclty attached?)
+ b) scriptelement has the correct path (is its pathFromOwner the path where it was
+ attached?)
+
+ For bindings to objects, arrays and scripts, check that the bindingIdentifiers are correctly
+ attached in the Dom.
+ */
+
+ {
+ DomItem binding = rootQmlObject.field(Fields::bindings).key("binding");
+ QCOMPARE(binding.indexes(), 1);
+
+ QCOMPARE(binding.index(0).field(Fields::value).internalKind(),
+ DomType::ScriptExpression);
+ QCOMPARE(binding.index(0)
+ .field(Fields::value)
+ .field(Fields::scriptElement)
+ .internalKind(),
+ DomType::ScriptLiteral);
+ // Fields::value is in the path of the owner, and therefore should not be in
+ // pathFromOwner!
+ DomItem scriptElement =
+ binding.index(0).field(Fields::value).field(Fields::scriptElement);
+ QCOMPARE(scriptElement.pathFromOwner(), Path().field(Fields::scriptElement));
+ compareFileLocationsPathWithCanonicalPath(scriptElement);
+ }
+
+ {
+ DomItem bindingInPropertyDefinition =
+ rootQmlObject.field(Fields::bindings).key("bindingInPropertyDefinition");
+ QCOMPARE(bindingInPropertyDefinition.indexes(), 1);
+
+ QCOMPARE(bindingInPropertyDefinition.index(0).field(Fields::value).internalKind(),
+ DomType::ScriptExpression);
+ QCOMPARE(bindingInPropertyDefinition.index(0)
+ .field(Fields::value)
+ .field(Fields::scriptElement)
+ .internalKind(),
+ DomType::ScriptLiteral);
+ // Fields::value is in the path of the owner, and therefore should not be in
+ // pathFromOwner!
+ DomItem scriptElement = bindingInPropertyDefinition.index(0)
+ .field(Fields::value)
+ .field(Fields::scriptElement);
+ QCOMPARE(scriptElement.pathFromOwner(), Path().field(Fields::scriptElement));
+ compareFileLocationsPathWithCanonicalPath(scriptElement);
+ }
+ // check the parameters + returnType of the method
+ {
+ DomItem return42 = rootQmlObject.field(Fields::methods).key("return42");
+ QCOMPARE(return42.indexes(), 1);
+
+ DomItem typeAnnotation =
+ return42.index(0).field(Fields::returnType).field(Fields::scriptElement);
+ QCOMPARE(typeAnnotation.internalKind(), DomType::ScriptType);
+ compareFileLocationsPathWithCanonicalPath(typeAnnotation);
+
+ DomItem parameters = return42.index(0).field(Fields::parameters);
+ QCOMPARE(parameters.indexes(), 3);
+ for (int i = 0; i < 3; ++i) {
+ QCOMPARE(parameters.index(i).field(Fields::defaultValue).internalKind(),
+ DomType::ScriptExpression);
+ DomItem scriptElement =
+ parameters.index(i).field(Fields::value).field(Fields::scriptElement);
+ QCOMPARE(scriptElement.internalKind(), DomType::ScriptFormalParameter);
+ QCOMPARE(scriptElement.pathFromOwner(), Path().field(Fields::scriptElement));
+ compareFileLocationsPathWithCanonicalPath(scriptElement);
+ }
+ }
+ // check the body of the methods
+ QList<QString> methodNames = { "full", "return42" };
+ for (QString &methodName : methodNames) {
+ DomItem method = rootQmlObject.field(Fields::methods).key(methodName);
+ DomItem body = method.index(0).field(Fields::body);
+ QCOMPARE(body.internalKind(), DomType::ScriptExpression);
+ DomItem scriptElement = body.field(Fields::scriptElement);
+ QCOMPARE(scriptElement.internalKind(), DomType::ScriptBlockStatement);
+ QCOMPARE(scriptElement.pathFromOwner(), Path().field(Fields::scriptElement));
+ compareFileLocationsPathWithCanonicalPath(scriptElement);
+ }
+
+ {
+ DomItem binding = rootQmlObject.field(Fields::bindings).key("arrayBinding");
+ QCOMPARE(binding.indexes(), 1);
+ QCOMPARE(binding.index(0).field(Fields::value).internalKind(),
+ DomType::ScriptExpression);
+ QCOMPARE(binding.index(0)
+ .field(Fields::value)
+ .field(Fields::scriptElement)
+ .internalKind(),
+ DomType::ScriptArray);
+ // Fields::value is in the path of the owner, and therefore should not be in
+ // pathFromOwner!
+ DomItem scriptElement =
+ binding.index(0).field(Fields::value).field(Fields::scriptElement);
+ QCOMPARE(scriptElement.pathFromOwner(), Path().field(Fields::scriptElement));
+ compareFileLocationsPathWithCanonicalPath(scriptElement);
+ // also check that the left hand side of the binding is correctly attached to the Dom:
+ scriptElement = binding.index(0).field(Fields::bindingIdentifiers);
+ QCOMPARE(scriptElement.pathFromOwner(),
+ Path::fromString(u".components[\"\"][0].objects[0].bindings[\"arrayBinding\"]["
+ u"0].bindingIdentifiers"));
+ compareFileLocationsPathWithCanonicalPath(scriptElement);
+ }
+ {
+ DomItem binding = rootQmlObject.field(Fields::bindings).key("objectBinding");
+ QCOMPARE(binding.indexes(), 1);
+ QCOMPARE(binding.index(0).field(Fields::value).internalKind(), DomType::QmlObject);
+ // check that the left hand side of the binding is correctly attached to the Dom:
+ DomItem scriptElement = binding.index(0).field(Fields::bindingIdentifiers);
+ QCOMPARE(scriptElement.pathFromOwner(),
+ Path::fromString(u".components[\"\"][0].objects[0].bindings[\"objectBinding\"]["
+ u"0].bindingIdentifiers"));
+ compareFileLocationsPathWithCanonicalPath(scriptElement);
+ }
+ }
+
+ void goToFile()
+ {
+ using namespace Qt::StringLiterals;
+ const QString filePathA = baseDir + u"/nullStatements.qml"_s;
+ const QString filePathB = baseDir + u"/propertyBindings.qml"_s;
+ const QString canonicalFilePathB = QFileInfo(filePathB).canonicalFilePath();
+ QVERIFY(!canonicalFilePathB.isEmpty());
+
+ DomCreationOptions options;
+ options.setFlag(DomCreationOption::WithScriptExpressions);
+ options.setFlag(DomCreationOption::WithSemanticAnalysis);
+ auto envPtr = DomEnvironment::create(
+ qmltypeDirs,
+ QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
+ | QQmlJS::Dom::DomEnvironment::Option::NoDependencies,
+ options);
+
+ DomItem fileA;
+ DomItem fileB;
+
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, filePathA),
+ [&fileA](Path, const DomItem &, const DomItem &newIt) {
+ fileA = newIt.fileObject();
+ });
+
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, filePathB),
+ [&fileB](Path, const DomItem &, const DomItem &newIt) {
+ fileB = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
+
+ QCOMPARE(fileA.goToFile(canonicalFilePathB), fileB);
+ }
+
+ void goUp()
+ {
+ using namespace Qt::StringLiterals;
+ const QString filePath = baseDir + u"/nullStatements.qml"_s;
+ const QString canonicalFilePathB = QFileInfo(filePath).canonicalFilePath();
+ QVERIFY(!canonicalFilePathB.isEmpty());
+
+ DomCreationOptions options;
+ options.setFlag(DomCreationOption::WithScriptExpressions);
+ options.setFlag(DomCreationOption::WithSemanticAnalysis);
+ auto envPtr = DomEnvironment::create(
+ qmltypeDirs,
+ QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
+ | QQmlJS::Dom::DomEnvironment::Option::NoDependencies,
+ options);
+
+ DomItem fileA;
+ DomItem fileB;
+
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, filePath),
+ [&fileA](Path, const DomItem &, const DomItem &newIt) {
+ fileA = newIt.fileObject();
+ });
+
+ envPtr->loadPendingDependencies();
+
+ QCOMPARE(fileA.top().goUp(1), DomItem());
+ QCOMPARE(fileA.top().directParent(), DomItem());
+
+ DomItem component = fileA.field(Fields::components).key(QString()).index(0);
+
+ DomItem forStatement = component.field(Fields::objects)
+ .index(0)
+ .field(Fields::methods)
+ .key(u"testForNull"_s)
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements)
+ .index(0)
+ .field(Fields::body);
+
+ DomItem forStatementBlock = forStatement.field(Fields::statements);
+
+ QCOMPARE(forStatementBlock.directParent(), forStatement);
+ QCOMPARE(forStatementBlock.goUp(1), forStatement);
+ QCOMPARE(forStatementBlock.goUp(11), component);
+
+ QCOMPARE(forStatement.component(GoTo::Strict), component);
+ }
+
+private:
+ static DomItem parse(const QString &path, const QStringList &qmltypeDirs)
+ {
+ DomCreationOptions options;
+ options.setFlag(DomCreationOption::WithScriptExpressions);
+ options.setFlag(DomCreationOption::WithSemanticAnalysis);
+
+ auto envPtr = DomEnvironment::create(
+ qmltypeDirs,
+ QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
+ | QQmlJS::Dom::DomEnvironment::Option::NoDependencies,
+ options);
+
+ DomItem fileItem;
+
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, path),
+ [&fileItem](Path, const DomItem &, const DomItem &newIt) {
+ fileItem = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
+ return fileItem;
+ }
+
+ static DomItem rootQmlObjectFromFile(const QString &path, const QStringList &qmltypeDirs)
+ {
+ auto dom = parse(path, qmltypeDirs);
+ return dom.rootQmlObject(GoTo::MostLikely);
+ }
+
+ void fieldMemberExpressionHelper(const DomItem &actual, const QStringList &expected)
+ {
+ Q_ASSERT(!expected.isEmpty());
+ auto currentString = expected.rbegin();
+ auto endString = expected.rend();
+ DomItem current = actual;
+
+ for (; currentString != endString; ++currentString, current = current.field(Fields::left)) {
+ QCOMPARE(current.internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(current.field(Fields::operation).value().toInteger(),
+ ScriptElements::BinaryExpression::FieldMemberAccess);
+ QCOMPARE(current.field(Fields::right).internalKind(),
+ DomType::ScriptIdentifierExpression);
+ QCOMPARE(current.field(Fields::right).field(Fields::identifier).value().toString(),
+ *currentString);
+ }
+ }
+
+private slots:
+ void mapsKeyedByFileLocationRegion()
+ {
+ using namespace Qt::StringLiterals;
+ const QString filePath = baseDir + u"/fileLocationRegion.qml"_s;
+ const DomItem rootQmlObject = rootQmlObjectFromFile(filePath, qmltypeDirs);
+ QVERIFY(rootQmlObject);
+
+ // test if preComments map works correctly with DomItem interface
+ const DomItem binding = rootQmlObject.field(Fields::bindings).key(u"helloWorld"_s).index(0);
+ const DomItem bindingRegionComments =
+ binding.field(Fields::comments).field(Fields::regionComments);
+ const DomItem preComments =
+ bindingRegionComments.key(fileLocationRegionName(FileLocationRegion::IdentifierRegion))
+ .field(Fields::preComments);
+
+ QCOMPARE(preComments.indexes(), 1);
+ QString rawPreComment = preComments.index(0).field(Fields::rawComment).value().toString();
+ QCOMPARE(preComments.index(0)
+ .field(Fields::rawComment)
+ .value()
+ .toString()
+ // replace weird newlines by \n
+ .replace("\r\n", "\n")
+ .replace("\r", "\n"),
+ u" // before helloWorld binding\n "_s);
+
+ // test if postComments map works correctly with DomItem interface
+ const DomItem postComments =
+ bindingRegionComments
+ .key(fileLocationRegionName(FileLocationRegion::MainRegion))
+ .field(Fields::postComments);
+ QCOMPARE(postComments.indexes(), 1);
+ QCOMPARE(postComments.index(0)
+ .field(Fields::rawComment)
+ .value()
+ .toString()
+ // replace the windows newlines by \n
+ .replace("\r\n", "\n")
+ .replace("\r", "\n"),
+ u" // after helloWorld binding\n"_s);
+
+ const auto fileLocations = FileLocations::findAttachedInfo(binding);
+ const DomItem bindingFileLocation =
+ rootQmlObject.path(fileLocations.foundTreePath).field(Fields::infoItem);
+
+ // test if FileLocation Tree map works correctly with DomItem interface
+ QCOMPARE(bindingFileLocation.field(Fields::fullRegion).value(),
+ bindingFileLocation.field(Fields::regions)
+ .key(fileLocationRegionName(FileLocationRegion::MainRegion))
+ .value());
+
+ QCOMPARE(bindingFileLocation.field(Fields::fullRegion).value(),
+ sourceLocationToQCborValue(fileLocations.foundTree->info().fullRegion));
+
+ QCOMPARE(bindingFileLocation.field(Fields::regions)
+ .key(fileLocationRegionName(FileLocationRegion::MainRegion))
+ .value(),
+ sourceLocationToQCborValue(fileLocations.foundTree->info().regions[MainRegion]));
+
+ QCOMPARE(bindingFileLocation.field(Fields::regions)
+ .key(fileLocationRegionName(FileLocationRegion::ColonTokenRegion))
+ .value(),
+ sourceLocationToQCborValue(fileLocations.foundTree->info().regions[ColonTokenRegion]));
+ }
+
+ // add qml files here that should not crash the dom construction
+ void crashes_data()
+ {
+ QTest::addColumn<QString>("filePath");
+
+ QTest::addRow("inactiveVisitorMarkerCrash")
+ << baseDir + u"/inactiveVisitorMarkerCrash.qml"_s;
+
+ QTest::addRow("templateStrings")
+ << baseDir + u"/crashes/templateStrings.qml"_s;
+
+ QTest::addRow("lambda")
+ << baseDir + u"/crashes/lambda.qml"_s;
+
+ QTest::addRow("bracketsInBinding")
+ << baseDir + u"/crashes/bracketsInBinding.qml"_s;
+ }
+ void crashes()
+ {
+ QFETCH(QString, filePath);
+
+ const DomItem rootQmlObject = rootQmlObjectFromFile(filePath, qmltypeDirs);
+ QVERIFY(rootQmlObject);
+ }
+
+ void continueStatement()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/continueStatement.qml"_s;
+ const DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ const DomItem block =
+ rootQmlObject.path(".methods[\"f\"][0].body.scriptElement.statements");
+
+ const DomItem firstContinue = block.index(0);
+ QCOMPARE(firstContinue.internalKind(), DomType::ScriptContinueStatement);
+ QCOMPARE(firstContinue.field(Fields::label).value().toString("UNEXISTING"),
+ u"helloWorld"_s);
+
+ const DomItem secondContinue = block.index(1);
+ QCOMPARE(secondContinue.internalKind(), DomType::ScriptContinueStatement);
+ QCOMPARE(secondContinue.field(Fields::label).internalKind(), DomType::Empty);
+ }
+
+ void breakStatement()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/breakStatement.qml"_s;
+ const DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ const DomItem block =
+ rootQmlObject.path(".methods[\"f\"][0].body.scriptElement.statements");
+
+ const DomItem firstContinue = block.index(0);
+ QCOMPARE(firstContinue.internalKind(), DomType::ScriptBreakStatement);
+ QCOMPARE(firstContinue.field(Fields::label).value().toString("UNEXISTING"),
+ u"helloWorld"_s);
+
+ const DomItem secondContinue = block.index(1);
+ QCOMPARE(secondContinue.internalKind(), DomType::ScriptBreakStatement);
+ QCOMPARE(secondContinue.field(Fields::label).internalKind(), DomType::Empty);
+ }
+
+ void emptyMethodBody()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/emptyMethodBody.qml"_s;
+ const DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ const DomItem block = rootQmlObject.path(".methods[\"f\"][0].body.scriptElement");
+
+ QCOMPARE(block.internalKind(), DomType::ScriptBlockStatement);
+ QCOMPARE(block.field(Fields::statements).indexes(), 0);
+ }
+
+ void commaExpression()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/commaExpression.qml"_s;
+ const DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ const DomItem commaExpression = rootQmlObject.path(".methods[\"f\"][0].body.scriptElement.statements[0]");
+
+ QCOMPARE(commaExpression.internalKind(), DomType::ScriptBinaryExpression);
+ QCOMPARE(commaExpression.field(Fields::right)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"c"_s);
+ QCOMPARE(commaExpression.field(Fields::left)
+ .field(Fields::right)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"b"_s);
+ QCOMPARE(commaExpression.field(Fields::left)
+ .field(Fields::left)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"a"_s);
+ }
+
+ void conditionalExpression()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/conditionalExpression.qml"_s;
+ const DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+ const DomItem commaExpression = rootQmlObject.path(".methods[\"f\"][0].body.scriptElement.statements[0]");
+
+ QCOMPARE(commaExpression.internalKind(), DomType::ScriptConditionalExpression);
+ QCOMPARE(commaExpression.field(Fields::condition)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"a"_s);
+ QCOMPARE(commaExpression.field(Fields::consequence)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"b"_s);
+ QCOMPARE(commaExpression.field(Fields::alternative)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"c"_s);
+ }
+
+ void unaryExpression_data()
+ {
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<DomType>("type");
+
+ const QString folder = baseDir + u"/unaryExpressions/"_s;
+
+ QTest::addRow("minus") << folder + u"unaryMinus.qml"_s << DomType::ScriptUnaryExpression;
+ QTest::addRow("plus") << folder + u"unaryPlus.qml"_s << DomType::ScriptUnaryExpression;
+ QTest::addRow("tilde") << folder + u"tilde.qml"_s << DomType::ScriptUnaryExpression;
+ QTest::addRow("not") << folder + u"not.qml"_s << DomType::ScriptUnaryExpression;
+ QTest::addRow("typeof") << folder + u"typeof.qml"_s << DomType::ScriptUnaryExpression;
+ QTest::addRow("delete") << folder + u"delete.qml"_s << DomType::ScriptUnaryExpression;
+ QTest::addRow("void") << folder + u"void.qml"_s << DomType::ScriptUnaryExpression;
+ QTest::addRow("increment") << folder + u"increment.qml"_s << DomType::ScriptUnaryExpression;
+ QTest::addRow("decrement") << folder + u"decrement.qml"_s << DomType::ScriptUnaryExpression;
+
+ // post stuff
+ QTest::addRow("postIncrement")
+ << folder + u"postIncrement.qml"_s << DomType::ScriptPostExpression;
+ QTest::addRow("postDecrement")
+ << folder + u"postDecrement.qml"_s << DomType::ScriptPostExpression;
+ }
+
+ void unaryExpression()
+ {
+ using namespace Qt::StringLiterals;
+ QFETCH(QString, fileName);
+ QFETCH(DomType, type);
+ const DomItem rootQmlObject = rootQmlObjectFromFile(fileName, qmltypeDirs);
+ const DomItem firstStatement =
+ rootQmlObject.path(".methods[\"f\"][0].body.scriptElement.statements[0]");
+
+ QCOMPARE(firstStatement.internalKind(), type);
+ QCOMPARE(firstStatement.field(Fields::expression)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"a"_s);
+ }
+
+ void objectBindings()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/objectBindings.qml"_s;
+ const DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
+
+ const DomItem xBinding = rootQmlObject.path(".bindings[\"x\"][0].value");
+ QCOMPARE(xBinding.field(Fields::name).value().toString(), u"root.QQ.Drag");
+ QCOMPARE(xBinding.field(Fields::nameIdentifiers).internalKind(),
+ DomType::ScriptType);
+ QCOMPARE(xBinding.field(Fields::nameIdentifiers).field(Fields::typeName).internalKind(),
+ DomType::ScriptBinaryExpression);
+ QCOMPARE(xBinding.field(Fields::nameIdentifiers)
+ .field(Fields::typeName)
+ .field(Fields::operation)
+ .value()
+ .toInteger(-1),
+ ScriptElements::BinaryExpression::FieldMemberAccess);
+
+ QCOMPARE(xBinding.field(Fields::nameIdentifiers).field(Fields::typeName).field(Fields::left).internalKind(),
+ DomType::ScriptBinaryExpression);
+ QCOMPARE(xBinding.field(Fields::nameIdentifiers)
+ .field(Fields::typeName)
+ .field(Fields::left)
+ .field(Fields::right)
+ .value()
+ .toString(),
+ u"QQ");
+ QCOMPARE(xBinding.field(Fields::nameIdentifiers)
+ .field(Fields::typeName)
+ .field(Fields::left)
+ .field(Fields::left)
+ .value()
+ .toString(),
+ u"root");
+
+ const DomItem item = rootQmlObject.path(".children[0]");
+ QCOMPARE(item.field(Fields::nameIdentifiers).field(Fields::typeName).value().toString(),
+ u"Item");
+
+ const DomItem qqItem = rootQmlObject.path(".children[1]");
+ QCOMPARE(qqItem.field(Fields::nameIdentifiers)
+ .field(Fields::typeName)
+ .field(Fields::operation)
+ .value()
+ .toInteger(-1),
+ ScriptElements::BinaryExpression::FieldMemberAccess);
+ QCOMPARE(qqItem.field(Fields::nameIdentifiers)
+ .field(Fields::typeName)
+ .field(Fields::right)
+ .value()
+ .toString(),
+ u"Item");
+ QCOMPARE(qqItem.field(Fields::nameIdentifiers)
+ .field(Fields::typeName)
+ .field(Fields::left)
+ .value()
+ .toString(),
+ u"QQ");
+ }
+
+ void scriptExpression()
+ {
+ // verifying support of ECMA script modules by ScriptExpression
+ const ScriptExpression esmExport("export function a(){}",
+ ScriptExpression::ExpressionType::ESMCode);
+ QVERIFY(esmExport.localErrors().empty());
+ }
+
+ void semanticAnalysis()
+ {
+
+ DomItem baseItem;
+ DomItem derivedItem;
+ DomCreationOptions options;
+ options.setFlag(DomCreationOption::WithScriptExpressions);
+ options.setFlag(DomCreationOption::WithSemanticAnalysis);
+
+ auto envPtr =
+ DomEnvironment::create(qmltypeDirs, QQmlJS::Dom::DomEnvironment::Option{}, options);
+
+ envPtr->loadFile(
+ FileToLoad::fromFileSystem(envPtr, baseDir + u"/Base.qml"_s),
+ [&baseItem](Path, const DomItem &, const DomItem &newIt) {
+ baseItem = newIt.rootQmlObject(GoTo::MostLikely);
+ });
+
+ envPtr->loadFile(
+ FileToLoad::fromFileSystem(envPtr, baseDir + u"/Derived.qml"_s),
+ [&derivedItem](Path, const DomItem &, const DomItem &newIt) {
+ derivedItem = newIt.rootQmlObject(GoTo::MostLikely);
+ });
+ envPtr->loadPendingDependencies();
+
+ const auto baseScope = baseItem.semanticScope();
+ const auto derivedScope = derivedItem.semanticScope();
+
+ QCOMPARE_NE(baseScope, QQmlJSScope::ConstPtr{});
+ QCOMPARE(baseScope, derivedScope->baseType());
+ }
+
+ void propertyDefinitionScopes()
+ {
+ DomItem qmlObject;
+ DomCreationOptions options;
+ options.setFlag(DomCreationOption::WithScriptExpressions);
+ options.setFlag(DomCreationOption::WithSemanticAnalysis);
+
+ auto envPtr =
+ DomEnvironment::create(qmltypeDirs, QQmlJS::Dom::DomEnvironment::Option{}, options);
+
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, baseDir + u"/propertyBindings.qml"_s),
+ [&qmlObject](Path, const DomItem &, const DomItem &newIt) {
+ qmlObject = newIt.rootQmlObject(GoTo::MostLikely);
+ });
+ envPtr->loadPendingDependencies();
+
+ {
+ const auto a = qmlObject.field(Fields::propertyDefs).key(u"a").index(0);
+ const auto scopeA = a.semanticScope();
+ QCOMPARE_NE(scopeA, QQmlJSScope::ConstPtr{});
+ QCOMPARE(scopeA->scopeType(), QQmlSA::ScopeType::QMLScope);
+ }
+
+ {
+ const auto b = qmlObject.field(Fields::propertyDefs).key(u"b").index(0);
+ const auto scopeB = b.semanticScope();
+ QCOMPARE_NE(scopeB, QQmlJSScope::ConstPtr{});
+ QCOMPARE(scopeB->scopeType(), QQmlSA::ScopeType::QMLScope);
+ }
+ }
+
+ // simulate qmlls loading the same file twice like in QTBUG-123591
+ void loadFileTwice()
+ {
+ DomItem qmlObject;
+ DomItem qmlObject2;
+ DomCreationOptions options;
+ options.setFlag(DomCreationOption::WithScriptExpressions);
+ options.setFlag(DomCreationOption::WithSemanticAnalysis);
+ options.setFlag(DomCreationOption::WithRecovery);
+
+ std::shared_ptr<DomEnvironment> envPtr = DomEnvironment::create(
+ qmltypeDirs, QQmlJS::Dom::DomEnvironment::Option::SingleThreaded, options);
+
+ const QString fileName{ baseDir + u"/propertyBindings.qml"_s };
+ QFile file(fileName);
+ QVERIFY(file.open(QFile::ReadOnly));
+ const QString content = file.readAll();
+
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, baseDir + u"/propertyBindings.qml"_s),
+ [&qmlObject](Path, const DomItem &, const DomItem &newIt) {
+ qmlObject = newIt.rootQmlObject(GoTo::MostLikely);
+ });
+ envPtr->loadPendingDependencies();
+
+ // should not assert when loading the same file again
+ auto envPtrChild = envPtr->makeCopy(DomItem(envPtr));
+ envPtrChild->loadFile(
+ FileToLoad::fromMemory(envPtr, baseDir + u"/propertyBindings.qml"_s, content),
+ [&qmlObject2](Path, const DomItem &, const DomItem &newIt) {
+ qmlObject2 = newIt.rootQmlObject(GoTo::MostLikely);
+ });
+ envPtrChild->loadPendingDependencies();
+ }
+
+ void populateLazyFileBeforeCommitToBase()
+ {
+ DomItem qmlObject;
+ DomCreationOptions options;
+ options.setFlag(DomCreationOption::WithScriptExpressions);
+ options.setFlag(DomCreationOption::WithSemanticAnalysis);
+ options.setFlag(DomCreationOption::WithRecovery);
+
+ std::shared_ptr<DomEnvironment> envPtr = DomEnvironment::create(
+ qmltypeDirs, QQmlJS::Dom::DomEnvironment::Option::SingleThreaded, options);
+
+ const QString fileName{ QDir::cleanPath(baseDir + u"/propertyBindings.qml"_s) };
+
+ {
+ DomItem envChild = DomItem(envPtr).makeCopy(DomItem::CopyOption::EnvConnected).item();
+ auto envPtrChild = envChild.ownerAs<DomEnvironment>();
+ envPtrChild->loadFile(
+ FileToLoad::fromFileSystem(envPtrChild, fileName),
+ [&qmlObject](Path, const DomItem &, const DomItem &newIt) {
+ qmlObject = newIt.fileObject();
+ });
+ envPtrChild->loadPendingDependencies();
+
+ const DomItem childEnv = DomItem(envPtrChild->shared_from_this());
+ // populate the lazy file by accessing it via the DomItem interface
+ const DomItem mainComponent =
+ childEnv.field(Fields::qmlFileWithPath)
+ .key(fileName)
+ .field(Fields::currentItem)
+ .field(Fields::components)
+ .key(QString());
+ QVERIFY(mainComponent);
+
+ envPtrChild->commitToBase(DomItem(envPtrChild));
+ } // destroy the temporary environment that the file was loaded into
+
+ // also make sure that the main component also exists in the base environment after the
+ // commitToBase call.
+ const DomItem env = DomItem(envPtr->shared_from_this());
+ const DomItem mainComponent = env.field(Fields::qmlFileWithPath)
+ .key(fileName)
+ .field(Fields::currentItem)
+ .field(Fields::components)
+ .key(QString());
+ QVERIFY(mainComponent);
+ }
+
+ void populateLazyFileAfterCommitToBase()
+ {
+ DomItem qmlObject;
+ DomCreationOptions options;
+ options.setFlag(DomCreationOption::WithScriptExpressions);
+ options.setFlag(DomCreationOption::WithSemanticAnalysis);
+ options.setFlag(DomCreationOption::WithRecovery);
+
+ std::shared_ptr<DomEnvironment> envPtr = DomEnvironment::create(
+ qmltypeDirs, QQmlJS::Dom::DomEnvironment::Option::SingleThreaded, options);
+
+ const QString fileName{ QDir::cleanPath(baseDir + u"/propertyBindings.qml"_s) };
+
+ {
+ DomItem envChild = DomItem(envPtr).makeCopy(DomItem::CopyOption::EnvConnected).item();
+ auto envPtrChild = envChild.ownerAs<DomEnvironment>();
+ envPtrChild->loadFile(
+ FileToLoad::fromFileSystem(envPtrChild, fileName),
+ [&qmlObject](Path, const DomItem &, const DomItem &newIt) {
+ qmlObject = newIt.fileObject();
+ });
+ envPtrChild->loadPendingDependencies();
+ envPtrChild->commitToBase(DomItem(envPtrChild));
+ } // destroy the temporary environment that the file was loaded into
+
+ const DomItem env = DomItem(envPtr->shared_from_this());
+ // populate the lazy file by accessing it via the DomItem interface
+ const DomItem mainComponent = env.field(Fields::qmlFileWithPath)
+ .key(fileName)
+ .field(Fields::currentItem)
+ .field(Fields::components)
+ .key(QString());
+ QVERIFY(mainComponent);
+ }
+
+ void qtbug_124799()
+ {
+ // reproduces the completion crash in QTBUG-124799 that was actually not completion related:
+ // triggering the completion was triggering the population of a file, that led to a
+ // heap-use-after-free. The steps to reproduce the crash are following:
+ // 1. load a file in a temporary environment
+ // 2. grab an unpopulated qqmljsscope from the type resolver of the loaded file
+ // 3. destroy the temporary environment
+ // 4. update the loaded file with new content, to make sure the QQmlJSImporter (used to
+ // populate of qmlfiles) has no more strong references in the QmlFile.
+ // 5. populate the unpopulated qqmljsscope: its factory should have kept track that its
+ // environment is not the temporary one but the base one (because of the commitToBase()
+ // call) and use the correct QQmlJSImporter (if its the one from the temporary environment
+ // this will lead to the heap-use-after-free memory error you get when triggering
+ // completions before this fix)
+
+ DomItem qmlObject;
+ DomCreationOptions options;
+ options.setFlag(DomCreationOption::WithScriptExpressions);
+ options.setFlag(DomCreationOption::WithSemanticAnalysis);
+ options.setFlag(DomCreationOption::WithRecovery);
+
+ std::shared_ptr<DomEnvironment> envPtr = DomEnvironment::create(
+ qmltypeDirs, QQmlJS::Dom::DomEnvironment::Option::SingleThreaded, options);
+
+ const QString fileName{ QDir::cleanPath(baseDir + u"/propertyBindings.qml"_s) };
+
+ QQmlJSScope::ConstPtr populateAfterEnvironmentDestruction;
+
+ {
+ DomItem envChild = DomItem(envPtr).makeCopy(DomItem::CopyOption::EnvConnected).item();
+ auto envPtrChild = envChild.ownerAs<DomEnvironment>();
+ envPtrChild->loadFile(
+ FileToLoad::fromFileSystem(envPtrChild, fileName),
+ [&qmlObject](Path, const DomItem &, const DomItem &newIt) {
+ qmlObject = newIt.fileObject();
+ });
+ envPtrChild->loadPendingDependencies();
+
+ auto qmlFilePtr = qmlObject.ownerAs<QmlFile>();
+ auto resolver = qmlFilePtr->typeResolver();
+ // simulate completion by grabbing some type from the resolver
+ populateAfterEnvironmentDestruction = resolver->importedTypes()[u"Derived"_s].scope;
+ envPtrChild->commitToBase(DomItem(envPtrChild));
+ }
+
+ // update the file
+ {
+ DomItem envChild = DomItem(envPtr).makeCopy(DomItem::CopyOption::EnvConnected).item();
+ auto envPtrChild = envChild.ownerAs<DomEnvironment>();
+
+ // simulate user typing something
+ QFile file(fileName);
+ QVERIFY(file.open(QFile::ReadOnly));
+ const QString content = file.readAll();
+ const QString newContent = content + "\n // important comment here\n";
+ envPtrChild->loadFile(FileToLoad::fromMemory(envPtrChild, fileName, newContent),
+ [&qmlObject](Path, const DomItem &, const DomItem &newIt) {
+ qmlObject = newIt.fileObject();
+ });
+ envPtrChild->loadPendingDependencies();
+ envPtrChild->commitToBase(DomItem(envPtrChild));
+ }
+
+ // step 3: populate the lazy qqmljsscope, it should not crash
+ QCOMPARE(populateAfterEnvironmentDestruction->filePath(),
+ QDir::cleanPath(baseDir + u"/Derived.qml"_s));
+ }
+
+ void visitTreeFilter()
+ {
+ DomItem qmlObject;
+ DomCreationOptions options;
+ options.setFlag(DomCreationOption::WithScriptExpressions);
+ options.setFlag(DomCreationOption::WithSemanticAnalysis);
+
+ auto envPtr =
+ DomEnvironment::create(qmltypeDirs, QQmlJS::Dom::DomEnvironment::Option{}, options);
+
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, baseDir + u"/visitTreeFilter.qml"_s),
+ [&qmlObject](Path, const DomItem &, const DomItem &newIt) {
+ qmlObject = newIt.rootQmlObject(GoTo::MostLikely);
+ });
+ envPtr->loadPendingDependencies();
+
+ FieldFilter filter({}, { { QString(), QString::fromUtf16(Fields::propertyDefs) } });
+
+ // check if propertyDefs is visited without the filter
+ bool success = false;
+ qmlObject.visitTree(
+ Path(), emptyChildrenVisitor, VisitOption::Recurse | VisitOption::VisitSelf,
+ [&success](const Path &p, const DomItem &, bool) {
+ const QString pathString = p.toString();
+ if (p && p.checkHeadName(Fields::propertyDefs)) {
+ success = true;
+ }
+ return true;
+ },
+ emptyChildrenVisitor);
+ QVERIFY(success);
+
+ // check that propertyDefs is not visited with the filter
+ success = true;
+ qmlObject.visitTree(
+ Path(), emptyChildrenVisitor, VisitOption::Recurse | VisitOption::VisitSelf,
+ [&success](const Path &p, const DomItem &, bool) {
+ if (p && p.checkHeadName(Fields::propertyDefs)) {
+ qWarning() << "Filter did not filter propertyDefs at path" << p;
+ success = false;
+ }
+ return true;
+ },
+ emptyChildrenVisitor, filter);
+ QVERIFY(success);
+ }
+
+ void fileLocationRegions_data()
+ {
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<FileLocationRegion>("region");
+ QTest::addColumn<QSet<QQmlJS::SourceLocation>>("expectedLocs");
+
+ QTest::newRow("import") << baseDir + u"/fileLocationRegions/imports.qml"_s << ImportTokenRegion <<
+ QSet {
+ QQmlJS::SourceLocation{112, 6, 4, 1},
+ QQmlJS::SourceLocation{127, 6, 5, 1},
+ };
+ QTest::newRow("importUri") << baseDir + u"/fileLocationRegions/imports.qml"_s << ImportUriRegion <<
+ QSet {
+ QQmlJS::SourceLocation{119, 7, 4, 8},
+ QQmlJS::SourceLocation{152, 16, 6, 8},
+ QQmlJS::SourceLocation{186, 9, 7, 8}
+ };
+ QTest::newRow("asToken") << baseDir + u"/fileLocationRegions/imports.qml"_s << AsTokenRegion <<
+ QSet {
+ QQmlJS::SourceLocation{169, 2, 6, 25}
+ };
+ QTest::newRow("version") << baseDir + u"/fileLocationRegions/imports.qml"_s << VersionRegion <<
+ QSet {
+ QQmlJS::SourceLocation{140, 4, 5, 14}
+ };
+ QTest::newRow("namespace") << baseDir + u"/fileLocationRegions/imports.qml"_s << IdNameRegion <<
+ QSet {
+ QQmlJS::SourceLocation{172, 6, 6, 28}
+ };
+
+ QTest::newRow("function") << baseDir + u"/fileLocationRegions/functions.qml"_s
+ << FunctionKeywordRegion
+ << QSet{ QQmlJS::SourceLocation{ 139, 9, 7, 5 },
+ QQmlJS::SourceLocation{ 195, 9, 10, 9 } };
+
+ QTest::newRow("signal") << baseDir + u"/fileLocationRegions/functions.qml"_s
+ << SignalKeywordRegion
+ << QSet{ QQmlJS::SourceLocation{ 234, 6, 13, 5 },
+ QQmlJS::SourceLocation{ 254, 6, 14, 5 } };
+ QTest::newRow("return-type-identifier")
+ << baseDir + u"/fileLocationRegions/functions.qml"_s << TypeIdentifierRegion
+ << QSet{ QQmlJS::SourceLocation{ 154, 3, 7, 20 },
+ QQmlJS::SourceLocation{ 216, 3, 10, 30 } };
+ QTest::newRow("function-parameter-type-identifier")
+ << baseDir + u"/fileLocationRegions/functions.qml"_s << TypeIdentifierRegion
+ << QSet{ QQmlJS::SourceLocation{ 209, 3, 10, 23 } };
+ QTest::newRow("signal-parameter-type-identifier")
+ << baseDir + u"/fileLocationRegions/functions.qml"_s << TypeIdentifierRegion
+ << QSet{ QQmlJS::SourceLocation{ 243, 3, 13, 14 },
+ QQmlJS::SourceLocation{ 267, 3, 14, 18 } };
+ QTest::newRow("signal-parameter-identifier")
+ << baseDir + u"/fileLocationRegions/functions.qml"_s << IdentifierRegion
+ << QSet{ QQmlJS::SourceLocation{ 247, 1, 13, 18 },
+ QQmlJS::SourceLocation{ 264, 1, 14, 15 } };
+
+ QTest::newRow("pragma-keyword")
+ << baseDir + u"/fileLocationRegions/pragmas.qml"_s << PragmaKeywordRegion
+ << QSet{ QQmlJS::SourceLocation{ 112, 6, 4, 1 },
+ QQmlJS::SourceLocation{ 129, 6, 5, 1 },
+ QQmlJS::SourceLocation{ 161, 6, 6, 1 },
+ QQmlJS::SourceLocation{ 204, 6, 7, 1 }};
+ QTest::newRow("pragmaId")
+ << baseDir + u"/fileLocationRegions/pragmas.qml"_s << IdentifierRegion
+ << QSet{ QQmlJS::SourceLocation{ 119, 9, 4, 8 },
+ QQmlJS::SourceLocation{ 136, 17, 5, 8 },
+ QQmlJS::SourceLocation{ 168, 25, 6, 8 },
+ QQmlJS::SourceLocation{ 211, 17, 7, 8 }};
+ QTest::newRow("pragmaValues")
+ << baseDir + u"/fileLocationRegions/pragmas.qml"_s << PragmaValuesRegion
+ << QSet{ QQmlJS::SourceLocation{ 155, 5, 5, 27 },
+ QQmlJS::SourceLocation{ 195, 8, 6, 35 },
+ QQmlJS::SourceLocation{ 230, 4, 7, 27 },
+ QQmlJS::SourceLocation{ 235, 11, 7, 32 }};
+
+ QTest::newRow("enum-keyword")
+ << baseDir + u"/fileLocationRegions/enums.qml"_s << EnumKeywordRegion
+ << QSet{ QQmlJS::SourceLocation{ 139, 4, 7, 5 }};
+ QTest::newRow("enum-id")
+ << baseDir + u"/fileLocationRegions/enums.qml"_s << IdentifierRegion
+ << QSet{ QQmlJS::SourceLocation{ 144, 3, 7, 10 }};
+ QTest::newRow("enum-member")
+ << baseDir + u"/fileLocationRegions/enums.qml"_s << IdentifierRegion
+ << QSet{ QQmlJS::SourceLocation{ 158, 3, 8, 9 },
+ QQmlJS::SourceLocation{ 175, 3, 9, 9 },
+ QQmlJS::SourceLocation{ 188, 3, 10, 9 }};
+ QTest::newRow("enum-value")
+ << baseDir + u"/fileLocationRegions/enums.qml"_s << EnumValueRegion
+ << QSet{ QQmlJS::SourceLocation{ 164, 1, 8, 15 },
+ QQmlJS::SourceLocation{ 194, 2, 10, 15 }};
+ }
+
+ void fileLocationRegions()
+ {
+ QFETCH(QString, filePath);
+ QFETCH(FileLocationRegion, region);
+ QFETCH(QSet<QQmlJS::SourceLocation>, expectedLocs);
+ auto envPtr = DomEnvironment::create(
+ QStringList(),
+ QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
+ | QQmlJS::Dom::DomEnvironment::Option::NoDependencies);
+
+ QFile f(filePath);
+ QVERIFY(f.open(QIODevice::ReadOnly | QIODevice::Text));
+ QString code = f.readAll();
+ DomItem file;
+ envPtr->loadFile(FileToLoad::fromMemory(envPtr, filePath, code),
+ [&file](Path, const DomItem &, const DomItem &newIt) {
+ file = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
+
+ const auto tree = FileLocations::treeOf(file);
+ using AttachedInfo = AttachedInfoT<FileLocations>;
+ QSet<QQmlJS::SourceLocation> locs;
+ auto visitor = [&](const Path &currentPath, const AttachedInfo::Ptr &attachedInfo){
+ Q_UNUSED(currentPath);
+ const auto regions = attachedInfo->info().regions;
+ if (regions.contains(region)) {
+ locs << regions.value(region);
+ }
+ return true;
+ };
+ AttachedInfo::visitTree(tree, visitor, Path());
+ [&] {
+ QVERIFY(locs.contains(expectedLocs));
+ }();
+
+ if (QTest::currentTestFailed()) {
+ qDebug() << "Got:\n";
+ for (auto &x : locs) {
+ qDebug() << "Offset: " << x.offset
+ << ", Length:" << x.length
+ << ", Startline: " << x.startLine
+ << ", StartColumn: " << x.startColumn;
+ }
+ qDebug() << "But expected: \n";
+ for (auto &x : expectedLocs) {
+ qDebug() << "Offset: " << x.offset
+ << ", Length:" << x.length
+ << ", Startline: " << x.startLine
+ << ", StartColumn: " << x.startColumn;
+ }
+ }
+ }
+
+ void doNotCrashAtAstComments()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/astComments.qml"_s;
+ const DomItem fileObject = rootQmlObjectFromFile(testFile, qmltypeDirs).fileObject();
+ const DomItem astComments = fileObject.path(".astComments");
+
+ // Visiting astComment element shouldn't fail
+ QSet<QStringView> comments;
+ astComments.visitTree(
+ Path(),
+ [&comments](const Path &, const DomItem &item, bool) {
+ if (item.internalKind() == DomType::Comment) {
+ auto comment = item.as<Comment>();
+ comments << comment->rawComment();
+ }
+ return true;
+ }
+ );
+
+ QVERIFY(comments.contains(u"/*Ast Comment*/ "_s));
+ }
+
+ void doNotCrashOnMissingLogger()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = QDir::cleanPath(baseDir + u"/astComments.qml"_s);
+ const DomItem fileObject = rootQmlObjectFromFile(testFile, qmltypeDirs).fileObject();
+ auto filePtr = fileObject.as<QmlFile>();
+ QVERIFY(filePtr);
+ auto typeResolver = filePtr->typeResolver();
+ QVERIFY(typeResolver);
+ auto logger = typeResolver->logger();
+ // make sure that the logger is not use-after-free by checking its content
+ QCOMPARE(logger->fileName(), testFile);
+ }
+
+ void commentLocations()
+ {
+ auto envPtr = DomEnvironment::create(
+ QStringList(),
+ QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
+ | QQmlJS::Dom::DomEnvironment::Option::NoDependencies);
+
+ const auto filePath = baseDir + u"/fileLocationRegions/comments.qml"_s;
+ QFile f(filePath);
+ QVERIFY(f.open(QIODevice::ReadOnly | QIODevice::Text));
+ QString code = f.readAll();
+ DomItem file;
+ envPtr->loadFile(FileToLoad::fromMemory(envPtr, filePath, code),
+ [&file](Path, const DomItem &, const DomItem &newIt) {
+ file = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
+
+ const auto expctedCommentLocations = QSet {
+ QQmlJS::SourceLocation(0, 41, 1, 1),
+ QQmlJS::SourceLocation(42,68, 2, 1),
+ QQmlJS::SourceLocation(126,25, 6, 1),
+ QQmlJS::SourceLocation(152,14, 10, 1),
+ QQmlJS::SourceLocation(167,21, 11, 1)
+ };
+
+ QSet<SourceLocation> locs;
+ file.fileObject(GoTo::MostLikely).visitTree(Path(), [&locs](Path, const DomItem &item, bool){
+ if (item.internalKind() == DomType::Comment) {
+ const auto comment = item.as<Comment>();
+ if (comment) {
+ locs << comment->info().sourceLocation();
+ }
+ }
+ return true;
+ }, VisitOption::Default, emptyChildrenVisitor, emptyChildrenVisitor);
+
+
+ QCOMPARE(locs, expctedCommentLocations);
+ }
+
+ void lambdas()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/lambdas.qml"_s;
+ const DomItem fileObject = rootQmlObjectFromFile(testFile, qmltypeDirs).fileObject();
+ const DomItem mainObject = fileObject.field(Fields::components)
+ .key(QString())
+ .index(0)
+ .field(Fields::objects)
+ .index(0);
+ {
+ const DomItem lambda = mainObject.field(Fields::methods)
+ .key(u"method"_s)
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements)
+ .index(1)
+ .field(Fields::declarations)
+ .index(0)
+ .field(Fields::initializer);
+ QVERIFY(lambda);
+ QCOMPARE(lambda.internalKind(), DomType::ScriptFunctionExpression);
+ QCOMPARE(lambda.field(Fields::name).value().toString(), u"myLambda"_s);
+ QCOMPARE(lambda.field(Fields::parameters).indexes(), 2);
+ QCOMPARE(lambda.field(Fields::parameters).index(0).field(Fields::identifier).value().toString(), u"a");
+ QCOMPARE(lambda.field(Fields::parameters).index(1).field(Fields::identifier).value().toString(), u"b");
+
+ auto scope = lambda.semanticScope();
+ QVERIFY(scope);
+ QVERIFY(scope->jsIdentifier(u"b"_s));
+
+ const DomItem body = lambda.field(Fields::body);
+ QCOMPARE(body.internalKind(), DomType::ScriptBlockStatement);
+ }
+ }
+ void arrow()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/lambdas.qml"_s;
+ const DomItem fileObject = rootQmlObjectFromFile(testFile, qmltypeDirs).fileObject();
+ const DomItem mainObject = fileObject.field(Fields::components)
+ .key(QString())
+ .index(0)
+ .field(Fields::objects)
+ .index(0);
+ {
+ const DomItem arrow = mainObject.field(Fields::methods)
+ .key(u"method"_s)
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements)
+ .index(2)
+ .field(Fields::declarations)
+ .index(0)
+ .field(Fields::initializer);
+ QVERIFY(arrow);
+ QCOMPARE(arrow.internalKind(), DomType::ScriptFunctionExpression);
+ QCOMPARE(arrow.field(Fields::name).value().toString(), u"myArrow"_s);
+ QCOMPARE(arrow.field(Fields::parameters).indexes(), 2);
+ QCOMPARE(arrow.field(Fields::parameters)
+ .index(0)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"v");
+ QCOMPARE(arrow.field(Fields::parameters)
+ .index(1)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"w");
+
+ auto scope = arrow.semanticScope();
+ QVERIFY(scope);
+ QVERIFY(scope->jsIdentifier(u"w"_s));
+
+ const DomItem body = arrow.field(Fields::body);
+ QCOMPARE(body.internalKind(), DomType::ScriptBlockStatement);
+ QCOMPARE(body.field(Fields::statements).indexes(), 1);
+ QCOMPARE(body.field(Fields::statements).index(0).internalKind(),
+ DomType::ScriptReturnStatement);
+ }
+ }
+ void lamdbaInBinding()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/lambdas.qml"_s;
+ const DomItem fileObject = rootQmlObjectFromFile(testFile, qmltypeDirs).fileObject();
+ const DomItem mainObject = fileObject.field(Fields::components)
+ .key(QString())
+ .index(0)
+ .field(Fields::objects)
+ .index(0);
+ {
+ const DomItem lambda = mainObject.field(Fields::bindings)
+ .key(u"onHelloSignal"_s)
+ .index(0)
+ .field(Fields::value)
+ .field(Fields::scriptElement);
+ QVERIFY(lambda);
+ QCOMPARE(lambda.internalKind(), DomType::ScriptFunctionExpression);
+ QCOMPARE(lambda.field(Fields::name).value().toString(), QString());
+ QCOMPARE(lambda.field(Fields::parameters).indexes(), 3);
+ QCOMPARE(lambda.field(Fields::parameters).index(0).field(Fields::identifier).value().toString(), u"x");
+ QCOMPARE(lambda.field(Fields::parameters).index(2).field(Fields::identifier).value().toString(), u"z");
+ auto scope = lambda.semanticScope();
+ QVERIFY(scope);
+ QVERIFY(scope->jsIdentifier(u"z"_s));
+ const DomItem body = lambda.field(Fields::body);
+ QCOMPARE(body.internalKind(), DomType::ScriptBlockStatement);
+ }
+ }
+ void nestedFunction()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/lambdas.qml"_s;
+ const DomItem fileObject = rootQmlObjectFromFile(testFile, qmltypeDirs).fileObject();
+ const DomItem mainObject = fileObject.field(Fields::components)
+ .key(QString())
+ .index(0)
+ .field(Fields::objects)
+ .index(0);
+ {
+ const DomItem nested = mainObject.field(Fields::methods)
+ .key(u"testNestedFunctions"_s)
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements)
+ .index(0);
+ QVERIFY(nested);
+ QCOMPARE(nested.internalKind(), DomType::ScriptFunctionExpression);
+ QCOMPARE(nested.field(Fields::name).value().toString(), u"nested"_s);
+ QCOMPARE(nested.field(Fields::parameters).indexes(), 3);
+ QCOMPARE(nested.field(Fields::parameters)
+ .index(0)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"tic");
+ QCOMPARE(nested.field(Fields::parameters)
+ .index(2)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"toe");
+ const DomItem body = nested.field(Fields::body);
+ QCOMPARE(body.internalKind(), DomType::ScriptBlockStatement);
+ auto scope = nested.semanticScope();
+ QVERIFY(scope);
+ QVERIFY(scope->jsIdentifier(u"toe"_s));
+ }
+ }
+ void generatorDeclaration()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/lambdas.qml"_s;
+ const DomItem fileObject = rootQmlObjectFromFile(testFile, qmltypeDirs).fileObject();
+ const DomItem mainObject = fileObject.field(Fields::components)
+ .key(QString())
+ .index(0)
+ .field(Fields::objects)
+ .index(0);
+ {
+ const DomItem generator = mainObject.field(Fields::methods)
+ .key(u"generators"_s)
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements)
+ .index(0);
+ QVERIFY(generator);
+ QCOMPARE(generator.internalKind(), DomType::ScriptFunctionExpression);
+ QCOMPARE(generator.field(Fields::name).value().toString(), u"myGeneratorDeclaration"_s);
+ QCOMPARE(generator.field(Fields::parameters).indexes(), 2);
+ QCOMPARE(generator.field(Fields::parameters)
+ .index(0)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"a");
+ QCOMPARE(generator.field(Fields::parameters)
+ .index(1)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"b");
+ const DomItem body = generator.field(Fields::body);
+ QCOMPARE(body.internalKind(), DomType::ScriptBlockStatement);
+ auto scope = generator.semanticScope();
+ QVERIFY(scope);
+ QVERIFY(scope->jsIdentifier(u"b"_s));
+
+ const DomItem yieldExpression =
+ generator.field(Fields::body).field(Fields::statements).index(0);
+ QCOMPARE(yieldExpression.internalKind(), DomType::ScriptYieldExpression);
+ QCOMPARE(yieldExpression.field(Fields::expression).value().toInteger(), 5);
+ }
+ }
+ void generatorExpression()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/lambdas.qml"_s;
+ const DomItem fileObject = rootQmlObjectFromFile(testFile, qmltypeDirs).fileObject();
+ const DomItem mainObject = fileObject.field(Fields::components)
+ .key(QString())
+ .index(0)
+ .field(Fields::objects)
+ .index(0);
+ {
+ const DomItem generator = mainObject.field(Fields::methods)
+ .key(u"generators"_s)
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements)
+ .index(1)
+ .field(Fields::declarations)
+ .index(0)
+ .field(Fields::initializer);
+ QVERIFY(generator);
+ QCOMPARE(generator.internalKind(), DomType::ScriptFunctionExpression);
+ QCOMPARE(generator.field(Fields::name).value().toString(), u"myGenerator"_s);
+ QCOMPARE(generator.field(Fields::parameters).indexes(), 3);
+ QCOMPARE(generator.field(Fields::parameters)
+ .index(0)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"tic");
+ QCOMPARE(generator.field(Fields::parameters)
+ .index(2)
+ .field(Fields::identifier)
+ .value()
+ .toString(),
+ u"toe");
+ const DomItem body = generator.field(Fields::body);
+ QCOMPARE(body.internalKind(), DomType::ScriptBlockStatement);
+ auto scope = generator.semanticScope();
+ QVERIFY(scope);
+ QVERIFY(scope->jsIdentifier(u"toe"_s));
+ }
+ }
+ void generatorDeclarationInQmlObject()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/lambdas.qml"_s;
+ const DomItem fileObject = rootQmlObjectFromFile(testFile, qmltypeDirs).fileObject();
+ const DomItem statements = fileObject.field(Fields::components)
+ .key(QString())
+ .index(0)
+ .field(Fields::objects)
+ .index(0)
+ .field(Fields::methods)
+ .key(u"generatorInQmlObject"_s)
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements);
+ {
+ const DomItem nested = statements.index(0);
+ QVERIFY(nested);
+ QCOMPARE(nested.internalKind(), DomType::ScriptFunctionExpression);
+
+ const DomItem nested2 = statements.index(1);
+ QVERIFY(nested2);
+ QCOMPARE(nested2.internalKind(), DomType::ScriptFunctionExpression);
+
+ const DomItem yield = statements.index(2);
+ QVERIFY(yield);
+ QCOMPARE(yield.internalKind(), DomType::ScriptYieldExpression);
+
+ const DomItem yieldStar = statements.index(3);
+ QVERIFY(yieldStar);
+ QCOMPARE(yieldStar.internalKind(), DomType::ScriptYieldExpression);
+
+ }
+ }
+ void traditionalLambda()
+ {
+ using namespace Qt::StringLiterals;
+ const QString testFile = baseDir + u"/lambdas.qml"_s;
+ const DomItem fileObject = rootQmlObjectFromFile(testFile, qmltypeDirs).fileObject();
+ const DomItem initializer = fileObject.field(Fields::components)
+ .key(QString())
+ .index(0)
+ .field(Fields::objects)
+ .index(0)
+ .field(Fields::methods)
+ .key(u"traditionalLambda"_s)
+ .index(0)
+ .field(Fields::body)
+ .field(Fields::scriptElement)
+ .field(Fields::statements)
+ .index(0)
+ .field(Fields::declarations)
+ .index(0)
+ .field(Fields::initializer);
+ QVERIFY(initializer);
+ QCOMPARE(initializer.internalKind(), DomType::ScriptParenthesizedExpression);
+ const DomItem lambda = initializer.field(Fields::expression);
+ QVERIFY(lambda);
+ QCOMPARE(lambda.internalKind(), DomType::ScriptFunctionExpression);
+ }
+
+
private:
QString baseDir;
QStringList qmltypeDirs;
diff --git a/tests/auto/qmldom/errormessage/CMakeLists.txt b/tests/auto/qmldom/errormessage/CMakeLists.txt
index 5a61ebcb29..7c82876827 100644
--- a/tests/auto/qmldom/errormessage/CMakeLists.txt
+++ b/tests/auto/qmldom/errormessage/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmldomerrormessage Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmldomerrormessage LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qmldomerrormessage
SOURCES
tst_qmldomerrormessage.cpp tst_qmldomerrormessage.h
diff --git a/tests/auto/qmldom/errormessage/tst_qmldomerrormessage.cpp b/tests/auto/qmldom/errormessage/tst_qmldomerrormessage.cpp
index 0ca1091a18..2c2007c119 100644
--- a/tests/auto/qmldom/errormessage/tst_qmldomerrormessage.cpp
+++ b/tests/auto/qmldom/errormessage/tst_qmldomerrormessage.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_qmldomerrormessage.h"
#include <QtQmlDom/private/qqmldomerrormessage_p.h>
diff --git a/tests/auto/qmldom/errormessage/tst_qmldomerrormessage.h b/tests/auto/qmldom/errormessage/tst_qmldomerrormessage.h
index f7d3a291b6..31628ef52d 100644
--- a/tests/auto/qmldom/errormessage/tst_qmldomerrormessage.h
+++ b/tests/auto/qmldom/errormessage/tst_qmldomerrormessage.h
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQmlDom/qqmldom_global.h>
#include <QtTest/QtTest>
diff --git a/tests/auto/qmldom/merging/CMakeLists.txt b/tests/auto/qmldom/merging/CMakeLists.txt
index 2eaf7b9615..a33df96216 100644
--- a/tests/auto/qmldom/merging/CMakeLists.txt
+++ b/tests/auto/qmldom/merging/CMakeLists.txt
@@ -6,6 +6,13 @@
#####################################################################
## tst_qmldomitem Binary:
#####################################################################
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_dommerging LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/..
diff --git a/tests/auto/qmldom/merging/tst_dommerging.cpp b/tests/auto/qmldom/merging/tst_dommerging.cpp
index 2dc1570e32..1fa994b1a3 100644
--- a/tests/auto/qmldom/merging/tst_dommerging.cpp
+++ b/tests/auto/qmldom/merging/tst_dommerging.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_dommerging.h"
QTEST_MAIN(QQmlJS::Dom::TestDomMerging)
diff --git a/tests/auto/qmldom/merging/tst_dommerging.h b/tests/auto/qmldom/merging/tst_dommerging.h
index 01d20014bf..59937b279e 100644
--- a/tests/auto/qmldom/merging/tst_dommerging.h
+++ b/tests/auto/qmldom/merging/tst_dommerging.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TST_DOMMERGING_H
#define TST_DOMMERGING_H
@@ -38,16 +38,13 @@ private slots:
auto envPtr = std::shared_ptr<QQmlJS::Dom::DomEnvironment>(new QQmlJS::Dom::DomEnvironment(
qmltypeDirs,
DomEnvironment::Option::SingleThreaded | DomEnvironment::Option::NoDependencies));
- QQmlJS::Dom::DomItem env(envPtr);
- QVERIFY(env);
QString testFile1 = baseDir + QLatin1String("/test1.qml");
- env.loadFile(
- testFile1, QString(),
- [this](Path, const DomItem &, const DomItem &newIt) { this->tFile = newIt; },
- LoadOption::DefaultLoad);
- env.loadFile(baseDir, QString(), {}, LoadOption::DefaultLoad);
- envPtr->loadPendingDependencies(env);
+ envPtr->loadFile(
+ FileToLoad::fromFileSystem(envPtr, testFile1),
+ [this](Path, const DomItem &, const DomItem &newIt) { this->tFile = newIt; });
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, baseDir), {});
+ envPtr->loadPendingDependencies();
QVERIFY(tFile);
tFile = tFile.field(Fields::currentItem);
diff --git a/tests/auto/qmldom/path/CMakeLists.txt b/tests/auto/qmldom/path/CMakeLists.txt
index dbffe714d9..bf3e5d20f5 100644
--- a/tests/auto/qmldom/path/CMakeLists.txt
+++ b/tests/auto/qmldom/path/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmldompath Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmldompath LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qmldompath
SOURCES
tst_qmldompath.cpp tst_qmldompath.h
diff --git a/tests/auto/qmldom/path/tst_qmldompath.cpp b/tests/auto/qmldom/path/tst_qmldompath.cpp
index 86ef15e035..54a634e476 100644
--- a/tests/auto/qmldom/path/tst_qmldompath.cpp
+++ b/tests/auto/qmldom/path/tst_qmldompath.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_qmldompath.h"
QTEST_MAIN(QQmlJS::Dom::PathEls::TestPaths)
diff --git a/tests/auto/qmldom/path/tst_qmldompath.h b/tests/auto/qmldom/path/tst_qmldompath.h
index 24d8c30bcf..f463b93164 100644
--- a/tests/auto/qmldom/path/tst_qmldompath.h
+++ b/tests/auto/qmldom/path/tst_qmldompath.h
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TST_QMLDOMPATH_H
#define TST_QMLDOMPATH_H
@@ -16,7 +16,7 @@ namespace PathEls {
class TestPaths: public QObject {
Q_OBJECT
public:
- void testPathInternals(Path p1)
+ void testPathInternals(const Path &p1)
{
QCOMPARE(p1.component(0).kind(), Kind::Root);
QCOMPARE(p1.component(1).kind(), Kind::Current);
@@ -85,11 +85,11 @@ private slots:
auto c10=PathComponent(Any());
QCOMPARE(c10.kind(), Kind::Any);
QVERIFY(c9!=c10);
- auto c11=PathComponent(Filter([](DomItem){ return true; }));
+ auto c11=PathComponent(Filter([](const DomItem &){ return true; }));
auto c12=c11;
- auto c13=PathComponent(Filter([](DomItem){ return false; }));
- auto c14=PathComponent(Filter([](DomItem){ return false; }, u"skipAll"));
- auto c15=PathComponent(Filter([](DomItem){ return true; }, u"skipAll"));
+ auto c13=PathComponent(Filter([](const DomItem &){ return false; }));
+ auto c14=PathComponent(Filter([](const DomItem &){ return false; }, u"skipAll"));
+ auto c15=PathComponent(Filter([](const DomItem &){ return true; }, u"skipAll"));
QCOMPARE(c11.kind(), Kind::Filter);
QCOMPARE(c11, c11);
QVERIFY(c11 != c12); // native code assumed to be non comparable and different even if they are the same
@@ -132,7 +132,7 @@ private slots:
QCOMPARE(p6[6].headKind(), Kind::Empty);
auto rString = u"$.@.aa[4][\"bla\"][*].";
QCOMPARE(p6.toString(), rString);
- auto p7 = p6.filter([](DomItem){ return true; }, u"true");
+ auto p7 = p6.filter([](const DomItem &){ return true; }, u"true");
auto p7Str = p7.toString();
QCOMPARE(p7Str, u"$.@.aa[4][\"bla\"][*].[?(true)]");
auto p8 = p7.dropTail();
@@ -161,7 +161,7 @@ private slots:
void testPathSplit()
{
- QList<Path> paths({Path(),
+ const QList<Path> paths({Path(),
Path::Root(PathRoot::Env).field(u"pippo").key(u"pluto").index(4),
Path::Root(PathRoot::Env).field(u"pippo").key(u"pluto"),
Path::Root(PathRoot::Env).field(u"pippo"),
@@ -175,7 +175,7 @@ private slots:
Path::Index(4),
Path::Key(u"zz")
});
- foreach (Path p, paths) {
+ for (const Path &p : paths) {
Source s = p.split();
QCOMPARE(p, s.pathToSource.path(s.pathFromSource));
if (!s.pathFromSource)
diff --git a/tests/auto/qmldom/reformatter/CMakeLists.txt b/tests/auto/qmldom/reformatter/CMakeLists.txt
index 7b7f7e4708..1b8cfb0d8a 100644
--- a/tests/auto/qmldom/reformatter/CMakeLists.txt
+++ b/tests/auto/qmldom/reformatter/CMakeLists.txt
@@ -4,6 +4,13 @@
#####################################################################
## tst_reformatter:
#####################################################################
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_reformatter LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/..
diff --git a/tests/auto/qmldom/reformatter/tst_reformatter.cpp b/tests/auto/qmldom/reformatter/tst_reformatter.cpp
index 75f8b445e7..00d26bc55b 100644
--- a/tests/auto/qmldom/reformatter/tst_reformatter.cpp
+++ b/tests/auto/qmldom/reformatter/tst_reformatter.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_reformatter.h"
QTEST_MAIN(QQmlJS::Dom::TestReformatter)
diff --git a/tests/auto/qmldom/reformatter/tst_reformatter.h b/tests/auto/qmldom/reformatter/tst_reformatter.h
index 908c2f66a9..5cf800c80c 100644
--- a/tests/auto/qmldom/reformatter/tst_reformatter.h
+++ b/tests/auto/qmldom/reformatter/tst_reformatter.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TST_QMLDOMCODEFORMATTER_H
#define TST_QMLDOMCODEFORMATTER_H
@@ -8,6 +8,7 @@
#include <QtQmlDom/private/qqmldomoutwriter_p.h>
#include <QtQmlDom/private/qqmldomitem_p.h>
#include <QtQmlDom/private/qqmldomtop_p.h>
+#include <QtQmlDom/private/qqmldomreformatter_p.h>
#include <QtTest/QtTest>
#include <QCborValue>
@@ -24,6 +25,69 @@ class TestReformatter : public QObject
{
Q_OBJECT
public:
+private:
+ // TODO Move to a dedicated LineWriter factory / LineWriter API ?
+ enum class LineWriterType { Default, Indenting };
+ std::unique_ptr<LineWriter> getLineWriter(const SinkF &innerSink,
+ const LineWriterOptions &lwOptions)
+ {
+ return lwOptions.maxLineLength > 0
+ ? getLineWriter(LineWriterType::Indenting, innerSink, lwOptions)
+ : getLineWriter(LineWriterType::Default, innerSink, lwOptions);
+ }
+
+ std::unique_ptr<LineWriter> getLineWriter(LineWriterType type, const SinkF &innerSink,
+ const LineWriterOptions &lwOptions)
+ {
+ switch (type) {
+ case LineWriterType::Indenting:
+ return std::make_unique<IndentingLineWriter>(innerSink, QLatin1String("*testStream*"),
+ lwOptions);
+ default:
+ return std::make_unique<LineWriter>(innerSink, QLatin1String("*testStream*"),
+ lwOptions);
+ }
+ Q_UNREACHABLE_RETURN(nullptr);
+ }
+
+ // "Unix" LineWriter (with '\n' line endings) is used by default,
+ // under the assumption that line endings are properly tested in lineWriter() test.
+ static LineWriterOptions defaultLineWriterOptions()
+ {
+ LineWriterOptions opts;
+ opts.lineEndings = LineWriterOptions::LineEndings::Unix;
+ return opts;
+ }
+
+ QString formatJSCode(const QString &jsCode,
+ const LineWriterOptions &lwOptions = defaultLineWriterOptions())
+ {
+ return formatPlainJS(jsCode, ScriptExpression::ExpressionType::JSCode, lwOptions);
+ }
+
+ QString formatJSModuleCode(const QString &jsCode,
+ const LineWriterOptions &lwOptions = defaultLineWriterOptions())
+ {
+ return formatPlainJS(jsCode, ScriptExpression::ExpressionType::ESMCode, lwOptions);
+ }
+
+ QString formatPlainJS(const QString &jsCode, ScriptExpression::ExpressionType exprType,
+ const LineWriterOptions &lwOptions = defaultLineWriterOptions())
+ {
+ QString resultStr;
+ QTextStream res(&resultStr);
+ auto lwPtr = getLineWriter([&res](QStringView s) { res << s; }, lwOptions);
+ assert(lwPtr);
+ OutWriter ow(*lwPtr);
+
+ const ScriptExpression scriptItem(jsCode, exprType);
+ scriptItem.writeOut(DomItem(), ow);
+
+ lwPtr->flush(); // flush instead of eof to ignore line endings
+ res.flush();
+ return resultStr;
+ }
+
private slots:
void reindent_data()
{
@@ -145,18 +209,16 @@ private slots:
QString baseDir = QLatin1String(QT_QMLTEST_DATADIR) + QLatin1String("/reformatter");
QStringList qmltypeDirs =
QStringList({ baseDir, QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath) });
- DomItem env = DomEnvironment::create(
+ auto envPtr = DomEnvironment::create(
qmltypeDirs,
QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
| QQmlJS::Dom::DomEnvironment::Option::NoDependencies);
QString testFilePath = baseDir + QLatin1Char('/') + inFile;
DomItem tFile;
- env.loadBuiltins();
- env.loadFile(
- testFilePath, QString(),
- [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; },
- LoadOption::DefaultLoad);
- env.loadPendingDependencies();
+ envPtr->loadBuiltins();
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, testFilePath),
+ [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; });
+ envPtr->loadPendingDependencies();
MutableDomItem myFile = tFile.field(Fields::currentItem);
@@ -252,20 +314,16 @@ private slots:
QString baseDir = QLatin1String(QT_QMLTEST_DATADIR) + QLatin1String("/reformatter");
QStringList qmltypeDirs =
QStringList({ baseDir, QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath) });
- DomItem env = DomEnvironment::create(
+ auto envPtr = DomEnvironment::create(
qmltypeDirs,
QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
| QQmlJS::Dom::DomEnvironment::Option::NoDependencies);
QString testFilePath = baseDir + QLatin1Char('/') + inFile;
DomItem tFile;
- env.loadBuiltins();
- env.loadFile(
- testFilePath, QString(),
- [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; },
- LoadOption::DefaultLoad);
- env.loadPendingDependencies();
-
- MutableDomItem myFile = tFile.field(Fields::currentItem);
+ envPtr->loadBuiltins();
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, testFilePath),
+ [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; });
+ envPtr->loadPendingDependencies();
QString resultStr;
QTextStream res(&resultStr);
@@ -388,6 +446,331 @@ private slots:
}
}
+ void hoistableDeclaration_data()
+ {
+ QTest::addColumn<QString>("declarationToBeFormatted");
+ QTest::addColumn<QString>("expectedFormattedDeclaration");
+
+ QTest::newRow("Function") << QStringLiteral(u"function a(a,b){}")
+ << QStringLiteral(u"function a(a, b) {}");
+ QTest::newRow("AnonymousFunction") << QStringLiteral(u"let f=function (a,b){}")
+ << QStringLiteral(u"let f = function (a, b) {}");
+ QTest::newRow("Generator_lhs_star")
+ << QStringLiteral(u"function* g(a,b){}") << QStringLiteral(u"function* g(a, b) {}");
+ QTest::newRow("Generator_rhs_star")
+ << QStringLiteral(u"function *g(a,b){}") << QStringLiteral(u"function* g(a, b) {}");
+ QTest::newRow("AnonymousGenerator") << QStringLiteral(u"let g=function * (a,b){}")
+ << QStringLiteral(u"let g = function* (a, b) {}");
+ QTest::newRow("yield") << QStringLiteral(u"let g=function*(a,b){yield a;}")
+ << QStringLiteral(u"let g = function* (a, b) {\nyield a;\n}");
+ QTest::newRow("yield*") << QStringLiteral(u"let g=function*(a,b){yield*a;}")
+ << QStringLiteral(u"let g = function* (a, b) {\nyield* a;\n}");
+ QTest::newRow("yield*NoSemicolon")
+ << QStringLiteral(u"let g=function*(a,b){yield*a}")
+ << QStringLiteral(u"let g = function* (a, b) {\nyield* a;\n}");
+ }
+
+ // https://262.ecma-international.org/7.0/#prod-HoistableDeclaration
+ void hoistableDeclaration()
+ {
+ QFETCH(QString, declarationToBeFormatted);
+ QFETCH(QString, expectedFormattedDeclaration);
+
+ QString formattedDeclaration = formatJSCode(declarationToBeFormatted);
+
+ QCOMPARE(formattedDeclaration, expectedFormattedDeclaration);
+ }
+
+ void exportDeclarations_data()
+ {
+ QTest::addColumn<QString>("exportToBeFormatted");
+ QTest::addColumn<QString>("expectedFormattedExport");
+ // not exhaustive list of ExportDeclarations as per
+ // https://262.ecma-international.org/7.0/#prod-ExportDeclaration
+
+ // LexicalDeclaration
+ QTest::newRow("LexicalDeclaration_let_Binding")
+ << QStringLiteral(u"export let name") << QStringLiteral(u"export let name;");
+ QTest::newRow("LexicalDeclaration_const_BindingList")
+ << QStringLiteral(u"export const "
+ u"n1=1,n2=2,n3=3,n4=4,n5=5")
+ << QStringLiteral(u"export const "
+ u"n1 = 1, n2 = 2, n3 = 3, n4 = 4, n5 = 5;");
+ QTest::newRow("LexicalDeclaration_const_ArrayBinding")
+ << QStringLiteral(u"export const "
+ u"[a,b]=a_and_b")
+ << QStringLiteral(u"export const "
+ u"[a, b] = a_and_b;");
+ QTest::newRow("LexicalDeclaration_let_ObjectBinding")
+ << QStringLiteral(u"export let "
+ u"{a,b:c}=a_and_b")
+ << QStringLiteral(u"export let "
+ u"{\na,\nb: c\n} = a_and_b;");
+
+ // ClassDeclaration
+ QTest::newRow("ClassDeclaration") << QStringLiteral(u"export "
+ u"class A extends B{}")
+ << QStringLiteral(u"export "
+ u"class A extends B {}");
+
+ // HoistableDeclaration
+ QTest::newRow("HoistableDeclaration_FunctionDeclaration")
+ << QStringLiteral(u"export "
+ u"function a(a,b){}")
+ << QStringLiteral(u"export "
+ u"function a(a, b) {}");
+ QTest::newRow("HoistableDeclaration_GeneratorDeclaration")
+ << QStringLiteral(u"export "
+ u"function * g(a,b){}")
+ << QStringLiteral(u"export "
+ u"function* g(a, b) {}");
+
+ // export ExportClause ;
+ QTest::newRow("ExportClause_Empty")
+ << QStringLiteral(u"export{}") << QStringLiteral(u"export {};");
+ QTest::newRow("ExportClause_1Specifier")
+ << QStringLiteral(u"export{one}") << QStringLiteral(u"export { one };");
+ QTest::newRow("ExportClause_Specifier_as")
+ << QStringLiteral(u"export{one as o}") << QStringLiteral(u"export { one as o };");
+ QTest::newRow("ExportClause_Specifier_as_StringLiteral")
+ << QStringLiteral(u"export{one as \"s\"}")
+ << QStringLiteral(u"export { one as \"s\" };");
+ QTest::newRow("ExportClause_ExportsList")
+ << QStringLiteral(u"export{one,two,three,four as fo,five}")
+ << QStringLiteral(u"export { one, two, three, four as fo, five };");
+
+ // export * FromClause ;
+ QTest::newRow("star") << QStringLiteral(u"export * from \"design\"")
+ << QStringLiteral(u"export * from \"design\";");
+ QTest::newRow("star_as_Specifier") << QStringLiteral(u"export * as star from \"design\"")
+ << QStringLiteral(u"export * as star from \"design\";");
+
+ // export ExportClause FromClause ;
+ QTest::newRow("ExportClause")
+ << QStringLiteral(u"export {i1 as n1,i2 as n2,nN} from \"M\"")
+ << QStringLiteral(u"export { i1 as n1, i2 as n2, nN } from \"M\";");
+
+ // export default HoistableDeclaration
+ QTest::newRow("Default_AnonymousFunction")
+ << QStringLiteral(u"export default function(a,b){}")
+ << QStringLiteral(u"export default function (a, b) {}");
+ QTest::newRow("Default_AnonymousGenerator")
+ << QStringLiteral(u"export default function * (a,b){}")
+ << QStringLiteral(u"export default function* (a, b) {}");
+ QTest::newRow("Default_Function") << QStringLiteral(u"export default function a(a,b){}")
+ << QStringLiteral(u"export default function a(a, b) {}");
+
+ // export default ClassDeclaration
+ QTest::newRow("Default_Class") << QStringLiteral(u"export default class A{}")
+ << QStringLiteral(u"export default class A {}");
+ QTest::newRow("Default_AnonymousClass")
+ << QStringLiteral(u"export default class extends A{}")
+ << QStringLiteral(u"export default class extends A{}");
+
+ // export default Expression
+ QTest::newRow("Default_Expression") << QStringLiteral(u"export default 1+1")
+ << QStringLiteral(u"export default 1 + 1;");
+ QTest::newRow("Default_ArrowFunctionExpression")
+ << QStringLiteral(u"export default(x,y)=> x+2")
+ << QStringLiteral(u"export default (x, y) => x + 2;");
+ }
+
+ // https://262.ecma-international.org/7.0/#prod-ExportDeclaration
+ void exportDeclarations()
+ {
+ QFETCH(QString, exportToBeFormatted);
+ QFETCH(QString, expectedFormattedExport);
+
+ QString formattedExport = formatJSModuleCode(exportToBeFormatted);
+
+ QEXPECT_FAIL("ExportClause_Specifier_as_StringLiteral",
+ "export {a as \"string name\"} declaration is not supported yet", Abort);
+ QEXPECT_FAIL("star_as_Specifier", "export * as star declaration is not supported yet",
+ Abort);
+ QEXPECT_FAIL("Default_AnonymousClass", "QTBUG-122291", Abort);
+ QEXPECT_FAIL("Default_AnonymousFunction", "QTBUG-122291", Abort);
+ QEXPECT_FAIL("Default_AnonymousGenerator", "QTBUG-122291", Abort);
+ QCOMPARE(formattedExport, expectedFormattedExport);
+ }
+
+ void carryoverMJS_data()
+ {
+ QTest::addColumn<QString>("codeToBeFormatted");
+ QTest::addColumn<int>("maxLineLength");
+ QTest::addColumn<QString>("expectedFormattedCode");
+
+ QTest::newRow("LongExportList_NoMaxLineLength")
+ << QStringLiteral(u"export const n1=1,n2=2,n3=3,n4=4,n5=5") << -1
+ << QStringLiteral(u"export const n1 = 1, n2 = 2, n3 = 3, n4 = 4, n5 = 5;");
+ QTest::newRow("LongExportList_MaxLineLength20")
+ << QStringLiteral(u"export const n1=1,n2=2,n3=3,n4=4,n5=5") << 20
+ << QStringLiteral(u"export const n1 = 1,\n"
+ u" n2 = 2, n3 = 3,\n"
+ u" n4 = 4, n5 = 5;");
+ }
+
+ void carryoverMJS()
+ {
+ QFETCH(QString, codeToBeFormatted);
+ QFETCH(int, maxLineLength);
+ QFETCH(QString, expectedFormattedCode);
+
+ LineWriterOptions lwOptions;
+ lwOptions.maxLineLength = maxLineLength;
+ // TODO maybe fetch this
+ lwOptions.formatOptions.indentSize = 2;
+ QString formattedCode = formatJSModuleCode(codeToBeFormatted, lwOptions);
+
+ QEXPECT_FAIL("LongExportList_MaxLineLength20", "QTBUG-122260", Abort);
+ QCOMPARE(formattedCode, expectedFormattedCode);
+ }
+
+ void importDeclarations_data()
+ {
+ QTest::addColumn<QString>("importToBeFormatted");
+ QTest::addColumn<QString>("expectedFormattedImport");
+ // not exhaustive list of ExportDeclarations as per
+ // https://262.ecma-international.org/7.0/#prod-ImportDeclaration
+
+ // import ModuleSpecifier;
+ QTest::newRow("ModuleSpecifier")
+ << QStringLiteral(u"import \"Module\"") << QStringLiteral(u"import \"Module\";");
+
+ // import ImportClause FromClause ;
+ QTest::newRow("NameSpaceImport") << QStringLiteral(u"import * as d from \"design\";")
+ << QStringLiteral(u"import * as d from \"design\";");
+
+ QTest::newRow("NamedImports") << QStringLiteral(u"import {b,cd as c,d} from \"M\";")
+ << QStringLiteral(u"import { b, cd as c, d } from \"M\";");
+
+ QTest::newRow("DefaultBindung") << QStringLiteral(u"import defaultExport from \"M\"")
+ << QStringLiteral(u"import defaultExport from \"M\";");
+ QTest::newRow("DefaultBindung_NameSpaceImport")
+ << QStringLiteral(u"import defaultExport, * as m from \"M\";")
+ << QStringLiteral(u"import defaultExport, * as m from \"M\";");
+ QTest::newRow("DefaultBinding_NamedImports")
+ << QStringLiteral(u"import defaultExport,{b,cd as c,d} from \"M\";")
+ << QStringLiteral(u"import defaultExport, { b, cd as c, d } from \"M\";");
+
+ QTest::newRow("ImportClause_Specifier_as_StringLiteral")
+ << QStringLiteral(u"import{\"s\" as s} from \"M\"")
+ << QStringLiteral(u"import { \"s\" as s } from \"M\";");
+ }
+
+ // https://262.ecma-international.org/7.0/#prod-ImportDeclaration
+ void importDeclarations()
+ {
+ QFETCH(QString, importToBeFormatted);
+ QFETCH(QString, expectedFormattedImport);
+
+ QString formattedImport = formatJSModuleCode(importToBeFormatted);
+
+ QEXPECT_FAIL(
+ "ImportClause_Specifier_as_StringLiteral",
+ "import {\"string literal export\" as alias } declaration is not supported yet",
+ Abort);
+ QCOMPARE(formattedImport, expectedFormattedImport);
+ }
+
+ void methodDefinitions_data()
+ {
+ QTest::addColumn<QString>("methodToBeFormatted");
+ QTest::addColumn<QString>("expectedFormattedMethod");
+
+ // ObjectInitializer
+ QTest::newRow("ObjGetter") << QStringLiteral(u"const o={get a(){},}")
+ << QStringLiteral(u"const o = {\nget a(){}\n}");
+ QTest::newRow("ObjSetter") << QStringLiteral(u"const o={set a(a){},}")
+ << QStringLiteral(u"const o = {\nset a(a){}\n}");
+ QTest::newRow("ComputedObjPropertyGetter")
+ << QStringLiteral(u"const o={get [a+b](){},}")
+ << QStringLiteral(u"const o = {\nget [a + b](){}\n}");
+
+ // Generator
+ QTest::newRow("ObjPropertyGenerator")
+ << QStringLiteral(u"const o={*a(){1+1;},}")
+ << QStringLiteral(u"const o = {\n*a(){\n1 + 1;\n}\n}");
+ QTest::newRow("ComputedClassPropertyGenerator")
+ << QStringLiteral(u"class A{*[a+b](){}}")
+ << QStringLiteral(u"class A {\n*[a + b](){}\n}");
+
+ // ClassDefinitions
+ QTest::newRow("ClassGetter") << QStringLiteral(u"class A{get a(){}}")
+ << QStringLiteral(u"class A {\nget a(){}\n}");
+ QTest::newRow("ClassSetter") << QStringLiteral(u"class A{set a(a){}}")
+ << QStringLiteral(u"class A {\nset a(a){}\n}");
+ }
+
+ // https://262.ecma-international.org/7.0/#sec-method-definitions
+ void methodDefinitions()
+ {
+ QFETCH(QString, methodToBeFormatted);
+ QFETCH(QString, expectedFormattedMethod);
+
+ QString formattedMethod = formatJSCode(methodToBeFormatted);
+
+ QCOMPARE(formattedMethod, expectedFormattedMethod);
+ }
+
+ void statementList_data()
+ {
+ QTest::addColumn<QString>("codeToBeFormatted");
+ QTest::addColumn<QString>("expectedFormattedCode");
+
+ QTest::newRow("StatementsOnTheSameLine")
+ << QStringLiteral(u"a=1;b=1;") << QStringLiteral(u"a = 1;\nb = 1;");
+
+ QTest::newRow("StatementsOnSuccessiveLines")
+ << QStringLiteral(u"a=1;\nb=1;") << QStringLiteral(u"a = 1;\nb = 1;");
+
+ QTest::newRow("EmptyLineBetweenStatements")
+ << QStringLiteral(u"a=1;\n\nb=1;") << QStringLiteral(u"a = 1;\n\nb = 1;");
+
+ QTest::newRow("MultipleEmptyLinesBetweenStatements")
+ << QStringLiteral(u"a=1;\n\n\n\n\n\nb=1;") << QStringLiteral(u"a = 1;\n\nb = 1;");
+
+ QTest::newRow("MultilineStatementWithStatementOnTheFollowingLine")
+ << QStringLiteral(u"console.log(\n\n);\nb = 1;")
+ << QStringLiteral(u"console.log();\nb = 1;");
+
+ QTest::newRow("StatementWithPostCommentAndStatementOnTheFollowingLine")
+ << QStringLiteral(u"a=1;//\nb=1;") << QStringLiteral(u"a = 1;//\nb = 1;");
+
+ QTest::newRow("StatementWithPostCommentAndEmptyLineToNextStatement")
+ << QStringLiteral(u"a=1;//\n\nb=1;") << QStringLiteral(u"a = 1;//\n\nb = 1;");
+
+ QTest::newRow("StatementWithPostCommentAndMultipleEmptyLinesToNextStatement")
+ << QStringLiteral(u"a=1;//\n\n\n\n\nb=1;") << QStringLiteral(u"a = 1;//\n\nb = 1;");
+
+ QTest::newRow("StatementsWithCommentInBetweenThem")
+ << QStringLiteral(u"a=1;\n//\nb=1;") << QStringLiteral(u"a = 1;\n//\nb = 1;");
+
+ QTest::newRow("StatementsWithCommentAndSingleEmptyLineInBetweenThem")
+ << QStringLiteral(u"a=1;\n\n//\n\nb=1;")
+ << QStringLiteral(u"a = 1;\n\n//\n\nb = 1;");
+
+ QTest::newRow("StatementsWithCommentAndMultipleEmptyLinesInBetweenThem")
+ << QStringLiteral(u"a=1;\n\n\n\n//\n\n\nb=1;")
+ << QStringLiteral(u"a = 1;\n\n//\n\nb = 1;");
+
+ QTest::newRow("StatementWithSingleEmptyLineAndPreCommentOnNextStatement")
+ << QStringLiteral(u"a=1;\n\n//\nb=1;") << QStringLiteral(u"a = 1;\n\n//\nb = 1;");
+
+ QTest::newRow("StatementWithMultipleEmptyLinesAndPreCommentOnNextStatement")
+ << QStringLiteral(u"a=1;\n\n\n\n\n\n\n\n//\nb=1;")
+ << QStringLiteral(u"a = 1;\n\n//\nb = 1;");
+ }
+
+ void statementList()
+ {
+ QFETCH(QString, codeToBeFormatted);
+ QFETCH(QString, expectedFormattedCode);
+
+ QString formattedCode = formatJSCode(codeToBeFormatted);
+
+ QCOMPARE(formattedCode, expectedFormattedCode);
+ }
+
private:
};
diff --git a/tests/auto/qmldom/standalone/CMakeLists.txt b/tests/auto/qmldom/standalone/CMakeLists.txt
deleted file mode 100644
index e141ec0835..0000000000
--- a/tests/auto/qmldom/standalone/CMakeLists.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
-
-#####################################################################
-## tst_dom_all Binary executing all tests together
-## (simpler to verify coverage)
-#####################################################################
-# Collect test data
-file(GLOB_RECURSE test_data_glob
- RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/..
- domdata/*)
-list(APPEND test_data ${test_data_glob})
-
-set(QMLDOM_EXTERNAL_BUILD OFF CACHE BOOL "If the build is against an external Qt, and not tested inside a build of this Qt" FORCE)
-add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/qmldom/standalone qmldomlib)
-
-if(MSVC)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
-elseif (MINGW)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj")
-endif()
-
-qt_internal_add_test(tst_standalone
- SOURCES
- tst_standalone.cpp
- DEFINES
- QT_DEPRECATED_WARNINGS
- QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/../domdata"
- LIBRARIES
- Qt::Core
- Qt::QmlPrivate
- qmldomlib
- TESTDATA ${test_data}
-)
-
-qt_internal_extend_target(tst_standalone CONDITION ANDROID OR IOS
- DEFINES
- QT_QMLTEST_DATADIR=":/domdata"
-)
diff --git a/tests/auto/qmldom/standalone/tst_standalone.cpp b/tests/auto/qmldom/standalone/tst_standalone.cpp
deleted file mode 100644
index 14b6424525..0000000000
--- a/tests/auto/qmldom/standalone/tst_standalone.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-#include "tst_standalone.h"
-QTEST_MAIN(QQmlJS::Dom::TestStandalone)
diff --git a/tests/auto/qmldom/standalone/tst_standalone.h b/tests/auto/qmldom/standalone/tst_standalone.h
deleted file mode 100644
index c403c660e6..0000000000
--- a/tests/auto/qmldom/standalone/tst_standalone.h
+++ /dev/null
@@ -1,634 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-#include <QtTest/QtTest>
-#ifdef QMLDOM_STANDALONE
-# include "qmldom/qqmldom_global.h"
-// common declarations
-# include "qmldom/qqmldomitem_p.h"
-// comparisons of two DomItems
-# include "qmldom/qqmldomcompare_p.h"
-// field filters to compare only selected fields (ignore for example location changes)
-# include "qmldom/qqmldomfieldfilter_p.h"
-// needed to edit and cast to concrete type (PropertyDefinition, ScriptExpression,...)
-# include "qmldom/qqmldomelements_p.h"
-// cast of the top level items (DomEnvironments,...)
-# include "qmldom/qqmldomtop_p.h"
-#else
-# include <QtQmlDom/qqmldom_global.h>
-// common declarations
-# include <QtQmlDom/private/qqmldomitem_p.h>
-// comparisons of two DomItems
-# include <QtQmlDom/private/qqmldomcompare_p.h>
-// field filters to compare only selected fields (ignore for example location changes)
-# include <QtQmlDom/private/qqmldomfieldfilter_p.h>
-// needed to edit and cast to concrete type (PropertyDefinition, ScriptExpression,...)
-# include <QtQmlDom/private/qqmldomelements_p.h>
-// cast of the top level items (DomEnvironments,...)
-# include <QtQmlDom/private/qqmldomtop_p.h>
-#endif
-
-#include <QDebug>
-#include <QLatin1String>
-#include <QLatin1Char>
-#include <QLibraryInfo>
-#include <QDir>
-
-QT_BEGIN_NAMESPACE
-namespace QQmlJS {
-namespace Dom {
-
-class TestStandalone : public QObject
-{
- Q_OBJECT
-private slots:
- void testLoadEditSave()
- {
- QString baseDir = QLatin1String(QT_QMLTEST_DATADIR) + QLatin1String("/reformatter");
- QStringList qmltypeDirs =
- QStringList({ baseDir, QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath) });
-
- // qDebug() << "Creating an environment loading qml from the directories" << qmltypeDirs;
- // qDebug() << "single threaded, no dependencies";
- DomItem env = DomEnvironment::create(
- qmltypeDirs,
- QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
- | QQmlJS::Dom::DomEnvironment::Option::NoDependencies);
-
- QString testFilePath = baseDir + QLatin1String("/file1.qml");
- DomItem tFile; // place where to store the loaded file
-
- // qDebug() << "loading the file" << testFilePath;
- env.loadFile(
- testFilePath, QString(),
- [&tFile](Path, const DomItem &, const DomItem &newIt) {
- tFile = newIt; // callback called when everything is loaded that receives the
- // loaded external file pair (path, oldValue, newValue)
- },
- LoadOption::DefaultLoad);
-
- // trigger the load
- env.loadPendingDependencies();
-
- // # Read only API: DomItem is a generic pointer for read only access to Dom Itmes :)
- {
- // ## declarative json like API
- DomItem qmlFile = tFile.field(Fields::currentItem);
- DomItem imports = qmlFile.field(Fields::imports);
- DomItem qmlObj = qmlFile.field(Fields::components)
- .key(QString())
- .index(0)
- .field(Fields::objects)
- .index(0);
-
- // ### Dump
- // any DomItem can be dumped
- // qDebug() << "writing to QDebug dumps that element:" << imports;
- // often the dump is too verbose, and one might want it to a separate file
- QString dumpFilePath = QDir(QDir::tempPath())
- .filePath(QFileInfo(testFilePath).baseName()
- + QLatin1String(".dump.json"));
- qmlFile.dump(dumpFilePath, FieldFilter::defaultFilter());
- // qDebug() << "dumped file to" << dumpFilePath;
-
- // ### Paths
- // qDebug() << "To identify a DomItem a canonical path can be used:"
- // << imports.canonicalPath();
- // a path can be converted to/from strings
- QString pString = imports.canonicalPath().toString();
- Path importsPath = Path::fromString(pString);
- // and loaded again using the .path(somePath) method
- DomItem imports2 = env.path(importsPath);
- QCOMPARE(imports, imports2);
- // the canonical path is absolute, but you can have relative paths
- Path first = Path::Index(0);
- DomItem firstImport = imports.path(first);
- // an existing path can also be extended
- Path firstImportPath = importsPath.index(0);
- QCOMPARE(firstImportPath, firstImport.canonicalPath());
- // the normal elements of a path are index, key, field
- // Uppercase static method creates one, lowercase appends to an existing path.
- Path mainComponentPath = Path::Field(Fields::components).key("").index(0);
- DomItem mainComponent = qmlFile.path(mainComponentPath);
- // DomItems have the same methods to access their elements
- DomItem mainComponent2 = qmlFile.field(Fields::components).key("").index(0);
- // two other special ements are root (root element for absolute paths)
- Path topPath = Path::Root(PathRoot::Top);
- QCOMPARE(topPath, importsPath[0]);
- // the current element performs an operation (tipically a lookup or iteration) at the
- // current path location (not handled here)
- Path lookupPath = Path::Current(PathCurrent::Lookup);
-
- // there are various visit methods to iterate/visit DomItems in particular visitTree
- // which is quite flexible.
- // They normally use callbacks that can return false to stop the iteration.
- // Still often the DomKind specific for loop presentated later are clearer and more
- // convenient
- {
- QString s;
- QTextStream dbg(&s);
- imports.visitTree(
- Path(),
- [&dbg](Path p, const DomItem &el, bool) {
- dbg << QStringLiteral(u" ").repeated(p.length()) << "*"
- << p.last().toString() << " " << domKindToString(el.domKind())
- << "(" << el.internalKindStr() << ")\n";
- // returning false here stops the whole iteration
- return true;
- },
- VisitOption::Default, // we want a recursive visit visiting also the top and
- // adopted
- [&dbg](Path p, const DomItem &, bool canonicalChild) {
- // returning false here skips that branch
- if (!canonicalChild) {
- dbg << QStringLiteral(u" ").repeated(p.length()) << "+"
- << p.last().toString() << " (adopted, will not recurse)\n";
- } else if (p && p.headIndex(0) % 2 == 1) {
- dbg << QStringLiteral(u" ").repeated(p.length()) << "-"
- << p.last().toString() << " *recursive visit skipped*\n";
- return false; // we skip odd entries in lists;
- } else {
- dbg << QStringLiteral(u" ").repeated(p.length()) << "+"
- << p.last().toString() << "\n";
- }
- return true;
- },
- [&dbg](Path p, const DomItem &, bool) {
- dbg << QStringLiteral(u" ").repeated(p.length()) << "="
- << p.last().toString() << "\n";
- return true;
- });
- dbg.flush();
- QCOMPARE(s,
- QStringLiteral("* List(List)\n"
- "+\n"
- " *[0] Object(Import)\n"
- " +[0]\n"
- " *.uri Value(ConstantData)\n"
- " +.uri\n"
- " =.uri\n"
- " *.version Object(Version)\n"
- " +.version\n"
- " *.majorVersion Value(ConstantData)\n"
- " +.majorVersion\n"
- " =.majorVersion\n"
- " *.minorVersion Value(ConstantData)\n"
- " +.minorVersion\n"
- " =.minorVersion\n"
- " *.isLatest Value(ConstantData)\n"
- " +.isLatest\n"
- " =.isLatest\n"
- " *.isValid Value(ConstantData)\n"
- " +.isValid\n"
- " =.isValid\n"
- " *.stringValue Value(ConstantData)\n"
- " +.stringValue\n"
- " =.stringValue\n"
- " =.version\n"
- " *.implicit Value(ConstantData)\n"
- " +.implicit\n"
- " =.implicit\n"
- " *.comments Object(RegionComments)\n"
- " +.comments\n"
- " =.comments\n"
- " =[0]\n"
- " *[1] Object(Import)\n"
- " -[1] *recursive visit skipped*\n"
- " *[2] Object(Import)\n"
- " +[2]\n"
- " *.uri Value(ConstantData)\n"
- " +.uri\n"
- " =.uri\n"
- " *.version Object(Version)\n"
- " +.version\n"
- " *.majorVersion Value(ConstantData)\n"
- " +.majorVersion\n"
- " =.majorVersion\n"
- " *.minorVersion Value(ConstantData)\n"
- " +.minorVersion\n"
- " =.minorVersion\n"
- " *.isLatest Value(ConstantData)\n"
- " +.isLatest\n"
- " =.isLatest\n"
- " *.isValid Value(ConstantData)\n"
- " +.isValid\n"
- " =.isValid\n"
- " *.stringValue Value(ConstantData)\n"
- " +.stringValue\n"
- " =.stringValue\n"
- " =.version\n"
- " *.implicit Value(ConstantData)\n"
- " +.implicit\n"
- " =.implicit\n"
- " *.comments Object(RegionComments)\n"
- " +.comments\n"
- " =.comments\n"
- " =[2]\n"
- " *[3] Object(Import)\n"
- " -[3] *recursive visit skipped*\n"
- " *[4] Object(Import)\n"
- " +[4]\n"
- " *.uri Value(ConstantData)\n"
- " +.uri\n"
- " =.uri\n"
- " *.version Object(Version)\n"
- " +.version\n"
- " *.majorVersion Value(ConstantData)\n"
- " +.majorVersion\n"
- " =.majorVersion\n"
- " *.minorVersion Value(ConstantData)\n"
- " +.minorVersion\n"
- " =.minorVersion\n"
- " *.isLatest Value(ConstantData)\n"
- " +.isLatest\n"
- " =.isLatest\n"
- " *.isValid Value(ConstantData)\n"
- " +.isValid\n"
- " =.isValid\n"
- " *.stringValue Value(ConstantData)\n"
- " +.stringValue\n"
- " =.stringValue\n"
- " =.version\n"
- " *.comments Object(RegionComments)\n"
- " +.comments\n"
- " =.comments\n"
- " =[4]\n"
- "=\n"));
- }
-
- // ### DomKind
- // any DomItem belongs to 5 basic types
-
- // 1. Object (a C++ object)
- QCOMPARE(qmlFile.domKind(), DomKind::Object);
- // The underlying type of the c++ object can be found with .internalKind()
- QCOMPARE(qmlFile.internalKind(), DomType::QmlFile);
- // .initernalKindStr() is a convenience string version of it
- QCOMPARE(qmlFile.internalKindStr(), u"QmlFile");
- // the object attributes (fields) can be reached using .field(u"filedName")
- // normally one should not use a string, but the Fields:: constant
- DomItem qmlFile2 = tFile.field(Fields::currentItem);
- // all the available fields can be listed via fields()
- // qDebug() << "The" << qmlObj.internalKindStr() << "at" << qmlObj.canonicalPath()
- // << "has the following fields:" << qmlObj.fields();
- // we can access the underlying C++ object with as<>
- // if (const QmlFile *qmlFilePtr = qmlFile.as<QmlFile>())
- // qDebug() << "The QmlFile lives at the address" << qmlFilePtr;
- //// We can get the shared pointer of the owner type (which for the file is the QmlFile
- /// itself
- // if (std::shared_ptr<QmlFile> qmlFilePtr = qmlFile.ownerAs<QmlFile>())
- // qDebug() << "QmlFile uses shared pointers as ownership method, the underlying
- // address "
- // "is the same"
- // << qmlFilePtr.get();
-
- // 2. a (Cbor-) Value, i.e a string, number,...
- DomItem fPath = qmlFile.field(Fields::canonicalFilePath);
- QCOMPARE(fPath.domKind(), DomKind::Value);
- // the Cbor representation of a value can be extracted with .value(), and in this case
- // we can then call toString
- // qDebug() << "The filePath DomItem is " << fPath << " and it still 'knows' its path "
- // << fPath.canonicalPath() << " but can have it also as value:" <<
- // fPath.value()
- // << "or even better as string." <<
- // fPath.value().toString(QLatin1String("*none*"));
- // a DomItem might have a valid value() even if it is not of type DomKind::Value, indeed
- // CBor maps and lists are mapped to DomKind::Map and DomKind::List, and can be
- // traversed thought that but also have a valid value().
-
- // 3. a list
- QCOMPARE(imports.domKind(), DomKind::List);
- // the number of elements can be sound with .indexes() and with .index(n) we access each
- // element
- // qDebug() << "We have " << imports.indexes() << " imports, and the first is "
- // << imports.index(0);
- // If we want to just loop on the elements .values() is the most convenient way
- // technically values *always* works even for objects and maps, iterating on the values
- // for (DomItem import : imports.values()) {
- // if (const Import *importPtr = import.as<Import>()) {
- // if (importPtr->implicit)
- // qDebug() << importPtr->uri << importPtr->version.stringValue();
- // }
- //}
-
- // 4. a map
- DomItem bindings = qmlObj.field(Fields::bindings);
- QCOMPARE(bindings.domKind(), DomKind::Map);
- // The keys of the map can be reached either with .keys() or .sortedKeys(), each element
- // with .key(k)
- // qDebug() << "bindings";
- // for (QString k : bindings.sortedKeys()) {
- // for (DomItem b : bindings.key(k).values()) {
- // qDebug() << k << ":" << b;
- // }
- //}
-
- // 5 The empty element
- DomItem empty;
- QCOMPARE(empty.domKind(), DomKind::Empty);
- // The empty element is the only DomItem that casted to bool returns false, so checking
- // for it can be just an implicit cast to bool
- QVERIFY(bindings && !empty);
- // the empty element supports all the previus operations so that one can traverse a non
- // existing path without checking at every element, but only check the result
- DomItem nonExisting = qmlFile.field(u"no-existing").key(u"a").index(0);
- QVERIFY(!nonExisting);
-
- // the index operator [] can be used instead of .index/.key/.field, it might be slightly
- // less efficient but works
-
- // find type
- // access type
-
- // ### write out
- // it is possible to write out a qmlFile (actually also parts of it), which will
- // automatically reformat it
- QString reformattedFilePath =
- QDir(QDir::tempPath())
- .filePath(QFileInfo(testFilePath).baseName() + QLatin1String(".qml"));
- DomItem newFile = qmlFile.writeOut(reformattedFilePath);
- // qDebug() << "reformatted written at " << reformattedFilePath;
-
- // ## Jumping around
- // ### Generic Methods
- // from a DomItem you do no have just deeper in the tree, you can also go up the
- // hierarch toward the root .container() just goes up one step in the canonicalPath of
- // the object
- QCOMPARE(imports, firstImport.container());
- // .containingObject() goes up to the containing DomKind::Object, skipping over all Maps
- // and Lists
- QCOMPARE(qmlFile, firstImport.containingObject());
- // .owner() returns the shared pointer based "owner" object, qmlFile and
- // ScriptExpression are owningItems
- QCOMPARE(qmlFile, bindings.owner());
- // .top() goes to the top of the tree, i.e the environment (or the universe)
- QCOMPARE(env, bindings.top());
- // environment is normally the same as top, but making sure it is a actually a
- // DomEnvironment
- QCOMPARE(env, bindings.environment());
- // the universe is a cache of loaded files which for each file keeps two versions: the
- // latest and the latest valid it can be reached with .universe(), from the universe you
- // cannot get back to the environment.
- QCOMPARE(env.universe().internalKind(), DomType::DomUniverse);
-
- // ## QML Oriented Methods
- // The Dom model is not for generic json-like structures, so there are methods tailored
- // for Qml and its structure The methods can succeed if there is a clearly defined
- // unique result. sometime there is an obivious, but not necessarily unique choice
- // (tipically going up the hierarchy), for example given a qml file the obvious choice
- // for a component is the root component, but the file might contain other inline
- // components, and for an object with different version exposed (C++ property
- // versioning) the latest version is the natural choice, but other might be available.
- // In these case passing GoTo::MostLikely as argument makes the method to this obivious
- // choice (or possibly even only choice if no other versions/components are actually
- // defined), instead of refusing any potentially ambiguous situation and returning the
- // empty element.
-
- // .fileObject() goes to the object representing the whole file
- // (from either the external object returned by load or from inside the file)
- DomItem fileObject = tFile.fileObject();
- DomItem fileObject2 = imports.fileObject();
- QCOMPARE(fileObject, fileObject2);
- QCOMPARE(fileObject.internalKind(), DomType::QmlFile);
- // .component() goes to the component object.
- QCOMPARE(qmlObj.component(), qmlFile.component(GoTo::MostLikely));
- // .pragmas gives access to the pragmas of the current component
- QCOMPARE(qmlFile.pragmas(), qmlFile.field(Fields::pragmas));
-
- // QmlObject
- // QmlObject if the main to represent the type information (methods, bindings,
- // properties,...) of qml. Please note that QmlObject -> component operation is
- // potentially lossy, when multiple version are exposed, so we represent a type through
- // its root object, not through a component.
-
- // .qmlObject() goes to the current QmlObject
- QCOMPARE(qmlObj, bindings.qmlObject());
-
- // Given the centrality of QmlObject several of its attributes have convenience methods
- // to access them:
-
- // .children() makes subObjects contained inside a QmlObject accessible
- // note that it is possible to add objects also by directly binding the children or data
- // attribute, those children are not listed here, this accesses only those listed inside
- // the QmlObject
- QCOMPARE(qmlObj.children(), qmlObj.field(Fields::children));
- DomItem subObj0 = qmlObj.children().index(0);
- // .child(<i>) is a shortcut for .children.index(<i>)
- QCOMPARE(subObj0, qmlObj.child(0));
- // rootQmlObject goes to the root qmlObject (unless one reaches an empty element)
- QVERIFY(bool(subObj0));
- QCOMPARE(subObj0.rootQmlObject(), qmlObj);
- // .bindings() returns the bindings defined in the current object
- QCOMPARE(bindings, qmlObj.bindings());
- DomItem mCompObj = qmlObj.child(0)
- .child(0)
- .bindings()
- .key(u"delegate")
- .index(0)
- .field(Fields::value)
- .child(1);
- // .methods() gives methods definitions and signals
- DomItem methods = mCompObj.methods();
- // qDebug() << "mCompObj methods:";
- for (QString methodName : methods.sortedKeys()) {
- for (DomItem method : methods.key(methodName).values()) {
- if (const MethodInfo *methodPtr = method.as<MethodInfo>()) {
- QCOMPARE(methodName, methodPtr->name);
- // qDebug() << " " << methodPtr->name << methodPtr->methodType;
- }
- }
- }
- // qDebug() << "mCompObj propertyDefs:";
- // .propertyDefs() returns the properties defined in the current object
- DomItem pDefs = mCompObj.propertyDefs();
- for (QString pDefName : pDefs.sortedKeys()) {
- for (DomItem pDef : pDefs.key(pDefName).values()) {
- if (const PropertyDefinition *pDefPtr = pDef.as<PropertyDefinition>()) {
- QCOMPARE(pDefName, pDefPtr->name);
- // qDebug() << " " << pDefPtr->name << pDefPtr->typeName;
- }
- }
- }
- // binding and property definitions are about the ones defined in the current object
- // often one is interested also to the inherited properties.
- // Here PropertyInfo helps, it list all the definitions and bindings for a given
- // property in the inheritance order (local definitions, parent definitions, parent
- // parent definitions,...) .propertyInfos() gives access in the usual way (through a
- // DomItem)
- DomItem propertyInfos = mCompObj.propertyInfos();
- // .propertyInfoWithName(<name>) directly accesses one
- PropertyInfo pInfo = mCompObj.propertyInfoWithName(QStringLiteral(u"a"));
- // qDebug() << "bindings" << pInfo.bindings;
- // .propertyInfoNames() gives the names of the properties
- QCOMPARE(propertyInfos.keys(), mCompObj.propertyInfoNames());
-
- // .globalScope() goes to the globa scope object
- QCOMPARE(qmlObj.globalScope().internalKind(), DomType::GlobalScope);
- // and scope to the containing scope
- QCOMPARE(bindings.scope(), qmlObj);
- }
- // mutate & edit
- {
- // DomItem handles read-only access, but if one wants to change something it cannot be
- // used. MutableDomItem can be initialized with a DomItem, and provides also the methods
- // to modify the item. It keeps the OwningItem and the path to the current item.
- // Mutability can invalidate pointers to non owning items (and thus DomItem).
- // For this reason one should not modify something that other code can have a DomItem
- // pointer to, the best practice is to make shared object immutable and never change
- // them. One should modify only a copy that is used only by a single thread, and do not
- // shared untils all modifications are done. A MutableItem stays valid (or becomes
- // Empty), but stays safe to use
- //
- // Assuming one guarantees that editing is ok, doing it in practice is just about using
- // MutableDomItem instead of DomItem
- // It is possible to simply initialize a mutable item with a DomItem
- DomItem origFile = tFile.fileObject();
- MutableDomItem myFile0(origFile);
- // Normally it is better to have a separate environment. Is possible to avoid re-reading
- // the files already read by sharing the Universe between two environments.
- // But normally it is better and just as safe to work on a copy, so that one can be sure
- // that no DomItem is kept by other code gets invalidated. The .makeCopy creates a deep
- // copy, and by default (DomItem::CopyOption::EnvConnected) creates an environment which
- // to takes all non local elements from the current environment (its parent environment)
- // but replaces the file object with the copy. When finished one can replace the file
- // object of the parent with the new one using .commitToBase().
- MutableDomItem myFile = origFile.makeCopy();
- QVERIFY(myFile.ownerAs<QmlFile>()
- && myFile.ownerAs<QmlFile>() != myFile0.ownerAs<QmlFile>());
- QVERIFY(myFile.environment().ownerAs<DomEnvironment>()
- && myFile.environment().ownerAs<DomEnvironment>()
- != myFile0.environment().ownerAs<DomEnvironment>());
- // we can check that the two files are really identical (.item() give back the DomItem
- // of a MutableDomItem
- Q_ASSERT(domCompareStrList(origFile, myFile, FieldFilter::compareFilter()).isEmpty());
- // MutableDomItem has the same methods as DomItem
- MutableDomItem qmlObj = myFile.qmlObject(GoTo::MostLikely);
- MutableDomItem qmlObj2 = myFile.field(Fields::components)
- .key(QString())
- .index(0)
- .field(Fields::objects)
- .index(0);
- QVERIFY(bool(qmlObj));
- QCOMPARE(qmlObj, qmlObj2);
- // qDebug() << "mutable qmlObj has canonicalPath " << qmlObj.canonicalPath();
- // but it adds methods to add
- // * new PropertyDefinitions
- PropertyDefinition b;
- b.name = QLatin1String("xx");
- b.typeName = QLatin1String("int");
- // if we make t true we also have to give a value...
- MutableDomItem addedPDef = qmlObj.addPropertyDef(b);
- // qDebug() << "added property definition at:" << addedPDef.pathFromOwner();
- // * new bindings
- MutableDomItem addedBinding0 = qmlObj.addBinding(
- Binding("height",
- std::shared_ptr<ScriptExpression>(new ScriptExpression(
- QStringLiteral(u"243"),
- ScriptExpression::ExpressionType::BindingExpression))));
- // by default addBinding, addPropertyDef and addMethod have the AddOption::Override
- // to make it more difficult to create invalid documents, so that only the
- // following binding remains (where we use the convenience constructor that constucts
- // the ScriptExpression internally
- MutableDomItem addedBinding =
- qmlObj.addBinding(Binding("height", QStringLiteral(u"242")));
- // qDebug() << "added binding at:" << addedBinding.pathFromOwner();
- // * new methods
- MethodInfo mInfo;
- mInfo.name = QLatin1String("foo2");
- MethodParameter param;
- param.name = QLatin1String("x");
- mInfo.parameters.append(param);
- mInfo.setCode(QLatin1String("return 4*10+2 - x"));
- // we can change the added binding
- addedBinding.setCode(QLatin1String("245"));
- MutableDomItem addedMethod = qmlObj.addMethod(mInfo);
- // qDebug() << "added method at:" << addedMethod.pathFromOwner();
- // * new QmlObjects
- QmlObject subObj;
- subObj.setName(QLatin1String("Item"));
- MutableDomItem addedSubObj = qmlObj.addChild(subObj);
- // qDebug() << "added subObject at:" << addedMethod.pathFromOwner();
- // It is possible to modify the content of objects, using the mutableAs method
- if (PropertyDefinition *addedPDefPtr = addedPDef.mutableAs<PropertyDefinition>()) {
- addedPDefPtr->isRequired = true;
- }
- MutableDomItem firstChild = qmlObj.child(0);
- // qDebug() << "firstChild:" << firstChild;
- // It is possible remove objects
- if (QmlObject *qmlObjPtr = qmlObj.mutableAs<QmlObject>()) {
- QList<QmlObject> children = qmlObjPtr->children();
- children.removeAt(0);
- qmlObjPtr->setChildren(children);
- }
- // But as MutableDomItem does not keep the identity, just the same position, the
- // addedSubObj becomes invalid (and firstChild changes)
- // qDebug() << "after removal firstChild:" << firstChild;
- // qDebug() << "addedSubObj becomes invalid:" << addedSubObj;
- // qDebug() << "But the last object is the added one:"
- // << qmlObj.child(qmlObj.children().indexes() - 1);
-
- // now origFile are different
- Q_ASSERT(!domCompareStrList(origFile, myFile, FieldFilter::compareFilter()).isEmpty());
- // and we can look at the places where they differ
- // qDebug().noquote().nospace()
- // << "Edits introduced the following diffs (ignoring file locations"
- // << " and thus whitespace/reformatting changes):\n"
- // << domCompareStrList(origFile, myFile, FieldFilter::noLocationFilter(),
- // DomCompareStrList::AllDiffs)
- // .join(QString());
-
- QString reformattedFilePath =
- QDir(QDir::tempPath())
- .filePath(QStringLiteral(u"edited") + QFileInfo(testFilePath).baseName()
- + QLatin1String(".qml"));
- Q_ASSERT(myFile.as<QmlFile>()
- && myFile.as<QmlFile>() == myFile.fileObject().as<QmlFile>());
- MutableDomItem reformattedEditedFile = myFile.writeOut(reformattedFilePath);
- // the reformatted edited file might be different from the edited file
- // but the differences are just in file location/formatting
- Q_ASSERT(domCompareStrList(myFile, reformattedEditedFile,
- FieldFilter::noLocationFilter())
- .isEmpty());
-
- // qDebug() << "The edited file was written at " << reformattedFilePath;
- QString dumpFilePath = QDir(QDir::tempPath())
- .filePath(QStringLiteral(u"edited0")
- + QFileInfo(testFilePath).baseName()
- + QLatin1String(".dump.json"));
- myFile.dump(dumpFilePath);
- // qDebug() << "The non reformatted edited file was dumped at " << dumpFilePath;
- QString reformattedDumpFilePath =
- QDir(QDir::tempPath())
- .filePath(QStringLiteral(u"edited") + QFileInfo(testFilePath).baseName()
- + QLatin1String(".dump.json"));
- reformattedEditedFile.dump(reformattedDumpFilePath);
- // qDebug() << "The edited file was dumped at " << reformattedDumpFilePath;
- // The top environment still contains the original loaded file
- Q_ASSERT(origFile.ownerAs<QmlFile>() != reformattedEditedFile.ownerAs<QmlFile>());
- Q_ASSERT(tFile.fileObject().refreshed().ownerAs<QmlFile>());
- QCOMPARE(tFile.fileObject().refreshed().ownerAs<QmlFile>(),
- origFile.ownerAs<QmlFile>());
- QCOMPARE(tFile.fileObject().ownerAs<QmlFile>(), origFile.ownerAs<QmlFile>());
- Q_ASSERT(tFile.fileObject().refreshed().ownerAs<QmlFile>()
- != reformattedEditedFile.ownerAs<QmlFile>());
- // we can commit the reformatted file
- if (!reformattedEditedFile.commitToBase()) {
- qWarning() << "No reformatted file to commit";
- }
- // myFile might not be the same (If and updated check is requested, not the case here)
- if (myFile.ownerAs<QmlFile>() != reformattedEditedFile.ownerAs<QmlFile>()
- && !myFile.commitToBase()) {
- qWarning() << "Could not commit edited file";
- }
- // but refreshing it (looking up its canonical path) we always find the updated file
- QCOMPARE(myFile.refreshed().ownerAs<QmlFile>(),
- reformattedEditedFile.ownerAs<QmlFile>());
- Q_ASSERT(tFile.fileObject().refreshed().ownerAs<QmlFile>()
- == reformattedEditedFile.ownerAs<QmlFile>());
- }
- }
-};
-
-} // Dom
-} // QQmlJS
-QT_END_NAMESPACE
diff --git a/tests/auto/qmldom/stringdumper/CMakeLists.txt b/tests/auto/qmldom/stringdumper/CMakeLists.txt
index a67041d433..2b09281302 100644
--- a/tests/auto/qmldom/stringdumper/CMakeLists.txt
+++ b/tests/auto/qmldom/stringdumper/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmldomstringdumper Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmldomstringdumper LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qmldomstringdumper
SOURCES
tst_qmldomstringdumper.cpp tst_qmldomstringdumper.h
diff --git a/tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.cpp b/tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.cpp
index bc25070838..fab3bc5be8 100644
--- a/tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.cpp
+++ b/tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_qmldomstringdumper.h"
QTEST_MAIN(QQmlJS::Dom::TestStringDumper)
diff --git a/tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.h b/tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.h
index 9d72b589c1..28e844db73 100644
--- a/tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.h
+++ b/tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.h
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TST_QMLDOMSTRINGDUMPER_H
#define TST_QMLDOMSTRINGDUMPER_H
diff --git a/tests/auto/qmlls/CMakeLists.txt b/tests/auto/qmlls/CMakeLists.txt
index bcb8d121d3..daf7d64cd4 100644
--- a/tests/auto/qmlls/CMakeLists.txt
+++ b/tests/auto/qmlls/CMakeLists.txt
@@ -1,8 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-if (TARGET Qt::LanguageServerPrivate)
- add_subdirectory(qmlls)
+if (TARGET Qt::QmlLSPrivate)
add_subdirectory(lifecycle)
- add_subdirectory(completions)
+ add_subdirectory(utils)
+ add_subdirectory(qqmlcodemodel)
+ add_subdirectory(qmlls)
+ add_subdirectory(modules)
+ add_subdirectory(cli)
endif()
+
diff --git a/tests/auto/qmlls/cli/CMakeLists.txt b/tests/auto/qmlls/cli/CMakeLists.txt
new file mode 100644
index 0000000000..1ac8016f66
--- /dev/null
+++ b/tests/auto/qmlls/cli/CMakeLists.txt
@@ -0,0 +1,34 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlls_modules LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+file(GLOB_RECURSE test_data_glob
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ data)
+
+qt_internal_add_test(tst_qmlls_cli
+ SOURCES
+ tst_qmlls_cli.cpp
+ tst_qmlls_cli.h
+ DEFINES
+ QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+ LIBRARIES
+ Qt::Core
+ Qt::QmlDomPrivate
+ Qt::LanguageServerPrivate
+ Qt::Test
+ Qt::QuickTestUtilsPrivate
+ Qt::QmlLSPrivate
+ TESTDATA ${test_data}
+)
+
+if (TARGET qmlls)
+ # standalone test builds do not know the qmlls target
+ # but if TARGET qmlls is known it should be built before this test
+ add_dependencies(tst_qmlls_cli qmlls)
+endif()
diff --git a/tests/auto/qmlls/cli/data/ImportPath1/SomeModule/A.qml b/tests/auto/qmlls/cli/data/ImportPath1/SomeModule/A.qml
new file mode 100644
index 0000000000..5468cae5e1
--- /dev/null
+++ b/tests/auto/qmlls/cli/data/ImportPath1/SomeModule/A.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property string helloSomeModule
+}
diff --git a/tests/auto/qmlls/cli/data/ImportPath1/SomeModule/qmldir b/tests/auto/qmlls/cli/data/ImportPath1/SomeModule/qmldir
new file mode 100644
index 0000000000..6e8de8bc53
--- /dev/null
+++ b/tests/auto/qmlls/cli/data/ImportPath1/SomeModule/qmldir
@@ -0,0 +1,2 @@
+module SomeModule
+A 254.0 A.qml
diff --git a/tests/auto/qmlls/cli/data/ImportPath2/AnotherModule/B.qml b/tests/auto/qmlls/cli/data/ImportPath2/AnotherModule/B.qml
new file mode 100644
index 0000000000..33af59274a
--- /dev/null
+++ b/tests/auto/qmlls/cli/data/ImportPath2/AnotherModule/B.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property string helloAnotherModule
+}
diff --git a/tests/auto/qmlls/cli/data/ImportPath2/AnotherModule/qmldir b/tests/auto/qmlls/cli/data/ImportPath2/AnotherModule/qmldir
new file mode 100644
index 0000000000..aa4ef803b1
--- /dev/null
+++ b/tests/auto/qmlls/cli/data/ImportPath2/AnotherModule/qmldir
@@ -0,0 +1,2 @@
+module AnotherModule
+B 254.0 B.qml
diff --git a/tests/auto/qmlls/cli/data/sourceFolder/ImportFromBothPaths.qml b/tests/auto/qmlls/cli/data/sourceFolder/ImportFromBothPaths.qml
new file mode 100644
index 0000000000..4a2775ce29
--- /dev/null
+++ b/tests/auto/qmlls/cli/data/sourceFolder/ImportFromBothPaths.qml
@@ -0,0 +1,10 @@
+import SomeModule
+import AnotherModule
+
+A {
+ helloSomeModule: "hello!"
+
+ B {
+ helloAnotherModule: "World!"
+ }
+} \ No newline at end of file
diff --git a/tests/auto/qmlls/cli/data/sourceFolder/ImportFromImportPath1.qml b/tests/auto/qmlls/cli/data/sourceFolder/ImportFromImportPath1.qml
new file mode 100644
index 0000000000..3417701352
--- /dev/null
+++ b/tests/auto/qmlls/cli/data/sourceFolder/ImportFromImportPath1.qml
@@ -0,0 +1,5 @@
+import SomeModule
+
+A {
+ helloSomeModule: "hello!"
+}
diff --git a/tests/auto/qmlls/cli/tst_qmlls_cli.cpp b/tests/auto/qmlls/cli/tst_qmlls_cli.cpp
new file mode 100644
index 0000000000..344ed48e64
--- /dev/null
+++ b/tests/auto/qmlls/cli/tst_qmlls_cli.cpp
@@ -0,0 +1,309 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "tst_qmlls_cli.h"
+
+using namespace Qt::StringLiterals;
+
+void tst_qmlls_cli::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+
+ m_qmllsPath = QLibraryInfo::path(QLibraryInfo::BinariesPath) + QLatin1String("/qmlls");
+#ifdef Q_OS_WIN
+ m_qmllsPath += QLatin1String(".exe");
+#endif
+ // allow overriding of the executable, to be able to use a qmlEcho script (as described in
+ // qmllanguageservertool.cpp)
+ m_qmllsPath = qEnvironmentVariable("QMLLS", m_qmllsPath);
+ m_server.setProgram(m_qmllsPath);
+}
+
+void tst_qmlls_cli::cleanup()
+{
+ m_server.closeWriteChannel();
+ m_server.waitForFinished();
+ QTRY_COMPARE(m_server.state(), QProcess::NotRunning);
+ QCOMPARE(m_server.exitStatus(), QProcess::NormalExit);
+}
+
+// Helper structs to avoid confusions between expected and unexpected messages and between expected
+// and unexpected diagnostics.
+struct ExpectedMessages : public QStringList
+{
+ using QStringList::QStringList;
+};
+struct UnexpectedMessages : public QStringList
+{
+ using QStringList::QStringList;
+};
+struct ExpectedDiagnostics : public QStringList
+{
+ using QStringList::QStringList;
+};
+struct UnexpectedDiagnostics : public QStringList
+{
+ using QStringList::QStringList;
+};
+
+// Extra environment variables to be added to qmlls's environment.
+struct Environment : public QList<QPair<QString, QString>>
+{
+ using QList<QPair<QString, QString>>::QList;
+};
+
+void tst_qmlls_cli::warnings_data()
+{
+ QTest::addColumn<QStringList>("args");
+ QTest::addColumn<Environment>("environment");
+ QTest::addColumn<QString>("filePath");
+ // messages are printed to stderr and not shown in editor:
+ QTest::addColumn<ExpectedMessages>("expectedMessages");
+ QTest::addColumn<UnexpectedMessages>("unexpectedMessages");
+ // diagnostics are passed via LSP to be shown in editor:
+ QTest::addColumn<ExpectedDiagnostics>("expectedDiagnostics");
+ QTest::addColumn<UnexpectedDiagnostics>("unexpectedDiagnostics");
+
+ const Environment defaultEnv;
+ const QString dir1 = testFile(u"ImportPath1"_s);
+ const QString dir2 = testFile(u"ImportPath2"_s);
+ const QString notDir = testFile(u"ImportPath1/SomeModule/qmldir"_s);
+ const QString wrongDir = testFile(u"ImportPathInexistent"_s);
+
+ const QString fileImportingDir1 = testFile(u"sourceFolder/ImportFromImportPath1.qml"_s);
+ const QString fileImportingBothDirs = testFile(u"sourceFolder/ImportFromBothPaths.qml"_s);
+
+ const QString importWarningDir1 = u"Warnings occurred while importing module \"SomeModule\""_s;
+ const QString importWarningDir2 = u"Warnings occurred while importing module \"AnotherModule\""_s;
+
+ const UnexpectedMessages noUnexpectedMessages;
+ const QString warnAboutQmllsIniFiles{
+ u"Using the build directories found in the .qmlls.ini file. Your build folder might not be found if no .qmlls.ini files are present in the root source folder."_s
+ };
+
+ QTest::addRow("2-build-dirs")
+ << QStringList{ u"--build-dir"_s, dir1, u"-b"_s, dir2 } << defaultEnv
+ << fileImportingDir1
+ << ExpectedMessages{ u"Using build directories passed by -b: \"%1\", \"%2\"."_s.arg(
+ dir1, dir2) }
+ << UnexpectedMessages{ warnAboutQmllsIniFiles } << ExpectedDiagnostics{}
+ << UnexpectedDiagnostics{ importWarningDir1 };
+
+ QTest::addRow("build-dir-not-dir")
+ << QStringList{ u"--build-dir"_s, notDir, u"-b"_s, dir2 } << defaultEnv
+ << fileImportingBothDirs
+ << ExpectedMessages{ u"Argument \"%1\" passed to -b is not a directory."_s.arg(notDir) }
+ << UnexpectedMessages{ warnAboutQmllsIniFiles }
+ << ExpectedDiagnostics{ importWarningDir1 }
+ << UnexpectedDiagnostics{ importWarningDir2 };
+
+ QTest::addRow("build-dir-not-existing")
+ << QStringList{ u"--build-dir"_s, wrongDir, u"-b"_s, dir2 } << defaultEnv
+ << fileImportingBothDirs
+ << ExpectedMessages{ u"Argument \"%1\" passed to -b does not exist."_s.arg(wrongDir) }
+ << UnexpectedMessages{ warnAboutQmllsIniFiles } << ExpectedDiagnostics{}
+ << UnexpectedDiagnostics{};
+
+ QTest::addRow("build-dir-from-environment")
+ << QStringList{}
+ << Environment{ { u"QMLLS_BUILD_DIRS"_s,
+ u"%1%2%3"_s.arg(dir1, QDir::listSeparator(), dir2) } }
+ << fileImportingBothDirs
+ << ExpectedMessages{ u"Using build directories passed from environment variable \"QMLLS_BUILD_DIRS\": \"%1\", \"%2\"."_s
+ .arg(dir1, dir2) }
+ << UnexpectedMessages{ warnAboutQmllsIniFiles } << ExpectedDiagnostics{}
+ << UnexpectedDiagnostics{ importWarningDir1, importWarningDir2 };
+
+ QTest::addRow("build-dir-from-environment-not-existing")
+ << QStringList{}
+ << Environment{ { u"QMLLS_BUILD_DIRS"_s,
+ QStringList{ dir1, wrongDir, notDir }.join(QDir::listSeparator()) } }
+ << fileImportingDir1
+ << ExpectedMessages{ u"Argument \"%1\" from environment variable \"QMLLS_BUILD_DIRS\" does not exist."_s
+ .arg(wrongDir),
+ u"Argument \"%1\" from environment variable \"QMLLS_BUILD_DIRS\" is not a directory."_s
+ .arg(notDir) }
+ << UnexpectedMessages{ warnAboutQmllsIniFiles } << ExpectedDiagnostics{}
+ << UnexpectedDiagnostics{ importWarningDir1, importWarningDir2 };
+
+ QTest::addRow("ignore-environment-with-option")
+ << QStringList{ u"--build-dir"_s, dir1 }
+ << Environment{ { u"QMLLS_BUILD_DIRS"_s, dir2 } } << fileImportingBothDirs
+ << ExpectedMessages{ u"Using build directories passed by -b: \"%1\"."_s.arg(dir1) }
+ << UnexpectedMessages{ dir2, warnAboutQmllsIniFiles }
+ << ExpectedDiagnostics{ importWarningDir2 }
+ << UnexpectedDiagnostics{ importWarningDir1 };
+
+ QTest::addRow("loadFromConfigFile")
+ << QStringList{} << Environment{} << fileImportingDir1
+ << ExpectedMessages{ warnAboutQmllsIniFiles } << UnexpectedMessages{}
+ << ExpectedDiagnostics{ importWarningDir1 } << UnexpectedDiagnostics{};
+
+ QTest::addRow("2-import-paths")
+ << QStringList{ u"-I"_s, dir1, u"-I"_s, dir2 } << Environment{} << fileImportingBothDirs
+ << ExpectedMessages{ u"Using import directories passed by -I: \"%1\", \"%2\"."_s.arg(
+ dir1, dir2) }
+ << UnexpectedMessages{} << ExpectedDiagnostics{}
+ << UnexpectedDiagnostics{ importWarningDir1, importWarningDir2 };
+
+ QTest::addRow("import-paths-ignore-env")
+ << QStringList{ u"-I"_s, dir1, } << Environment{ { u"QML_IMPORT_PATH"_s, dir2 } }
+ << fileImportingBothDirs
+ << ExpectedMessages{ u"Using import directories passed by -I: \"%1\"."_s.arg(dir1) }
+ << UnexpectedMessages{ u"Using import directories passed from environment variable \"QML_IMPORT_PATH\": \"%1\"."_s.arg(dir2)}
+ << ExpectedDiagnostics{importWarningDir2} << UnexpectedDiagnostics{ importWarningDir1 };
+
+ QTest::addRow("2-import-paths-mixed")
+ << QStringList{ u"-I"_s, dir1, u"-E"_s }
+ << Environment{ { u"QML_IMPORT_PATH"_s, dir2 } } << fileImportingBothDirs
+ << ExpectedMessages{ u"Using import directories passed by -I: \"%1\"."_s.arg(dir1),
+ u"Using import directories passed from environment variable \"QML_IMPORT_PATH\": \"%1\"."_s
+ .arg(dir2) }
+ << UnexpectedMessages{} << ExpectedDiagnostics{}
+ << UnexpectedDiagnostics{ importWarningDir1, importWarningDir2 };
+
+ QTest::addRow("2-import-paths-deprecated")
+ << QStringList{ u"-I"_s, dir1, u"-E"_s }
+ << Environment{ { u"QML2_IMPORT_PATH"_s, dir2 } } << fileImportingBothDirs
+ << ExpectedMessages{ u"Using import directories passed by -I: \"%1\"."_s.arg(dir1),
+ u"Using import directories passed from the deprecated environment variable \"QML2_IMPORT_PATH\": \"%1\"."_s
+ .arg(dir2) }
+ << UnexpectedMessages{} << ExpectedDiagnostics{}
+ << UnexpectedDiagnostics{ importWarningDir1, importWarningDir2 };
+}
+
+auto tst_qmlls_cli::startServerRAII()
+{
+ startServerImpl();
+ return qScopeGuard([this]() { this->stopServerImpl(); });
+}
+
+void tst_qmlls_cli::startServerImpl()
+{
+ m_protocol = std::make_unique<QLanguageServerProtocol>(
+ [this](const QByteArray &data) { m_server.write(data); });
+
+ connect(&m_server, &QProcess::readyReadStandardOutput, this, [this]() {
+ QByteArray data = m_server.readAllStandardOutput();
+ m_protocol->receiveData(data);
+ });
+
+ m_server.start();
+
+ QLspSpecification::InitializeParams clientInfo;
+ clientInfo.rootUri = QUrl::fromLocalFile(dataDirectory() + "/default").toString().toUtf8();
+
+ QLspSpecification::TextDocumentClientCapabilities tDoc;
+ tDoc.typeDefinition = QLspSpecification::TypeDefinitionClientCapabilities{ false, false };
+
+ QLspSpecification::PublishDiagnosticsClientCapabilities pDiag;
+ tDoc.publishDiagnostics = pDiag;
+ pDiag.versionSupport = true;
+ clientInfo.capabilities.textDocument = tDoc;
+ bool didInit = false;
+ m_protocol->requestInitialize(
+ clientInfo, [this, &didInit](const QLspSpecification::InitializeResult &serverInfo) {
+ Q_UNUSED(serverInfo);
+ m_protocol->notifyInitialized(QLspSpecification::InitializedParams());
+ didInit = true;
+ });
+ QTRY_COMPARE_WITH_TIMEOUT(didInit, true, 10000);
+}
+
+void tst_qmlls_cli::stopServerImpl()
+{
+ m_server.closeWriteChannel();
+ m_server.waitForFinished();
+ QTRY_COMPARE(m_server.state(), QProcess::NotRunning);
+ QCOMPARE(m_server.exitStatus(), QProcess::NormalExit);
+}
+
+void tst_qmlls_cli::warnings()
+{
+ QFETCH(QStringList, args);
+ QFETCH(Environment, environment);
+ QFETCH(ExpectedMessages, expectedMessages);
+ QFETCH(UnexpectedMessages, unexpectedMessages);
+ QFETCH(QString, filePath);
+ QFETCH(ExpectedDiagnostics, expectedDiagnostics);
+ QFETCH(UnexpectedDiagnostics, unexpectedDiagnostics);
+
+ QProcessEnvironment processEnvironment = QProcessEnvironment::systemEnvironment();
+ for (const auto &entry : environment)
+ processEnvironment.insert(entry.first, entry.second);
+ m_server.setProcessEnvironment(processEnvironment);
+ m_server.setArguments(args);
+
+ QList<int> countExpectedMessages(expectedMessages.size(), 0);
+ QList<int> countUnexpectedMessages(unexpectedMessages.size(), 0);
+ QList<int> countExpectedDiagnostics(expectedDiagnostics.size(), 0);
+ QList<int> countUnexpectedDiagnostics(unexpectedDiagnostics.size(), 0);
+
+ auto guard = qScopeGuard([this]() {
+ // note: the lambda used in the "connect"-call references local variables, so disconnect the
+ // lambda via QScopedGuard to avoid its captured references to dangle
+ disconnect(&m_server, &QProcess::readyReadStandardOutput, nullptr, nullptr);
+ });
+ connect(&m_server, &QProcess::readyReadStandardError, this,
+ [this, &expectedMessages, &countExpectedMessages, &unexpectedMessages,
+ &countUnexpectedMessages]() {
+ const auto data = QString::fromUtf8(m_server.readAllStandardError());
+ if (data.isEmpty())
+ return;
+
+ for (int i = 0; i < expectedMessages.size(); ++i) {
+ if (data.contains(expectedMessages[i]))
+ ++countExpectedMessages[i];
+ }
+ for (int i = 0; i < unexpectedMessages.size(); ++i) {
+ if (data.contains(unexpectedMessages[i]))
+ ++countUnexpectedMessages[i];
+ }
+ });
+
+ auto guard2 = startServerRAII();
+
+ // each expected message should appear exactly one time
+ QTRY_COMPARE_WITH_TIMEOUT(countExpectedMessages, QList<int>(expectedMessages.size(), 1), 500);
+ // each unexpected message should appear exactly zero times
+ QCOMPARE(countUnexpectedMessages, QList<int>(unexpectedMessages.size(), 0));
+
+ bool diagnosticOk = false;
+ m_protocol->registerPublishDiagnosticsNotificationHandler(
+ [&diagnosticOk, &expectedDiagnostics, &countExpectedDiagnostics, &unexpectedDiagnostics,
+ &countUnexpectedDiagnostics](const QByteArray &,
+ const QLspSpecification::PublishDiagnosticsParams &p) {
+ for (const auto &d : p.diagnostics) {
+ const QString message = QString::fromUtf8(d.message);
+ for (int i = 0; i < expectedDiagnostics.size(); ++i) {
+ if (message.contains(expectedDiagnostics[i]))
+ ++countExpectedDiagnostics[i];
+ }
+ for (int i = 0; i < unexpectedDiagnostics.size(); ++i) {
+ if (message.contains(unexpectedDiagnostics[i]))
+ ++countUnexpectedDiagnostics[i];
+ }
+ }
+ diagnosticOk = true;
+ });
+
+ QFile file(filePath);
+ QVERIFY(file.open(QIODevice::ReadOnly));
+
+ QLspSpecification::DidOpenTextDocumentParams oParams;
+ QLspSpecification::TextDocumentItem textDocument;
+ QByteArray uri = QUrl::fromLocalFile(filePath).toEncoded();
+ textDocument.uri = uri;
+ textDocument.text = file.readAll();
+ oParams.textDocument = textDocument;
+ m_protocol->notifyDidOpenTextDocument(oParams);
+
+ QTRY_VERIFY_WITH_TIMEOUT(diagnosticOk, 3000);
+ // each expected diagnostic should appear exactly one time
+ QCOMPARE(countExpectedDiagnostics, QList<int>(expectedDiagnostics.size(), 1));
+ // each unexpected diagnostic should appear exactly zero times
+ QCOMPARE(countUnexpectedDiagnostics, QList<int>(unexpectedDiagnostics.size(), 0));
+
+}
+
+QTEST_MAIN(tst_qmlls_cli)
diff --git a/tests/auto/qmlls/cli/tst_qmlls_cli.h b/tests/auto/qmlls/cli/tst_qmlls_cli.h
new file mode 100644
index 0000000000..3eab8b5d1b
--- /dev/null
+++ b/tests/auto/qmlls/cli/tst_qmlls_cli.h
@@ -0,0 +1,38 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TST_QMLLS_CLI_H
+#define TST_QMLLS_CLI_H
+
+#include <QtLanguageServer/private/qlanguageserverprotocol_p.h>
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qprocess.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qlibraryinfo.h>
+
+#include <QtTest/qtest.h>
+
+class tst_qmlls_cli: public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_qmlls_cli() : QQmlDataTest(QT_QMLTEST_DATADIR) { }
+ [[nodiscard]] auto startServerRAII();
+ void startServerImpl();
+ void stopServerImpl();
+
+private slots:
+ void initTestCase();
+ void cleanup();
+ void warnings_data();
+ void warnings();
+
+public:
+ QProcess m_server;
+ QString m_qmllsPath;
+ std::unique_ptr<QLanguageServerProtocol> m_protocol;
+};
+
+#endif // TST_QMLLS_CLI_H
diff --git a/tests/auto/qmlls/completions/CMakeLists.txt b/tests/auto/qmlls/completions/CMakeLists.txt
deleted file mode 100644
index 7b9a6111b2..0000000000
--- a/tests/auto/qmlls/completions/CMakeLists.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
-
-file(GLOB_RECURSE test_data_glob
- RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
- data)
-list(APPEND test_data ${test_data_glob})
-
-qt_internal_add_test(tst_qmllscompletions
- SOURCES
- tst_qmllscompletions.cpp
- DEFINES
- QT_DEPRECATED_WARNINGS
- QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
- LIBRARIES
- Qt::Core
- Qt::QmlDomPrivate
- Qt::LanguageServerPrivate
- Qt::Test
- Qt::QuickTestUtilsPrivate
- TESTDATA ${test_data}
-)
-
-qt_internal_extend_target(tst_qmllscompletions CONDITION ANDROID OR IOS
- DEFINES
- QT_QMLTEST_DATADIR=":/domdata"
-)
diff --git a/tests/auto/qmlls/completions/tst_qmllscompletions.cpp b/tests/auto/qmlls/completions/tst_qmllscompletions.cpp
deleted file mode 100644
index e5d955a337..0000000000
--- a/tests/auto/qmlls/completions/tst_qmllscompletions.cpp
+++ /dev/null
@@ -1,500 +0,0 @@
-// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <QtJsonRpc/private/qjsonrpcprotocol_p.h>
-#include <QtLanguageServer/private/qlanguageserverprotocol_p.h>
-#include <QtQuickTestUtils/private/qmlutils_p.h>
-#include <QtCore/private/qduplicatetracker_p.h>
-
-#include <QtCore/qobject.h>
-#include <QtCore/qprocess.h>
-#include <QtCore/qlibraryinfo.h>
-#include <QtCore/qstringlist.h>
-
-#include <QtTest/qtest.h>
-#include "../../../../tools/qmlls/lspcustomtypes.h"
-
-#include <iostream>
-#include <variant>
-
-// Check if QTest already has a QTEST_CHECKED macro
-#ifndef QTEST_CHECKED
-#define QTEST_CHECKED(...) \
-do { \
- __VA_ARGS__; \
- if (QTest::currentTestFailed()) \
- return; \
-} while (false)
-#endif
-
-QT_USE_NAMESPACE
-using namespace Qt::StringLiterals;
-using namespace QLspSpecification;
-
-class tst_QmllsCompletions : public QQmlDataTest
-{
- using ExpectedCompletion = QPair<QString, CompletionItemKind>;
- using ExpectedCompletions = QList<ExpectedCompletion>;
-
- using ExpectedDocumentation = std::tuple<QString, QString, QString>;
- using ExpectedDocumentations = QList<ExpectedDocumentation>;
-
- Q_OBJECT
-public:
- tst_QmllsCompletions();
- void checkCompletions(QByteArray uri, int lineNr, int character, ExpectedCompletions expected,
- QStringList notExpected);
-private slots:
- void initTestCase() final;
- void completions_data();
- void completions();
- void function_documentations_data();
- void function_documentations();
- void buildDir();
- void cleanupTestCase();
-
-private:
- QProcess m_server;
- QLanguageServerProtocol m_protocol;
- QString m_qmllsPath;
- QList<QByteArray> m_uriToClose;
-};
-
-tst_QmllsCompletions::tst_QmllsCompletions()
- : QQmlDataTest(QT_QMLTEST_DATADIR),
- m_protocol([this](const QByteArray &data) { m_server.write(data); })
-{
- connect(&m_server, &QProcess::readyReadStandardOutput, this, [this]() {
- QByteArray data = m_server.readAllStandardOutput();
- m_protocol.receiveData(data);
- });
-
- connect(&m_server, &QProcess::readyReadStandardError, this,
- [this]() {
- QProcess::ProcessChannel tmp = m_server.readChannel();
- m_server.setReadChannel(QProcess::StandardError);
- while (m_server.canReadLine())
- std::cerr << m_server.readLine().constData();
- m_server.setReadChannel(tmp);
- });
-
- m_qmllsPath =
- QLibraryInfo::path(QLibraryInfo::BinariesPath) + QLatin1String("/qmlls");
-#ifdef Q_OS_WIN
- m_qmllsPath += QLatin1String(".exe");
-#endif
- // allow overriding of the executable, to be able to use a qmlEcho script (as described in
- // qmllanguageservertool.cpp)
- m_qmllsPath = qEnvironmentVariable("QMLLS", m_qmllsPath);
- m_server.setProgram(m_qmllsPath);
- m_protocol.registerPublishDiagnosticsNotificationHandler([](const QByteArray &, auto) {
- // ignoring qmlint notifications
- });
-}
-
-void tst_QmllsCompletions::initTestCase()
-{
- QQmlDataTest::initTestCase();
- if (!QFileInfo::exists(m_qmllsPath)) {
- QString message =
- QStringLiteral("qmlls executable not found (looked for %0)").arg(m_qmllsPath);
- QSKIP(qPrintable(message)); // until we add a feature for this we avoid failing here
- }
- m_server.start();
- InitializeParams clientInfo;
- clientInfo.rootUri = QUrl::fromLocalFile(dataDirectory() + "/default").toString().toUtf8();
- TextDocumentClientCapabilities tDoc;
- PublishDiagnosticsClientCapabilities pDiag;
- tDoc.publishDiagnostics = pDiag;
- pDiag.versionSupport = true;
- clientInfo.capabilities.textDocument = tDoc;
- bool didInit = false;
- m_protocol.requestInitialize(clientInfo, [this, &didInit](const InitializeResult &serverInfo) {
- Q_UNUSED(serverInfo);
- m_protocol.notifyInitialized(InitializedParams());
- didInit = true;
- });
- QTRY_COMPARE_WITH_TIMEOUT(didInit, true, 10000);
-
- for (const QString &filePath :
- QStringList({ u"completions/Yyy.qml"_s, u"completions/fromBuildDir.qml"_s })) {
- QFile file(testFile(filePath));
- QVERIFY(file.open(QIODevice::ReadOnly));
- DidOpenTextDocumentParams oParams;
- TextDocumentItem textDocument;
- QByteArray uri = testFileUrl(filePath).toString().toUtf8();
- textDocument.uri = uri;
- textDocument.text = file.readAll();
- oParams.textDocument = textDocument;
- m_protocol.notifyDidOpenTextDocument(oParams);
- m_uriToClose.append(uri);
- }
-}
-
-void tst_QmllsCompletions::completions_data()
-{
- QTest::addColumn<QByteArray>("uri");
- QTest::addColumn<int>("lineNr");
- QTest::addColumn<int>("character");
- QTest::addColumn<ExpectedCompletions>("expected");
- QTest::addColumn<QStringList>("notExpected");
-
- QByteArray uri = testFileUrl("completions/Yyy.qml").toString().toUtf8();
-
- QTest::newRow("objEmptyLine") << uri << 8 << 0
- << ExpectedCompletions({
- { u"Rectangle"_s, CompletionItemKind::Class },
- { u"property"_s, CompletionItemKind::Keyword },
- { u"width"_s, CompletionItemKind::Property },
- { u"function"_s, CompletionItemKind::Keyword },
- })
- << QStringList({ u"QtQuick"_s, u"vector4d"_s });
-
- QTest::newRow("inBindingLabel") << uri << 5 << 9
- << ExpectedCompletions({
- { u"Rectangle"_s, CompletionItemKind::Class },
- { u"property"_s, CompletionItemKind::Keyword },
- { u"width"_s, CompletionItemKind::Property },
- })
- << QStringList({ u"QtQuick"_s, u"vector4d"_s });
-
- QTest::newRow("afterBinding") << uri << 5 << 10
- << ExpectedCompletions({
- { u"Rectangle"_s, CompletionItemKind::Field },
- { u"width"_s, CompletionItemKind::Field },
- { u"vector4d"_s, CompletionItemKind::Field },
- })
- << QStringList({ u"QtQuick"_s, u"property"_s });
-
- // suppress?
- QTest::newRow("afterId") << uri << 4 << 7
- << ExpectedCompletions({
- { u"import"_s, CompletionItemKind::Keyword },
- })
- << QStringList({ u"QtQuick"_s, u"property"_s, u"Rectangle"_s,
- u"width"_s, u"vector4d"_s });
-
- QTest::newRow("fileStart") << uri << 0 << 0
- << ExpectedCompletions({
- { u"Rectangle"_s, CompletionItemKind::Class },
- { u"import"_s, CompletionItemKind::Keyword },
- })
- << QStringList({ u"QtQuick"_s, u"vector4d"_s, u"width"_s });
-
- QTest::newRow("importImport") << uri << 0 << 3
- << ExpectedCompletions({
- { u"Rectangle"_s, CompletionItemKind::Class },
- { u"import"_s, CompletionItemKind::Keyword },
- })
- << QStringList({ u"QtQuick"_s, u"vector4d"_s, u"width"_s });
-
- QTest::newRow("importModuleStart")
- << uri << 0 << 7
- << ExpectedCompletions({
- { u"QtQuick"_s, CompletionItemKind::Module },
- })
- << QStringList({ u"vector4d"_s, u"width"_s, u"Rectangle"_s, u"import"_s });
-
- QTest::newRow("importVersionStart")
- << uri << 0 << 15
- << ExpectedCompletions({
- { u"2"_s, CompletionItemKind::Constant },
- { u"as"_s, CompletionItemKind::Keyword },
- })
- << QStringList({ u"Rectangle"_s, u"import"_s, u"vector4d"_s, u"width"_s });
-
- // QTest::newRow("importVersionMinor")
- // << uri << 0 << 17
- // << ExpectedCompletions({
- // { u"15"_s, CompletionItemKind::Constant },
- // })
- // << QStringList({ u"as"_s, u"Rectangle"_s, u"import"_s, u"vector4d"_s, u"width"_s });
-
- QTest::newRow("inScript") << uri << 6 << 14
- << ExpectedCompletions({
- { u"Rectangle"_s, CompletionItemKind::Field },
- { u"vector4d"_s, CompletionItemKind::Field },
- { u"lala()"_s, CompletionItemKind::Function },
- { u"longfunction()"_s, CompletionItemKind::Function },
- { u"documentedFunction()"_s,
- CompletionItemKind::Function },
- { u"lala()"_s, CompletionItemKind { 0 } },
- { u"width"_s, CompletionItemKind::Field },
- })
- << QStringList({ u"import"_s });
-
- QTest::newRow("expandBase1") << uri << 9 << 23
- << ExpectedCompletions({
- { u"width"_s, CompletionItemKind::Field },
- { u"foo"_s, CompletionItemKind::Field },
- })
- << QStringList({ u"import"_s, u"Rectangle"_s });
-
- QTest::newRow("expandBase2") << uri << 10 << 29
- << ExpectedCompletions({
- { u"width"_s, CompletionItemKind::Field },
- { u"color"_s, CompletionItemKind::Field },
- })
- << QStringList({ u"foo"_s, u"import"_s, u"Rectangle"_s });
-
- QTest::newRow("asCompletions")
- << uri << 25 << 8
- << ExpectedCompletions({
- { u"Rectangle"_s, CompletionItemKind::Field },
- })
- << QStringList({ u"foo"_s, u"import"_s, u"lala()"_s, u"width"_s });
-}
-
-void tst_QmllsCompletions::checkCompletions(QByteArray uri, int lineNr, int character,
- ExpectedCompletions expected, QStringList notExpected)
-{
- CompletionParams cParams;
- cParams.position.line = lineNr;
- cParams.position.character = character;
- cParams.textDocument.uri = uri;
- std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
- auto clean = [didFinish]() { *didFinish = true; };
-
- m_protocol.requestCompletion(
- cParams,
- [clean, uri, expected, notExpected](auto res) {
- QScopeGuard cleanup(clean);
- const QList<CompletionItem> *cItems = std::get_if<QList<CompletionItem>>(&res);
-
- if (!cItems) {
- return;
- }
-
- QSet<QString> labels;
- QDuplicateTracker<QByteArray> modulesTracker;
- QDuplicateTracker<QByteArray> keywordsTracker;
- QDuplicateTracker<QByteArray> classesTracker;
- QDuplicateTracker<QByteArray> fieldsTracker;
- QDuplicateTracker<QByteArray> propertiesTracker;
-
- for (const CompletionItem &c : *cItems) {
- if (c.kind->toInt() == int(CompletionItemKind::Module)) {
- QVERIFY2(!modulesTracker.hasSeen(c.label), "Duplicate module: " + c.label);
- } else if (c.kind->toInt() == int(CompletionItemKind::Keyword)) {
- QVERIFY2(!keywordsTracker.hasSeen(c.label),
- "Duplicate keyword: " + c.label);
- } else if (c.kind->toInt() == int(CompletionItemKind::Class)) {
- QVERIFY2(!classesTracker.hasSeen(c.label), "Duplicate class: " + c.label);
- } else if (c.kind->toInt() == int(CompletionItemKind::Field)) {
- QVERIFY2(!fieldsTracker.hasSeen(c.label), "Duplicate field: " + c.label);
- } else if (c.kind->toInt() == int(CompletionItemKind::Property)) {
- QVERIFY2(!propertiesTracker.hasSeen(c.label),
- "Duplicate property: " + c.label);
- QVERIFY2(c.insertText == c.label + u": "_s,
- "a property should end with a colon with a space for "
- "'insertText', for better coding experience");
- }
- labels << c.label;
- }
-
- for (const ExpectedCompletion &exp : expected) {
- QVERIFY2(labels.contains(exp.first),
- u"no %1 in %2"_s
- .arg(exp.first,
- QStringList(labels.begin(), labels.end()).join(u", "_s))
- .toUtf8());
- if (labels.contains(exp.first)) {
- for (const CompletionItem &c : *cItems) {
- const auto kind = static_cast<CompletionItemKind>(c.kind->toInt());
-
- bool foundEntry = false;
- bool hasCorrectKind = false;
- for (const ExpectedCompletion &e : expected) {
- if (c.label == e.first) {
- foundEntry = true;
- hasCorrectKind |= kind == e.second;
- }
- }
-
- // Ignore QVERIFY for those completions not in the expected list.
- if (!foundEntry)
- continue;
-
- QVERIFY2(hasCorrectKind,
- qPrintable(
- QString::fromLatin1(
- "Completion item '%1' has wrong kind '%2'")
- .arg(c.label)
- .arg(QMetaEnum::fromType<CompletionItemKind>()
- .valueToKey(int(kind)))));
- }
- }
- }
- for (const QString &nexp : notExpected) {
- QVERIFY2(!labels.contains(nexp),
- u"found unexpected completion %1"_s.arg(nexp).toUtf8());
- }
- },
- [clean](const ResponseError &err) {
- QScopeGuard cleanup(clean);
- ProtocolBase::defaultResponseErrorHandler(err);
- QVERIFY2(false, "error computing the completion");
- });
- QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 30000);
-}
-
-void tst_QmllsCompletions::completions()
-{
- QFETCH(QByteArray, uri);
- QFETCH(int, lineNr);
- QFETCH(int, character);
- QFETCH(ExpectedCompletions, expected);
- QFETCH(QStringList, notExpected);
-
- QTEST_CHECKED(checkCompletions(uri, lineNr, character, expected, notExpected));
-}
-
-void tst_QmllsCompletions::function_documentations_data()
-{
- QTest::addColumn<QByteArray>("uri");
- QTest::addColumn<int>("lineNr");
- QTest::addColumn<int>("character");
- QTest::addColumn<ExpectedDocumentations>("expectedDocs");
-
- QByteArray uri = testFileUrl("completions/Yyy.qml").toString().toUtf8();
-
- QTest::newRow("longfunction")
- << uri << 5 << 14
- << ExpectedDocumentations{
- std::make_tuple(u"lala()"_s, u"returns void"_s, u"lala()"_s),
- std::make_tuple(u"longfunction()"_s, u"returns string"_s,
- uR"(longfunction(a, b, c = "c", d = "d"))"_s),
- std::make_tuple(u"documentedFunction()"_s, u"returns string"_s,
- uR"(// documentedFunction: is documented
-// returns 'Good'
-documentedFunction(arg1, arg2 = "Qt"))"_s),
- };
-}
-
-void tst_QmllsCompletions::function_documentations()
-{
- QFETCH(QByteArray, uri);
- QFETCH(int, lineNr);
- QFETCH(int, character);
- QFETCH(ExpectedDocumentations, expectedDocs);
-
- CompletionParams cParams;
- cParams.position.line = lineNr;
- cParams.position.character = character;
- cParams.textDocument.uri = uri;
- std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
- auto clean = [didFinish]() { *didFinish = true; };
-
- m_protocol.requestCompletion(
- cParams,
- [clean, uri, expectedDocs](auto res) {
- const QList<CompletionItem> *cItems = std::get_if<QList<CompletionItem>>(&res);
-
- if (!cItems) {
- return;
- }
-
- for (const ExpectedDocumentation &exp : expectedDocs) {
- bool hasFoundExpected = false;
- const auto expectedLabel = std::get<0>(exp);
- for (const CompletionItem &c : *cItems) {
- if (c.kind->toInt() != int(CompletionItemKind::Function)) {
- // Only check functions.
- continue;
- }
-
- if (c.label == expectedLabel) {
- hasFoundExpected = true;
- }
- }
-
- QVERIFY2(hasFoundExpected,
- qPrintable(u"expected completion label '%1' wasn't found"_s.arg(
- expectedLabel)));
- }
-
- for (const CompletionItem &c : *cItems) {
- if (c.kind->toInt() != int(CompletionItemKind::Function)) {
- // Only check functions.
- continue;
- }
-
- QVERIFY(c.documentation != std::nullopt);
- // We currently don't support 'MarkupContent', change this when we do.
- QVERIFY(c.documentation->index() == 0);
- const QByteArray cDoc = std::get<0>(*c.documentation);
-
- for (const ExpectedDocumentation &exp : expectedDocs) {
- const auto &[label, details, docs] = exp;
-
- if (c.label != label)
- continue;
-
- QVERIFY2(c.detail == details,
- qPrintable(u"Completion item '%1' has wrong details '%2'"_s
- .arg(label).arg(*c.detail)));
- QVERIFY2(cDoc == docs,
- qPrintable(u"Completion item '%1' has wrong documentation '%2'"_s
- .arg(label).arg(cDoc)));
- }
- }
- clean();
- },
- [clean](const ResponseError &err) {
- ProtocolBase::defaultResponseErrorHandler(err);
- QVERIFY2(false, "error computing the completion");
- clean();
- });
- QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 30000);
-}
-
-void tst_QmllsCompletions::buildDir()
-{
- QString filePath = u"completions/fromBuildDir.qml"_s;
- QByteArray uri = testFileUrl(filePath).toString().toUtf8();
- QTEST_CHECKED(checkCompletions(uri, 3, 0,
- ExpectedCompletions({
- { u"property"_s, CompletionItemKind::Keyword },
- { u"function"_s, CompletionItemKind::Keyword },
- { u"Rectangle"_s, CompletionItemKind::Class },
- }),
- QStringList({ u"BuildDirType"_s, u"QtQuick"_s, u"width"_s, u"vector4d"_s })));
- Notifications::AddBuildDirsParams bDirs;
- UriToBuildDirs ub;
- ub.baseUri = uri;
- ub.buildDirs.append(testFile("buildDir").toUtf8());
- bDirs.buildDirsToSet.append(ub);
- m_protocol.typedRpc()->sendNotification(QByteArray(Notifications::AddBuildDirsMethod), bDirs);
- DidChangeTextDocumentParams didChange;
- didChange.textDocument.uri = uri;
- didChange.textDocument.version = 2;
- TextDocumentContentChangeEvent change;
- QFile file(testFile(filePath));
- QVERIFY(file.open(QIODevice::ReadOnly));
- change.text = file.readAll();
- didChange.contentChanges.append(change);
- m_protocol.notifyDidChangeTextDocument(didChange);
- QTEST_CHECKED(checkCompletions(uri, 3, 0,
- ExpectedCompletions({
- { u"BuildDirType"_s, CompletionItemKind::Class },
- { u"Rectangle"_s, CompletionItemKind::Class },
- { u"property"_s, CompletionItemKind::Keyword },
- { u"width"_s, CompletionItemKind::Property },
- { u"function"_s, CompletionItemKind::Keyword },
- }),
- QStringList({ u"QtQuick"_s, u"vector4d"_s })));
-}
-void tst_QmllsCompletions::cleanupTestCase()
-{
- for (const QByteArray &uri : m_uriToClose) {
- DidCloseTextDocumentParams closeP;
- closeP.textDocument.uri = uri;
- m_protocol.notifyDidCloseTextDocument(closeP);
- }
- m_server.closeWriteChannel();
- QTRY_COMPARE(m_server.state(), QProcess::NotRunning);
- QCOMPARE(m_server.exitStatus(), QProcess::NormalExit);
-}
-
-QTEST_MAIN(tst_QmllsCompletions)
-
-#include <tst_qmllscompletions.moc>
diff --git a/tests/auto/qmlls/lifecycle/CMakeLists.txt b/tests/auto/qmlls/lifecycle/CMakeLists.txt
index ec12884e98..fa97aca132 100644
--- a/tests/auto/qmlls/lifecycle/CMakeLists.txt
+++ b/tests/auto/qmlls/lifecycle/CMakeLists.txt
@@ -5,18 +5,22 @@
## tst_lifecycle Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_lifecycle LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_lifecycle
SOURCES
- ../../../../tools/qmlls/qlanguageserver.h ../../../../tools/qmlls/qlanguageserver.cpp
tst_lifecycle.cpp
qiopipe.h qiopipe.cpp
- INCLUDE_DIRECTORIES
- ../../../../tools/qmlls
DEFINES
QT_DEPRECATED_WARNINGS
LIBRARIES
Qt::CorePrivate
Qt::LanguageServerPrivate
Qt::Test
+ Qt::QmlLSPrivate
TESTDATA ${test_data}
)
diff --git a/tests/auto/qmlls/lifecycle/qiopipe.cpp b/tests/auto/qmlls/lifecycle/qiopipe.cpp
index 416fe8257d..44f34e6580 100644
--- a/tests/auto/qmlls/lifecycle/qiopipe.cpp
+++ b/tests/auto/qmlls/lifecycle/qiopipe.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qiopipe.h"
diff --git a/tests/auto/qmlls/lifecycle/qiopipe.h b/tests/auto/qmlls/lifecycle/qiopipe.h
index e6c6d8b9a4..1722e2e465 100644
--- a/tests/auto/qmlls/lifecycle/qiopipe.h
+++ b/tests/auto/qmlls/lifecycle/qiopipe.h
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef QECHODEVICE_H
#define QECHODEVICE_H
diff --git a/tests/auto/qmlls/lifecycle/tst_lifecycle.cpp b/tests/auto/qmlls/lifecycle/tst_lifecycle.cpp
index 6c960f414e..efbdf10c37 100644
--- a/tests/auto/qmlls/lifecycle/tst_lifecycle.cpp
+++ b/tests/auto/qmlls/lifecycle/tst_lifecycle.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qiopipe.h"
@@ -8,7 +8,7 @@
#include <QtJsonRpc/private/qjsonrpcprotocol_p.h>
#include <QtLanguageServer/private/qlanguageserverprotocol_p.h>
-#include "qlanguageserver.h"
+#include <QtQmlLS/private/qlanguageserver_p.h>
#include <QtCore/qjsonarray.h>
#include <QtCore/qjsonobject.h>
diff --git a/tests/auto/qmlls/modules/CMakeLists.txt b/tests/auto/qmlls/modules/CMakeLists.txt
new file mode 100644
index 0000000000..565c8fb62a
--- /dev/null
+++ b/tests/auto/qmlls/modules/CMakeLists.txt
@@ -0,0 +1,45 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlls_modules LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+file(GLOB_RECURSE test_data_glob
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ data)
+file(GLOB_RECURSE test_data_glob_qmlformat
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/../../qml/qmlformat/
+ data)
+list(APPEND test_data ${test_data_glob})
+
+qt_internal_add_test(tst_qmlls_modules
+ SOURCES
+ tst_qmlls_modules.cpp
+ tst_qmlls_modules.h
+ DEFINES
+ QT_DEPRECATED_WARNINGS
+ QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+ QT_QMLFORMATTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/../../qml/qmlformat/data"
+ LIBRARIES
+ Qt::Core
+ Qt::QmlDomPrivate
+ Qt::LanguageServerPrivate
+ Qt::Test
+ Qt::QuickTestUtilsPrivate
+ Qt::QmlLSPrivate
+ TESTDATA ${test_data}
+)
+
+qt_internal_extend_target(tst_qmlls_modules CONDITION ANDROID OR IOS
+ DEFINES
+ QT_QMLTEST_DATADIR=":/domdata"
+)
+
+if (TARGET qmlls)
+ # standalone test builds do not know the qmlls target
+ # but if TARGET qmlls is known it should be built before this test
+ add_dependencies(tst_qmlls_modules qmlls)
+endif()
diff --git a/tests/auto/qmlls/completions/data/buildDir/BuildDir/BuildDirType.qml b/tests/auto/qmlls/modules/data/buildDir/BuildDir/BuildDirType.qml
index 416ec33253..416ec33253 100644
--- a/tests/auto/qmlls/completions/data/buildDir/BuildDir/BuildDirType.qml
+++ b/tests/auto/qmlls/modules/data/buildDir/BuildDir/BuildDirType.qml
diff --git a/tests/auto/qmlls/completions/data/buildDir/BuildDir/qmldir b/tests/auto/qmlls/modules/data/buildDir/BuildDir/qmldir
index 18d90059da..df2320f1f0 100644
--- a/tests/auto/qmlls/completions/data/buildDir/BuildDir/qmldir
+++ b/tests/auto/qmlls/modules/data/buildDir/BuildDir/qmldir
@@ -1,2 +1,3 @@
module BuildDir
BuildDirType 1.0 BuildDirType.qml
+import QtQuick.Controls.Basic
diff --git a/tests/auto/qmlls/modules/data/completions/SomeBase.qml b/tests/auto/qmlls/modules/data/completions/SomeBase.qml
new file mode 100644
index 0000000000..9c36e13c5b
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/completions/SomeBase.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+Item {
+
+}
diff --git a/tests/auto/qmlls/completions/data/completions/Yyy.qml b/tests/auto/qmlls/modules/data/completions/Yyy.qml
index 23bbd057f7..9ac6f9968d 100644
--- a/tests/auto/qmlls/completions/data/completions/Yyy.qml
+++ b/tests/auto/qmlls/modules/data/completions/Yyy.qml
@@ -26,4 +26,7 @@ Zzz {
QQ.Rectangle {
color:"red"
}
+
+ component IC: Zzz { property SomeBase data }
+ property SomeBase mySomeBase
}
diff --git a/tests/auto/qmlls/completions/data/completions/Zzz.qml b/tests/auto/qmlls/modules/data/completions/Zzz.qml
index 165ea46394..165ea46394 100644
--- a/tests/auto/qmlls/completions/data/completions/Zzz.qml
+++ b/tests/auto/qmlls/modules/data/completions/Zzz.qml
diff --git a/tests/auto/qmlls/modules/data/completions/bindingAfterDot.qml b/tests/auto/qmlls/modules/data/completions/bindingAfterDot.qml
new file mode 100644
index 0000000000..2a8694342b
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/completions/bindingAfterDot.qml
@@ -0,0 +1,14 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+QtObject {
+ id: root
+ property int good
+ property var i: Item {
+ property int bad
+ property int myP: root.
+ Item { }
+ }
+}
diff --git a/tests/auto/qmlls/modules/data/completions/defaultBindingAfterDot.qml b/tests/auto/qmlls/modules/data/completions/defaultBindingAfterDot.qml
new file mode 100644
index 0000000000..4cf47b6f31
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/completions/defaultBindingAfterDot.qml
@@ -0,0 +1,14 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+QtObject {
+ id: root
+ property int good
+ property var i: Item {
+ property int bad
+ property int myP2: root.
+ bad: 43
+ }
+}
diff --git a/tests/auto/qmlls/completions/data/completions/fromBuildDir.qml b/tests/auto/qmlls/modules/data/completions/fromBuildDir.qml
index 4a572a3950..2c35f5b864 100644
--- a/tests/auto/qmlls/completions/data/completions/fromBuildDir.qml
+++ b/tests/auto/qmlls/modules/data/completions/fromBuildDir.qml
@@ -6,4 +6,5 @@ BuildDirType {
width: 250
height: 10
}
+ Button {}
}
diff --git a/tests/auto/qmlls/modules/data/findDefinition/jsDefinitions.qml b/tests/auto/qmlls/modules/data/findDefinition/jsDefinitions.qml
new file mode 100644
index 0000000000..3243030466
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/findDefinition/jsDefinitions.qml
@@ -0,0 +1,17 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.15
+
+Item {
+ id: rootId
+
+ property int i // (1)
+ function f(a /*(2)*/ , b) {return a /* go to definition on a leads to (2) */ > b} // (4)
+
+ Component.onCompleted: {
+ let x = 42 // (3)
+ f(x, i) // goto definition on f goes to 4, on x goes to (3) and on i goes to (1)
+ f(x, rootId.i) // goto definition on f goes to 4, on x goes to (3) and on i goes to (1)
+ }
+}
diff --git a/tests/auto/qmlls/modules/data/findUsages/jsIdentifierUsages.qml b/tests/auto/qmlls/modules/data/findUsages/jsIdentifierUsages.qml
new file mode 100644
index 0000000000..6c099edc9e
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/findUsages/jsIdentifierUsages.qml
@@ -0,0 +1,13 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function f() {
+ let sum = 0, sum2 = 0
+ for(let i = 1; i < 42; i = i + 2) {
+ sum = sum + i
+ }
+ }
+}
diff --git a/tests/auto/qmlls/modules/data/formatting/blanklines.formatted.qml b/tests/auto/qmlls/modules/data/formatting/blanklines.formatted.qml
new file mode 100644
index 0000000000..19548e9023
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/formatting/blanklines.formatted.qml
@@ -0,0 +1,4 @@
+// leading and trailing spaces
+import QtQuick
+
+Item {}
diff --git a/tests/auto/qmlls/modules/data/formatting/blanklines.qml b/tests/auto/qmlls/modules/data/formatting/blanklines.qml
new file mode 100644
index 0000000000..ae1a14daed
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/formatting/blanklines.qml
@@ -0,0 +1,15 @@
+
+
+
+
+// leading and trailing spaces
+import QtQuick
+
+
+Item {
+
+
+ }
+
+
+
diff --git a/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted1.qml b/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted1.qml
new file mode 100644
index 0000000000..e167f829b2
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted1.qml
@@ -0,0 +1,23 @@
+pragma Strict
+
+import QtQuick
+
+Item {
+ property var test: [{
+ // Testing
+ "foo": "bar"
+ }]
+
+ Item {
+
+ function test() {
+var patron = "ðŸˆtestðŸˆ";
+ let kivrik = 1;
+
+
+
+
+ const yumyum = 1;
+ }
+ }
+}
diff --git a/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted2.qml b/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted2.qml
new file mode 100644
index 0000000000..ebd68dbde2
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted2.qml
@@ -0,0 +1,20 @@
+pragma Strict
+
+import QtQuick
+
+Item {
+ property var test: [{
+// Testing
+ "foo": "bar"
+}]
+
+ Item {
+
+ function test() {
+ var patron = "ðŸˆtestðŸˆ";
+ let kivrik = 1;
+
+ const yumyum = 1;
+ }
+ }
+}
diff --git a/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted3.qml b/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted3.qml
new file mode 100644
index 0000000000..83f91c6af5
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted3.qml
@@ -0,0 +1,23 @@
+pragma Strict
+
+import QtQuick
+
+Item {
+ property var test: [{
+// Testing
+ "foo": "bar"
+}]
+
+ Item {
+
+ function test() {
+var patron = "ðŸˆtestðŸˆ";
+ let kivrik = 1;
+
+
+
+
+ const yumyum = 1;
+ }
+ }
+}
diff --git a/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted4.qml b/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted4.qml
new file mode 100644
index 0000000000..d6d7227588
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted4.qml
@@ -0,0 +1,20 @@
+pragma Strict
+
+import QtQuick
+
+Item {
+ property var test: [{
+ // Testing
+ "foo": "bar"
+ }]
+
+ Item {
+
+ function test() {
+ var patron = "ðŸˆtestðŸˆ";
+ let kivrik = 1;
+
+ const yumyum = 1;
+ }
+ }
+}
diff --git a/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted5.qml b/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted5.qml
new file mode 100644
index 0000000000..8b3ddf8df1
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/formatting/rangeFormatting.formatted5.qml
@@ -0,0 +1,20 @@
+pragma Strict
+
+import QtQuick
+
+Item {
+ property var test: [{
+// Testing
+ "foo": "bar"
+}]
+
+ Item {
+
+ function test() {
+ var patron = "ðŸˆtestðŸˆ";
+ let kivrik = 1;
+
+ const yumyum = 1;
+ }
+ }
+}
diff --git a/tests/auto/qmlls/modules/data/formatting/rangeFormatting.qml b/tests/auto/qmlls/modules/data/formatting/rangeFormatting.qml
new file mode 100644
index 0000000000..1431fb10c3
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/formatting/rangeFormatting.qml
@@ -0,0 +1,23 @@
+pragma Strict
+
+import QtQuick
+
+Item {
+ property var test: [{
+// Testing
+ "foo": "bar"
+}]
+
+ Item {
+
+ function test() {
+var patron = "ðŸˆtestðŸˆ";
+ let kivrik = 1;
+
+
+
+
+ const yumyum = 1;
+ }
+ }
+}
diff --git a/tests/auto/qmlls/modules/data/highlighting/basic.qml b/tests/auto/qmlls/modules/data/highlighting/basic.qml
new file mode 100644
index 0000000000..264f553b22
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/highlighting/basic.qml
@@ -0,0 +1,11 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ id: rootId
+ function a() {
+
+ }
+}
diff --git a/tests/auto/qmlls/modules/data/highlighting/bigFile.qml b/tests/auto/qmlls/modules/data/highlighting/bigFile.qml
new file mode 100644
index 0000000000..9832e8e98a
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/highlighting/bigFile.qml
@@ -0,0 +1,351 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ id: rootId
+ function f() {
+ let sum = 0, sum2 = 0;
+ for (let i = 1; i < 42; i = i + 2) {
+ sum = sum + i;
+ {
+ let sum = 42; // another unrelated sum
+ }
+ }
+ }
+
+ readonly property int helloProperty: 0
+ property int p2: 1
+
+ function withProperty() {
+ let sum = 0, sum2 = 0;
+ for (const i = 1; i < 42; i = i + 2) {
+ sum = sum + i;
+ helloProperty = helloProperty + sum - i * p2;
+ {
+ let helloProperty = "evil";
+ }
+ }
+ }
+ Item {
+ function f() {
+ return helloProperty + p2;
+ }
+ property string helloProperty
+ }
+ component IC: Item {
+ property var helloProperty
+ function f() {
+ return helloProperty + p2;
+ }
+ }
+ component NestedComponent: Item {
+ property NestedComponent2 inner: NestedComponent2 {}
+ property int p2
+ }
+ component NestedComponent2: Item {
+ property NestedComponent3 inner
+ property int p2
+ inner: NestedComponent3 {}
+ }
+ component NestedComponent3: Item {
+ property NestedComponent4 inner
+ property int p2
+ inner: NestedComponent4 {}
+ }
+ component NestedComponent4: Item {
+ property int helloProperty
+ property int p2
+ }
+ NestedComponent {
+ id: myNested
+ }
+ function nestedUsages() {
+ let x = myNested.inner.inner.inner.helloProperty + helloProperty;
+ let a = myNested.p2 + p2;
+ let b = myNested.inner.p2 + p2;
+ let c = myNested.inner.inner.p2 + p2;
+ let d = myNested.inner.inner.inner.p2 + p2;
+ }
+
+ function recursive(n: int): int {
+ if (n > 3)
+ return 1 + recursive(recursive(x - 1) + recursive(x - 2) - recursive(x - 3));
+ else
+ return recursive(0);
+ }
+
+ property int helloRecursive: recursive(42)
+ Rectangle {
+ function f() {
+ return rootId.recursive(123);
+ }
+ }
+
+ signal helloSignal
+
+ function callSignals() {
+ helloSignal();
+ if (false) {
+ helloSignal();
+ } else {
+ // helloSignal() // not a usage btw
+ if (true)
+ helloSignal();
+ }
+ }
+ function callSignals2() {
+ helloSignal();
+ if (false) {
+ widthChanged();
+ } else {
+ // helloSignal() // not a usage btw
+ if (true)
+ widthChanged();
+ rootId.widthChanged();
+ }
+ }
+ Item {
+ function callSignalsInChild() {
+ widthChanged();
+ rootId.widthChanged();
+ }
+ }
+
+ function myHelloHandler() {
+ let x = 32;
+ }
+ onHelloSignal: myHelloHandler
+
+ property int helloPropertyBinding
+ helloPropertyBinding: 123
+
+ property int checkHandlers
+ onCheckHandlersChanged: myHelloHandler
+ onChildrenChanged: myHelloHandler
+ function callChanged() {
+ checkHandlersChanged();
+ childrenChanged();
+ }
+ property int _: 48
+ property int ______42: 48
+ property int _123a: 48
+ on_Changed: myHelloHandler
+ on______42Changed: myHelloHandler
+ on_123AChanged: myHelloHandler
+ function weirdPropertynames() {
+ _Changed();
+ ______42Changed();
+ _123aChanged();
+ }
+
+ TapHandler {
+ onTapped: myHelloHandler
+ function f() {
+ tapped();
+ }
+ }
+
+ function anotherF() {
+ helloPropertyChanged();
+ }
+ onHelloPropertyChanged: myHelloHandler
+ // Type {}
+ function foo(mouse) {
+ }
+
+ MouseArea {
+ id: area1
+ onClicked: foo
+ property int insideMouseArea1
+ }
+
+ MouseArea {
+ id: area2
+ Connections {
+ function onClicked(mouse) {
+ area1.clicked();
+ area3.clicked();
+ }
+ }
+ property int insideMouseArea2
+
+ MouseArea {
+ id: area3
+ }
+ }
+
+ property Connections c: Connections {
+ target: area3
+ onClicked: function (mouse) {}
+ }
+ function useMouseAreas() {
+ area1.clicked();
+ area2.clicked();
+ area3.clicked();
+ }
+
+ function checkParameters(a: int, b: double, {
+ x,
+ y = {},
+ z = [x, y]
+ }) {
+ return a + b + c + x + y + z;
+ }
+
+ function deconstructingUsages(xxx) {
+ let {
+ a,
+ b
+ } = xxx;
+ let c = a + b;
+ }
+
+ function k() {
+ }
+
+ function mafik() {
+ var patron = 34;
+ const upperLimit = 42;
+ do {
+ ++patron;
+ if (patron < 2)
+ continue;
+ else
+ ++patron;
+ } while (patron < upperLimit)
+ switch (patron) {
+ case 1:
+ return 23;
+ default:
+ break;
+ }
+ try {
+ {}
+ } catch (error) {
+ {}
+ } finally {}
+ for (const a in [1, 2, 3]) {
+ throw 2;
+ }
+ }
+
+ enum Test {
+ LOG
+ }
+
+ readonly property int t: 34
+ signal tt
+ required property int k
+
+ signal kkk(string a)
+ signal yyy(string a)
+
+ function ttt() {
+ }
+
+ function createComplexExpression(...objects) {
+ // Create an object that holds some data
+ let data = {
+ a: 5,
+ b: 10,
+ c: 3
+ };
+
+ // Create a complex expression using the data object
+ let expression = ((data.a + data.b * data.c) / (data.a - data.b)) ** data.c;
+
+ return expression;
+ }
+
+ function set1() {
+ const array = [1, 2, 3, 4];
+ const [a, b] = [1, 2];
+ const [aa, , bb] = array;
+ const [aaa = 23, bbb] = array;
+ const [a1, b1, ...rest1] = array;
+ const [a2, , b2, ...rest2] = array;
+ const [a3, b3, ...{
+ pop,
+ push
+ }] = array;
+ const [a4, b4, ...[c, d]] = array;
+
+ const obj = {
+ _a: 1,
+ _b: 2
+ };
+ const {
+ a5,
+ b5
+ } = obj;
+ const {
+ a6: a_,
+ b6: b1_
+ } = obj;
+ const {
+ a7: a11 = 4,
+ b11 = 34,
+ c1: b111,
+ d1
+ } = obj;
+ let key = a;
+ const {
+ [key]: a___
+ } = obj;
+ }
+
+ function set2(s: int): int {
+ // declare first
+ let a, b, a1, b1, c, d, rest, pop, push;
+ const array = [1, 2, 3, 4];
+ [a, b] = array;
+ [a, , b] = array;
+ [a = aDefault, b] = array;
+ [a, b, ...rest] = array;
+ [a, , b, ...rest] = array;
+ [a, b, ...{
+ pop,
+ push
+ }] = array;
+ [a, b, ...[c, d]] = array;
+
+ const obj = {
+ _a: 1,
+ _b: 2
+ };
+ ({
+ a,
+ b
+ } = obj); // brackets are required
+ ({
+ a: a1,
+ b: b1
+ } = obj);
+
+ const complicatedObject = {
+ a: 1,
+ b: {
+ c: 2,
+ d: {
+ e: 3,
+ f: [4, 5, 6]
+ }
+ },
+ g: [7, 8, 9]
+ };
+
+ const {
+ patron,
+ b: {
+ mafik,
+ d: {
+ e,
+ f: [, secondF, ...restF]
+ }
+ },
+ g: [firstG, ...restG]
+ } = complicatedObject;
+ }
+}
diff --git a/tests/auto/qmlls/modules/data/hover/test.qml b/tests/auto/qmlls/modules/data/hover/test.qml
new file mode 100644
index 0000000000..dd1d5abcb0
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/hover/test.qml
@@ -0,0 +1,8 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+QtObject {
+ readonly property int t: ""
+}
diff --git a/tests/auto/qmlls/modules/data/linting/SimpleItem.qml b/tests/auto/qmlls/modules/data/linting/SimpleItem.qml
new file mode 100644
index 0000000000..b7b7fc5021
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/linting/SimpleItem.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ id: helloItem
+
+}
diff --git a/tests/auto/qmlls/modules/data/quickfixes/INeedAQuickFix.qml b/tests/auto/qmlls/modules/data/quickfixes/INeedAQuickFix.qml
new file mode 100644
index 0000000000..ccd2a55383
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/quickfixes/INeedAQuickFix.qml
@@ -0,0 +1,19 @@
+import QtQuick
+
+Item {
+ id: hello
+
+ signal s(xxx: string)
+ property int i: 42
+
+ // fix me! add '(xxx) =>' in front of console.log()
+ onS: console.log(xxx)
+
+ Item {
+ // fix me! prepend 'hello.' to 'i'!
+ function f() {
+ return i
+ }
+ }
+
+}
diff --git a/tests/auto/qmlls/modules/data/renameUsages/RenameMe.qml b/tests/auto/qmlls/modules/data/renameUsages/RenameMe.qml
new file mode 100644
index 0000000000..7680c63f95
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/renameUsages/RenameMe.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int helloProperty
+} \ No newline at end of file
diff --git a/tests/auto/qmlls/modules/data/renameUsages/RenameMe2.ui.qml b/tests/auto/qmlls/modules/data/renameUsages/RenameMe2.ui.qml
new file mode 100644
index 0000000000..b9197def63
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/renameUsages/RenameMe2.ui.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int helloProperty
+}
diff --git a/tests/auto/qmlls/modules/data/renameUsages/main.qml b/tests/auto/qmlls/modules/data/renameUsages/main.qml
new file mode 100644
index 0000000000..b59508f92f
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/renameUsages/main.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ RenameMe {}
+ RenameMe2 {}
+}
diff --git a/tests/auto/qmlls/modules/data/sourceDir/A.qml b/tests/auto/qmlls/modules/data/sourceDir/A.qml
new file mode 100644
index 0000000000..5560aee727
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/sourceDir/A.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+
+}
diff --git a/tests/auto/qmlls/modules/data/sourceDir/Main.qml b/tests/auto/qmlls/modules/data/sourceDir/Main.qml
new file mode 100644
index 0000000000..e9fc9d4298
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/sourceDir/Main.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ B {}
+ Button {}
+}
diff --git a/tests/auto/qmlls/modules/data/sourceDir/qmldir b/tests/auto/qmlls/modules/data/sourceDir/qmldir
new file mode 100644
index 0000000000..2dd55288e3
--- /dev/null
+++ b/tests/auto/qmlls/modules/data/sourceDir/qmldir
@@ -0,0 +1,3 @@
+module SourceDir
+B 1.0 A.qml
+import QtQuick.Controls.Basic
diff --git a/tests/auto/qmlls/modules/tst_qmlls_modules.cpp b/tests/auto/qmlls/modules/tst_qmlls_modules.cpp
new file mode 100644
index 0000000000..fa050b0727
--- /dev/null
+++ b/tests/auto/qmlls/modules/tst_qmlls_modules.cpp
@@ -0,0 +1,1765 @@
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "tst_qmlls_modules.h"
+#include "QtQmlLS/private/qqmllsutils_p.h"
+#include "QtQmlLS/private/qqmlsemantictokens_p.h"
+#include <algorithm>
+#include <memory>
+#include <optional>
+#include <string>
+#include <tuple>
+#include <type_traits>
+#include <variant>
+
+// Check if QTest already has a QTEST_CHECKED macro
+#ifndef QTEST_CHECKED
+#define QTEST_CHECKED(...) \
+do { \
+ __VA_ARGS__; \
+ if (QTest::currentTestFailed()) \
+ return; \
+} while (false)
+#endif
+
+QT_USE_NAMESPACE
+using namespace Qt::StringLiterals;
+using namespace QLspSpecification;
+
+static constexpr bool enable_debug_output = false;
+
+tst_qmlls_modules::tst_qmlls_modules() : QQmlDataTest(QT_QMLTEST_DATADIR)
+{
+ m_qmllsPath =
+ QLibraryInfo::path(QLibraryInfo::BinariesPath) + QLatin1String("/qmlls");
+#ifdef Q_OS_WIN
+ m_qmllsPath += QLatin1String(".exe");
+#endif
+ // allow overriding of the executable, to be able to use a qmlEcho script (as described in
+ // qmllanguageservertool.cpp)
+ m_qmllsPath = qEnvironmentVariable("QMLLS", m_qmllsPath);
+ // qputenv("QT_LOGGING_RULES",
+ // "qt.languageserver.codemodel.debug=true;qt.languageserver.codemodel.warning=true"); // helps
+ qputenv("QT_LOGGING_RULES", "*.debug=true;*.warning=true");
+ // when using EditingRecorder
+ m_server.setProgram(m_qmllsPath);
+ // m_server.setArguments(QStringList() << u"-v"_s << u"-w"_s << u"7"_s);
+}
+
+void tst_qmlls_modules::init()
+{
+ QQmlDataTest::init();
+
+ m_protocol = std::make_unique<QLanguageServerProtocol>(
+ [this](const QByteArray &data) { m_server.write(data); });
+
+ connect(&m_server, &QProcess::readyReadStandardOutput, this, [this]() {
+ QByteArray data = m_server.readAllStandardOutput();
+ m_protocol->receiveData(data);
+ });
+
+ if constexpr (enable_debug_output) {
+ connect(&m_server, &QProcess::readyReadStandardError, this, [this]() {
+ QProcess::ProcessChannel tmp = m_server.readChannel();
+ m_server.setReadChannel(QProcess::StandardError);
+ while (m_server.canReadLine())
+ qDebug() << m_server.readLine();
+ m_server.setReadChannel(tmp);
+ });
+ }
+
+ m_server.start();
+
+ InitializeParams clientInfo;
+ clientInfo.rootUri = QUrl::fromLocalFile(dataDirectory() + "/default").toString().toUtf8();
+
+ TextDocumentClientCapabilities tDoc;
+ tDoc.typeDefinition = TypeDefinitionClientCapabilities{ false, false };
+
+ PublishDiagnosticsClientCapabilities pDiag;
+ tDoc.publishDiagnostics = pDiag;
+ pDiag.versionSupport = true;
+ clientInfo.capabilities.textDocument = tDoc;
+ bool didInit = false;
+ m_protocol->requestInitialize(clientInfo, [this, &didInit](const InitializeResult &serverInfo) {
+ Q_UNUSED(serverInfo);
+ m_protocol->notifyInitialized(InitializedParams());
+ didInit = true;
+ });
+ QTRY_COMPARE_WITH_TIMEOUT(didInit, true, 10000);
+}
+
+void tst_qmlls_modules::cleanup()
+{
+ for (const QByteArray &uri : m_uriToClose) {
+ DidCloseTextDocumentParams closeP;
+ closeP.textDocument.uri = uri;
+ m_protocol->notifyDidCloseTextDocument(closeP);
+ }
+ m_uriToClose.clear();
+
+ // note: properly exit the language server
+ m_protocol->requestShutdown(nullptr, []() {});
+ m_protocol->notifyExit(nullptr);
+
+ m_server.waitForFinished();
+ QTRY_COMPARE(m_server.state(), QProcess::NotRunning);
+ QCOMPARE(m_server.exitStatus(), QProcess::NormalExit);
+}
+
+/*!
+\internal
+Opens a file from a relative filePath, and returns the loaded uri.
+Returns an empty option when the file could not be found.
+*/
+std::optional<QByteArray> tst_qmlls_modules::openFile(const QString &filePath)
+{
+ return openFileFromAbsolutePath(testFile(filePath));
+}
+
+/*!
+\internal
+Opens a file from an absolute filePath, and returns the loaded uri.
+Returns an empty option when the file could not be found.
+*/
+std::optional<QByteArray> tst_qmlls_modules::openFileFromAbsolutePath(const QString &filePath)
+{
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly))
+ return {};
+ DidOpenTextDocumentParams oParams;
+ TextDocumentItem textDocument;
+ QByteArray uri = QUrl::fromLocalFile(filePath).toEncoded();
+ textDocument.uri = uri;
+ textDocument.text = file.readAll();
+ oParams.textDocument = textDocument;
+ m_protocol->notifyDidOpenTextDocument(oParams);
+ m_uriToClose.append(uri);
+ return uri;
+}
+
+/*!
+\internal
+Ignore qmllint warnings, when not needed for the test.
+*/
+void tst_qmlls_modules::ignoreDiagnostics()
+{
+ m_protocol->registerPublishDiagnosticsNotificationHandler(
+ [](const QByteArray &, const PublishDiagnosticsParams &) {});
+}
+
+void tst_qmlls_modules::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ if (!QFileInfo::exists(m_qmllsPath)) {
+ QString message =
+ QStringLiteral("qmlls executable not found (looked for %0)").arg(m_qmllsPath);
+ QSKIP(qPrintable(message)); // until we add a feature for this we avoid failing here
+ }
+}
+
+void tst_qmlls_modules::checkCompletions(const QByteArray &uri, int lineNr, int character,
+ ExpectedCompletions expected, QStringList notExpected)
+{
+ CompletionParams cParams;
+ cParams.position.line = lineNr;
+ cParams.position.character = character;
+ cParams.textDocument.uri = uri;
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ auto clean = [didFinish]() { *didFinish = true; };
+
+ m_protocol->requestCompletion(
+ cParams,
+ [clean, uri, expected, notExpected](auto res) {
+ QScopeGuard cleanup(clean);
+ const QList<CompletionItem> *cItems = std::get_if<QList<CompletionItem>>(&res);
+
+ if (!cItems) {
+ return;
+ }
+
+ QSet<QString> labels;
+ QDuplicateTracker<QByteArray> modulesTracker;
+ QDuplicateTracker<QByteArray> keywordsTracker;
+ QDuplicateTracker<QByteArray> classesTracker;
+ QDuplicateTracker<QByteArray> fieldsTracker;
+ QDuplicateTracker<QByteArray> propertiesTracker;
+
+ for (const CompletionItem &c : *cItems) {
+ if (c.kind->toInt() == int(CompletionItemKind::Module)) {
+ QVERIFY2(!modulesTracker.hasSeen(c.label), "Duplicate module: " + c.label);
+ } else if (c.kind->toInt() == int(CompletionItemKind::Keyword)) {
+ QVERIFY2(!keywordsTracker.hasSeen(c.label),
+ "Duplicate keyword: " + c.label);
+ } else if (c.kind->toInt() == int(CompletionItemKind::Class)) {
+ QVERIFY2(!classesTracker.hasSeen(c.label), "Duplicate class: " + c.label);
+ } else if (c.kind->toInt() == int(CompletionItemKind::Field)) {
+ QVERIFY2(!fieldsTracker.hasSeen(c.label), "Duplicate field: " + c.label);
+ } else if (c.kind->toInt() == int(CompletionItemKind::Property)) {
+ QVERIFY2(!propertiesTracker.hasSeen(c.label),
+ "Duplicate property: " + c.label);
+ }
+ labels << c.label;
+ }
+
+ for (const ExpectedCompletion &exp : expected) {
+ QVERIFY2(labels.contains(exp.first),
+ u"no %1 in %2"_s
+ .arg(exp.first,
+ QStringList(labels.begin(), labels.end()).join(u", "_s))
+ .toUtf8());
+ if (labels.contains(exp.first)) {
+ for (const CompletionItem &c : *cItems) {
+ const auto kind = static_cast<CompletionItemKind>(c.kind->toInt());
+
+ bool foundEntry = false;
+ bool hasCorrectKind = false;
+ for (const ExpectedCompletion &e : expected) {
+ if (c.label == e.first) {
+ foundEntry = true;
+ hasCorrectKind |= kind == e.second;
+ }
+ }
+
+ // Ignore QVERIFY for those completions not in the expected list.
+ if (!foundEntry)
+ continue;
+
+ QVERIFY2(hasCorrectKind,
+ qPrintable(
+ QString::fromLatin1(
+ "Completion item '%1' has wrong kind '%2'")
+ .arg(c.label)
+ .arg(QMetaEnum::fromType<CompletionItemKind>()
+ .valueToKey(int(kind)))));
+ }
+ }
+ }
+ for (const QString &nexp : notExpected) {
+ QVERIFY2(!labels.contains(nexp),
+ u"found unexpected completion %1"_s.arg(nexp).toUtf8());
+ }
+ },
+ [clean](const ResponseError &err) {
+ QScopeGuard cleanup(clean);
+ ProtocolBase::defaultResponseErrorHandler(err);
+ QVERIFY2(false, "error computing the completion");
+ });
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 30000);
+}
+
+void tst_qmlls_modules::function_documentations_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<int>("lineNr");
+ QTest::addColumn<int>("character");
+ QTest::addColumn<ExpectedDocumentations>("expectedDocs");
+
+ const QString filePath = u"completions/Yyy.qml"_s;
+
+ QTest::newRow("longfunction")
+ << filePath << 5 << 14
+ << ExpectedDocumentations{
+ std::make_tuple(u"lala"_s, u"returns void"_s, u"lala()"_s),
+ std::make_tuple(u"longfunction"_s, u"returns string"_s,
+ uR"(longfunction(a, b, c = "c", d = "d"))"_s),
+ std::make_tuple(u"documentedFunction"_s, u"returns string"_s,
+ uR"(// documentedFunction: is documented
+// returns 'Good'
+documentedFunction(arg1, arg2 = "Qt"))"_s),
+ };
+}
+
+void tst_qmlls_modules::function_documentations()
+{
+ QFETCH(QString, filePath);
+ QFETCH(int, lineNr);
+ QFETCH(int, character);
+ QFETCH(ExpectedDocumentations, expectedDocs);
+
+ ignoreDiagnostics();
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+
+ CompletionParams cParams;
+ cParams.position.line = lineNr;
+ cParams.position.character = character;
+ cParams.textDocument.uri = *uri;
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ auto clean = [didFinish]() { *didFinish = true; };
+
+ m_protocol->requestCompletion(
+ cParams,
+ [clean, uri, expectedDocs](auto res) {
+ const QList<CompletionItem> *cItems = std::get_if<QList<CompletionItem>>(&res);
+
+ if (!cItems) {
+ return;
+ }
+
+ for (const ExpectedDocumentation &exp : expectedDocs) {
+ bool hasFoundExpected = false;
+ const auto expectedLabel = std::get<0>(exp);
+ for (const CompletionItem &c : *cItems) {
+ if (c.kind->toInt() != int(CompletionItemKind::Method)) {
+ // Only check functions.
+ continue;
+ }
+
+ if (c.label == expectedLabel) {
+ hasFoundExpected = true;
+ }
+ }
+
+ QVERIFY2(hasFoundExpected,
+ qPrintable(u"expected completion label '%1' wasn't found"_s.arg(
+ expectedLabel)));
+ }
+
+ for (const CompletionItem &c : *cItems) {
+ if (c.kind->toInt() != int(CompletionItemKind::Function)) {
+ // Only check functions.
+ continue;
+ }
+
+ QVERIFY(c.documentation != std::nullopt);
+ // We currently don't support 'MarkupContent', change this when we do.
+ QVERIFY(c.documentation->index() == 0);
+ const QByteArray cDoc = std::get<0>(*c.documentation);
+
+ for (const ExpectedDocumentation &exp : expectedDocs) {
+ const auto &[label, details, docs] = exp;
+
+ if (c.label != label)
+ continue;
+
+ QVERIFY2(c.detail == details,
+ qPrintable(u"Completion item '%1' has wrong details '%2'"_s
+ .arg(label).arg(*c.detail)));
+ QVERIFY2(cDoc == docs,
+ qPrintable(u"Completion item '%1' has wrong documentation '%2'"_s
+ .arg(label).arg(cDoc)));
+ }
+ }
+ clean();
+ },
+ [clean](const ResponseError &err) {
+ ProtocolBase::defaultResponseErrorHandler(err);
+ QVERIFY2(false, "error computing the completion");
+ clean();
+ });
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 3000);
+}
+
+void tst_qmlls_modules::buildDir()
+{
+ ignoreDiagnostics();
+ const QString filePath = u"completions/fromBuildDir.qml"_s;
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+ QTEST_CHECKED(checkCompletions(
+ *uri, 3, 0,
+ ExpectedCompletions({
+ { u"Rectangle"_s, CompletionItemKind::Constructor },
+ }),
+ QStringList({ u"BuildDirType"_s, u"QtQuick"_s, u"width"_s, u"vector4d"_s })));
+ Notifications::AddBuildDirsParams bDirs;
+ UriToBuildDirs ub;
+ ub.baseUri = *uri;
+ ub.buildDirs.append(testFile("buildDir").toUtf8());
+ bDirs.buildDirsToSet.append(ub);
+ m_protocol->typedRpc()->sendNotification(QByteArray(Notifications::AddBuildDirsMethod), bDirs);
+
+ DidChangeTextDocumentParams didChange;
+ didChange.textDocument.uri = *uri;
+ didChange.textDocument.version = 2;
+
+ // change the file content to force qqml— to recreate a new DomItem
+ // if it reuses the old DomItem then it will not know about the added build directory
+ TextDocumentContentChangeEvent change;
+ change.range = Range{ Position{ 4, 0 }, Position{ 4, 0 } };
+ change.text = "\n";
+
+ didChange.contentChanges.append(change);
+ m_protocol->notifyDidChangeTextDocument(didChange);
+
+ QTEST_CHECKED(checkCompletions(*uri, 3, 0,
+ ExpectedCompletions({
+ { u"BuildDirType"_s, CompletionItemKind::Constructor },
+ { u"Rectangle"_s, CompletionItemKind::Constructor },
+ { u"width"_s, CompletionItemKind::Property },
+ }),
+ QStringList({ u"QtQuick"_s, u"vector4d"_s })));
+}
+
+void tst_qmlls_modules::automaticSemicolonInsertionForCompletions_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+
+ QTest::addRow("bindingAfterDot") << u"completions/bindingAfterDot.qml"_s << 11 << 32;
+ QTest::addRow("defaultBindingAfterDot")
+ << u"completions/defaultBindingAfterDot.qml"_s << 11 << 32;
+}
+
+void tst_qmlls_modules::automaticSemicolonInsertionForCompletions()
+{
+ ignoreDiagnostics();
+ QFETCH(QString, filePath);
+ QFETCH(int, row);
+ QFETCH(int, column);
+ row--;
+ column--;
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+
+ QTEST_CHECKED(checkCompletions(
+ *uri, row, column,
+ ExpectedCompletions({
+ { u"good"_s, CompletionItemKind::Property },
+ }),
+ QStringList({ u"bad"_s, u"BuildDirType"_s, u"QtQuick"_s, u"width"_s, u"vector4d"_s })));
+}
+
+void tst_qmlls_modules::checkQuickSnippets()
+{
+ ignoreDiagnostics();
+ const auto uri = openFile(u"completions/Yyy.qml"_s);
+ QVERIFY(uri);
+
+ // if at least one snippet is there, then the pluginloading works. To test the plugin itself,
+ // add tests in tst_qmlls_utils instead.
+ QTEST_CHECKED(checkCompletions(
+ *uri, 4, 3,
+ ExpectedCompletions({
+ { u"BorderImage snippet"_s, CompletionItemKind::Snippet },
+ }),
+ QStringList({})));
+}
+
+void tst_qmlls_modules::goToTypeDefinition_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+ QTest::addColumn<QString>("expectedFilePath");
+ QTest::addColumn<int>("expectedStartLine");
+ QTest::addColumn<int>("expectedStartCharacter");
+ QTest::addColumn<int>("expectedEndLine");
+ QTest::addColumn<int>("expectedEndCharacter");
+
+ const QString yyyPath = u"completions/Yyy.qml"_s;
+ const QString zzzPath = u"completions/Zzz.qml"_s;
+ const QString someBasePath = u"completions/SomeBase.qml"_s;
+
+ QTest::newRow("BaseOfYyy") << yyyPath << 3 << 1 << zzzPath << 2 << 0 << 9 << 1;
+ QTest::newRow("BaseOfIC") << yyyPath << 29 << 19 << zzzPath << 2 << 0 << 9 << 1;
+
+ QTest::newRow("PropertyType") << yyyPath << 30 << 14 << someBasePath << 2 << 0 << 4 << 1;
+
+ QTest::newRow("TypeInIC") << yyyPath << 29 << 36 << someBasePath << 2 << 0 << 4 << 1;
+ QTest::newRow("ICTypeDefinition") << yyyPath << 29 << 15 << yyyPath << 29 << 14 << 29 << 16;
+}
+
+void tst_qmlls_modules::goToTypeDefinition()
+{
+ QFETCH(QString, filePath);
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(QString, expectedFilePath);
+ QFETCH(int, expectedStartLine);
+ QFETCH(int, expectedStartCharacter);
+ QFETCH(int, expectedEndLine);
+ QFETCH(int, expectedEndCharacter);
+
+ ignoreDiagnostics();
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+ QVERIFY(uri->startsWith("file://"_ba));
+
+ // note: do not call openFile(expectedFilePath), the definition should be found even if
+ // the qmlls user did not open the qml file with the definition yet.
+ const auto expectedUri = testFileUrl(expectedFilePath).toEncoded();
+
+ // TODO
+ TypeDefinitionParams params;
+ params.position.line = line;
+ params.position.character = character;
+ params.textDocument.uri = *uri;
+
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ auto clean = [didFinish]() { *didFinish = true; };
+
+ m_protocol->requestTypeDefinition(
+ params,
+ [&](auto res) {
+ QScopeGuard cleanup(clean);
+ auto *result = std::get_if<QList<Location>>(&res);
+
+ QVERIFY(result);
+
+ QCOMPARE(result->size(), 1);
+
+ Location l = result->front();
+ QCOMPARE(l.uri, expectedUri);
+ QCOMPARE(l.range.start.line, expectedStartLine);
+ QCOMPARE(l.range.start.character, expectedStartCharacter);
+ QCOMPARE(l.range.end.line, expectedEndLine);
+ QCOMPARE(l.range.end.character, expectedEndCharacter);
+ },
+ [clean](const ResponseError &err) {
+ QScopeGuard cleanup(clean);
+ ProtocolBase::defaultResponseErrorHandler(err);
+ QVERIFY2(false, "error computing the completion");
+ });
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 30000);
+}
+
+void tst_qmlls_modules::goToDefinition_data()
+{
+ QTest::addColumn<QString>("filePath");
+ // keep in mind that line and character are starting at 1!
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+
+ QTest::addColumn<QByteArray>("expectedUri");
+ // set to -1 when unchanged from above line and character. 0-based.
+ QTest::addColumn<int>("expectedStartLine");
+ QTest::addColumn<int>("expectedStartCharacter");
+ QTest::addColumn<int>("expectedEndLine");
+ QTest::addColumn<size_t>("expectedEndCharacter");
+
+ const QByteArray JSDefinitionsQml =
+ testFileUrl(u"findDefinition/jsDefinitions.qml"_s).toEncoded();
+ const QString JSDefinitionsQmlPath = u"findDefinition/jsDefinitions.qml"_s;
+ const QByteArray noResultExpected;
+
+ QTest::addRow("JSIdentifierX") << JSDefinitionsQmlPath << 14 << 11 << JSDefinitionsQml << 13
+ << 13 << 13 << 13 + strlen("x");
+ QTest::addRow("propertyI") << JSDefinitionsQmlPath << 14 << 14 << JSDefinitionsQml << 9 << 18
+ << 9 << 18 + strlen("i");
+ QTest::addRow("qualifiedPropertyI") << JSDefinitionsQmlPath << 15 << 21 << JSDefinitionsQml << 9
+ << 18 << 9 << 18 + strlen("i");
+ QTest::addRow("id") << JSDefinitionsQmlPath << 15 << 17 << JSDefinitionsQml << 7 << 9 << 7
+ << 9 + strlen("rootId");
+
+ QTest::addRow("comment") << JSDefinitionsQmlPath << 10 << 21 << noResultExpected << -1 << -1
+ << -1 << size_t{};
+}
+
+void tst_qmlls_modules::goToDefinition()
+{
+ QFETCH(QString, filePath);
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(QByteArray, expectedUri);
+ QFETCH(int, expectedStartLine);
+ QFETCH(int, expectedStartCharacter);
+ QFETCH(int, expectedEndLine);
+ QFETCH(size_t, expectedEndCharacter);
+
+ ignoreDiagnostics();
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+ QVERIFY(uri->startsWith("file://"_ba));
+
+ DefinitionParams params;
+ params.position.line = line - 1;
+ params.position.character = character - 1;
+ params.textDocument.uri = *uri;
+
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ auto clean = [didFinish]() { *didFinish = true; };
+
+ m_protocol->requestDefinition(
+ params,
+ [&](auto res) {
+ QScopeGuard cleanup(clean);
+ auto *result = std::get_if<QList<Location>>(&res);
+ const QByteArray noResultExpected;
+
+ QVERIFY(result);
+ if (expectedUri == noResultExpected) {
+ QCOMPARE(result->size(), 0);
+ } else {
+ QCOMPARE(result->size(), 1);
+
+ Location l = result->front();
+ QCOMPARE(l.uri, expectedUri);
+ QCOMPARE(l.range.start.line, expectedStartLine - 1);
+ QCOMPARE(l.range.start.character, expectedStartCharacter - 1);
+ QCOMPARE(l.range.end.line, expectedEndLine - 1);
+ QCOMPARE(l.range.end.character, (int)(expectedEndCharacter - 1));
+ }
+ },
+ [clean](const ResponseError &err) {
+ QScopeGuard cleanup(clean);
+ ProtocolBase::defaultResponseErrorHandler(err);
+ QVERIFY2(false, "error computing the completion");
+ });
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 30000);
+}
+
+// startLine and startCharacter start at 1, not 0
+static QLspSpecification::Range rangeFrom(const QString &code, quint32 startLine,
+ quint32 startCharacter, quint32 length)
+{
+ QLspSpecification::Range range;
+
+ // the LSP works with lines and characters starting at 0
+ range.start.line = startLine - 1;
+ range.start.character = startCharacter - 1;
+
+ quint32 startOffset = QQmlLSUtils::textOffsetFrom(code, startLine - 1, startCharacter - 1);
+ auto end = QQmlLSUtils::textRowAndColumnFrom(code, startOffset + length);
+ range.end.line = end.line;
+ range.end.character = end.character;
+
+ return range;
+}
+
+// startLine and startCharacter start at 1, not 0
+static QLspSpecification::Location locationFrom(const QByteArray fileName, const QString &code,
+ quint32 startLine, quint32 startCharacter,
+ quint32 length)
+{
+ QLspSpecification::Location location;
+ location.uri = QQmlLSUtils::qmlUrlToLspUri(fileName);
+ location.range = rangeFrom(code, startLine, startCharacter, length);
+ return location;
+}
+
+void tst_qmlls_modules::findUsages_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+ QTest::addColumn<QList<QLspSpecification::Location>>("expectedUsages");
+
+ const QByteArray jsIdentifierUsagesUri =
+ testFileUrl("findUsages/jsIdentifierUsages.qml").toEncoded();
+ const QString jsIdentifierUsagesPath = u"findUsages/jsIdentifierUsages.qml"_s;
+
+ QString jsIdentifierUsagesContent;
+ {
+ QFile file(testFile("findUsages/jsIdentifierUsages.qml").toUtf8());
+ QVERIFY(file.open(QIODeviceBase::ReadOnly));
+ jsIdentifierUsagesContent = QString::fromUtf8(file.readAll());
+ }
+
+ // line and character start at 1!
+ const QList<QLspSpecification::Location> sumUsages = {
+ locationFrom(jsIdentifierUsagesUri, jsIdentifierUsagesContent, 8, 13, strlen("sum")),
+ locationFrom(jsIdentifierUsagesUri, jsIdentifierUsagesContent, 10, 13, strlen("sum")),
+ locationFrom(jsIdentifierUsagesUri, jsIdentifierUsagesContent, 10, 19, strlen("sum")),
+ };
+ QVERIFY(sumUsages.front().uri.startsWith("file://"_ba));
+
+ // line and character start at 1!
+ QTest::addRow("sumUsagesFromUsage") << jsIdentifierUsagesPath << 10 << 14 << sumUsages;
+ QTest::addRow("sumUsagesFromUsage2") << jsIdentifierUsagesPath << 10 << 20 << sumUsages;
+ QTest::addRow("sumUsagesFromDefinition") << jsIdentifierUsagesPath << 8 << 14 << sumUsages;
+}
+
+static bool locationsAreEqual(const QLspSpecification::Location &a,
+ const QLspSpecification::Location &b)
+{
+ return std::tie(a.uri, a.range.start.character, a.range.start.line, a.range.end.character,
+ a.range.end.line)
+ == std::tie(b.uri, b.range.start.character, b.range.start.line, b.range.end.character,
+ b.range.end.line);
+}
+
+static bool locationListsAreEqual(const QList<QLspSpecification::Location> &a,
+ const QList<QLspSpecification::Location> &b)
+{
+ return std::equal(a.cbegin(), a.cend(), b.cbegin(), b.cend(), locationsAreEqual);
+}
+
+static QString locationToString(const QLspSpecification::Location &l)
+{
+ QString s = u"%1: (%2, %3) - (%4, %5)"_s.arg(l.uri)
+ .arg(l.range.start.line)
+ .arg(l.range.start.character)
+ .arg(l.range.end.line)
+ .arg(l.range.end.character);
+ return s;
+}
+
+void tst_qmlls_modules::findUsages()
+{
+ QFETCH(QString, filePath);
+ // line and character start at 1!
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(QList<QLspSpecification::Location>, expectedUsages);
+
+ ignoreDiagnostics();
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+ QVERIFY(uri->startsWith("file://"_ba));
+
+ ReferenceParams params;
+ params.position.line = line - 1;
+ params.position.character = character - 1;
+ params.textDocument.uri = *uri;
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ auto clean = [didFinish]() { *didFinish = true; };
+ m_protocol->requestReference(
+ params,
+ [&](auto res) {
+ QScopeGuard cleanup(clean);
+ auto *result = std::get_if<QList<Location>>(&res);
+
+ QVERIFY(result);
+ if constexpr (enable_debug_output) {
+ if (!locationListsAreEqual(*result, expectedUsages)) {
+ qDebug() << "Got following locations:";
+ for (auto &x : *result) {
+ qDebug() << locationToString(x);
+ }
+ qDebug() << "But expected:";
+ for (auto &x : expectedUsages) {
+ qDebug() << locationToString(x);
+ }
+ }
+ } else {
+ // dont get warning on unused function when enable_debug_output is false
+ Q_UNUSED(locationToString);
+ }
+
+ QVERIFY(locationListsAreEqual(*result, expectedUsages));
+ },
+ [clean](const ResponseError &err) {
+ QScopeGuard cleanup(clean);
+ ProtocolBase::defaultResponseErrorHandler(err);
+ QVERIFY2(false, "error computing the completion");
+ });
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 3000);
+}
+
+void tst_qmlls_modules::documentFormatting_data()
+{
+ QTest::addColumn<QString>("originalFile");
+ QTest::addColumn<QString>("expectedFile");
+
+ QDir directory(QT_QMLFORMATTEST_DATADIR);
+
+ // Exclude some test files which require options support
+ QStringList excludedFiles;
+ excludedFiles << u"tests/auto/qml/qmlformat/data/checkIdsNewline.qml"_s;
+ excludedFiles << u"tests/auto/qml/qmlformat/data/normalizedFunctionsSpacing.qml"_s;
+ excludedFiles << u"tests/auto/qml/qmlformat/data/normalizedObjectsSpacing.qml"_s;
+
+ // excluded because it crashes Dom construction
+ // TODO: fix QQMLDomAstConstructor to not crash on these files, see QTBUG-116392
+ excludedFiles << u"tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.qml"_s;
+ excludedFiles << u"tests/auto/qml/qmlformat/data/Example1.qml"_s;
+ excludedFiles << u"tests/auto/qml/qmlformat/data/nestedFunctions.qml"_s;
+
+ const auto shouldSkip = [&excludedFiles](const QString &fileName) {
+ for (const QString &file : excludedFiles) {
+ if (fileName.endsWith(file))
+ return true;
+ }
+ return false;
+ };
+
+ // Filter to include files contain .formatted.
+ const auto formattedFilesInfo =
+ directory.entryInfoList(QStringList{ { "*.formatted.qml" } }, QDir::Files);
+ for (const auto &formattedFileInfo : formattedFilesInfo) {
+ const QFileInfo unformattedFileInfo(directory, formattedFileInfo.fileName().remove(".formatted"));
+ const auto unformattedFilePath = unformattedFileInfo.canonicalFilePath();
+ if (shouldSkip(unformattedFilePath))
+ continue;
+
+ QTest::newRow(qPrintable(unformattedFileInfo.fileName()))
+ << unformattedFilePath << formattedFileInfo.canonicalFilePath();
+ }
+
+ // Extra tests
+ QTest::newRow("leading-and-trailing-blanklines")
+ << testFile("formatting/blanklines.qml")
+ << testFile("formatting/blanklines.formatted.qml");
+}
+
+void tst_qmlls_modules::documentFormatting()
+{
+ QFETCH(QString, originalFile);
+ QFETCH(QString, expectedFile);
+
+ ignoreDiagnostics();
+
+ const auto uri = openFileFromAbsolutePath(originalFile);
+ QVERIFY(uri);
+
+ DocumentFormattingParams params;
+ params.textDocument.uri = *uri;
+
+ const auto lineCount = [](const QString &filePath) {
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning() << "Error while opening the file " << filePath;
+ return -1;
+ }
+ int lineCount = 0;
+ QString line;
+ while (!file.atEnd()) {
+ line = file.readLine();
+ ++lineCount;
+ }
+ if (line.endsWith('\n'))
+ ++lineCount;
+ return lineCount;
+ };
+
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ auto clean = [didFinish]() { *didFinish = true; };
+ auto &&responseHandler = [&](auto response) {
+ QScopeGuard cleanup(clean);
+ if (std::holds_alternative<QList<TextEdit>>(response)) {
+ const auto results = std::get<QList<TextEdit>>(response);
+ QVERIFY(results.size() == 1);
+ QFile file(expectedFile);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning() << "Error while opening the file " << expectedFile;
+ return;
+ }
+
+ const auto &textEdit = results.first();
+ QCOMPARE(textEdit.range.start.line, 0);
+ QCOMPARE(textEdit.range.start.character, 0);
+ QCOMPARE(textEdit.range.end.line, lineCount(originalFile));
+ QCOMPARE(textEdit.range.end.character, 0);
+ QCOMPARE(textEdit.newText, file.readAll());
+ }
+ };
+
+ auto &&errorHandler = [&clean](const ResponseError &err) {
+ QScopeGuard cleanup(clean);
+ ProtocolBase::defaultResponseErrorHandler(err);
+ QVERIFY2(false, "error computing the completion");
+ };
+ m_protocol->requestDocumentFormatting(params, std::move(responseHandler),
+ std::move(errorHandler));
+
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 50000);
+}
+
+void tst_qmlls_modules::renameUsages_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+ QTest::addColumn<QString>("newName");
+ QTest::addColumn<QLspSpecification::WorkspaceEdit>("expectedEdit");
+ QTest::addColumn<QLspSpecification::ResponseError>("expectedError");
+
+ QLspSpecification::ResponseError noError;
+
+ const QString jsIdentifierUsagesPath = u"findUsages/jsIdentifierUsages.qml"_s;
+ const QByteArray jsIdentifierUsagesUri =
+ testFileUrl("findUsages/jsIdentifierUsages.qml").toEncoded();
+
+ QString jsIdentifierUsagesContent;
+ {
+ QFile file(testFile("findUsages/jsIdentifierUsages.qml").toUtf8());
+ QVERIFY(file.open(QIODeviceBase::ReadOnly));
+ jsIdentifierUsagesContent = QString::fromUtf8(file.readAll());
+ }
+ QString renamingContent;
+ {
+ QFile file(testFile("renameUsages/main.qml").toUtf8());
+ QVERIFY(file.open(QIODeviceBase::ReadOnly));
+ renamingContent = QString::fromUtf8(file.readAll());
+ }
+
+ // TODO: create workspace edit for the tests
+ QLspSpecification::WorkspaceEdit sumRenames{
+ std::nullopt, // TODO
+ QList<QLspSpecification::WorkspaceEdit::DocumentChange>{
+ TextDocumentEdit{
+ OptionalVersionedTextDocumentIdentifier{ { jsIdentifierUsagesUri } },
+ {
+ TextEdit{
+ rangeFrom(jsIdentifierUsagesContent, 8, 13, strlen("sum")),
+ "specialSum" },
+ TextEdit{
+ rangeFrom(jsIdentifierUsagesContent, 10, 13, strlen("sum")),
+ "specialSum" },
+ TextEdit{
+ rangeFrom(jsIdentifierUsagesContent, 10, 19, strlen("sum")),
+ "specialSum" },
+ } },
+ }
+ };
+
+ // line and character start at 1!
+ QTest::addRow("sumRenameFromUsage")
+ << jsIdentifierUsagesPath << 10 << 14 << u"specialSum"_s << sumRenames << noError;
+ QTest::addRow("sumRenameFromUsage2")
+ << jsIdentifierUsagesPath << 10 << 20 << u"specialSum"_s << sumRenames << noError;
+ QTest::addRow("sumRenameFromDefinition")
+ << jsIdentifierUsagesPath << 8 << 14 << u"specialSum"_s << sumRenames << noError;
+ QTest::addRow("invalidSumRenameFromDefinition")
+ << jsIdentifierUsagesPath << 8 << 14 << u"function"_s << sumRenames
+ << QLspSpecification::ResponseError{
+ 0,
+ "Invalid EcmaScript identifier!",
+ std::nullopt,
+ };
+
+ const QString renameUsagesPath = u"renameUsages/main.qml"_s;
+ const QByteArray renameUsagesUri = testFileUrl("renameUsages/main.qml").toEncoded();
+ const QByteArray renameMeUri = testFileUrl("renameUsages/RenameMe.qml").toEncoded();
+ const QByteArray renameMe2Uri = testFileUrl("renameUsages/RenameMe2.ui.qml").toEncoded();
+
+ const QByteArray newFileUri = testFileUrl("renameUsages/HelloWorld.qml").toEncoded();
+ const QByteArray newFileUri2 = testFileUrl("renameUsages/HelloWorld.ui.qml").toEncoded();
+
+ {
+
+ const QLspSpecification::WorkspaceEdit qmlComponentRename{
+ std::nullopt,
+ QList<QLspSpecification::WorkspaceEdit::DocumentChange>{
+ TextDocumentEdit{
+ OptionalVersionedTextDocumentIdentifier{ { renameUsagesUri } },
+ {
+ TextEdit{ rangeFrom(renamingContent, 4, 5,
+ strlen("RenameMe")),
+ "HelloWorld" },
+ } },
+ RenameFile{ "rename", renameMeUri, newFileUri } }
+ };
+
+ QTest::addRow("renameQmlComponent")
+ << renameUsagesPath << 4 << 8 << u"HelloWorld"_s << qmlComponentRename << noError;
+ }
+
+ {
+ QLspSpecification::WorkspaceEdit qmlComponentRename{
+ std::nullopt,
+ QList<QLspSpecification::WorkspaceEdit::DocumentChange>{
+ TextDocumentEdit{
+ OptionalVersionedTextDocumentIdentifier{ { renameUsagesUri } },
+ {
+ TextEdit{ rangeFrom(renamingContent, 5, 5,
+ strlen("RenameMe2")),
+ "HelloWorld" },
+ } },
+ RenameFile{ "rename", renameMe2Uri, newFileUri2 } }
+ };
+
+ QTest::addRow("renameUiQmlComponent")
+ << renameUsagesPath << 5 << 8 << u"HelloWorld"_s << qmlComponentRename << noError;
+ }
+}
+
+void tst_qmlls_modules::compareQTextDocumentEdit(const TextDocumentEdit &a,
+ const TextDocumentEdit &b)
+{
+
+ QCOMPARE(a.textDocument.uri, b.textDocument.uri);
+ QVERIFY(a.textDocument.uri.startsWith("file://"));
+ QCOMPARE(a.textDocument.version, b.textDocument.version);
+ QCOMPARE(a.edits.size(), b.edits.size());
+
+ for (qsizetype j = 0; j < a.edits.size(); ++j) {
+ std::visit(
+ [](auto &&textEdit, auto &&expectedTextEdit) {
+ using U = std::decay_t<decltype(textEdit)>;
+ using V = std::decay_t<decltype(expectedTextEdit)>;
+
+ if constexpr (std::conjunction_v<std::is_same<U, V>,
+ std::is_same<U, TextEdit>>) {
+ QCOMPARE(textEdit.range.start.line, expectedTextEdit.range.start.line);
+ QCOMPARE(textEdit.range.start.character,
+ expectedTextEdit.range.start.character);
+ QCOMPARE(textEdit.range.end.line, expectedTextEdit.range.end.line);
+ QCOMPARE(textEdit.range.end.character,
+ expectedTextEdit.range.end.character);
+ QCOMPARE(textEdit.newText, expectedTextEdit.newText);
+ } else {
+ QFAIL("Comparison not implemented");
+ }
+ },
+ a.edits[j], b.edits[j]);
+ }
+}
+
+void tst_qmlls_modules::renameUsages()
+{
+ QFETCH(QString, filePath);
+ // line and character start at 1!
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(QString, newName);
+ QFETCH(QLspSpecification::WorkspaceEdit, expectedEdit);
+ QFETCH(QLspSpecification::ResponseError, expectedError);
+
+ ignoreDiagnostics();
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+ QVERIFY(uri->startsWith("file://"_ba));
+
+ RenameParams params;
+ params.position.line = line - 1;
+ params.position.character = character - 1;
+ params.textDocument.uri = *uri;
+ params.newName = newName.toUtf8();
+
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ auto clean = [didFinish]() { *didFinish = true; };
+ m_protocol->requestRename(
+ params,
+ [&](auto &&res) {
+ QScopeGuard cleanup(clean);
+ auto *result = std::get_if<QLspSpecification::WorkspaceEdit>(&res);
+
+ QVERIFY(result);
+ QCOMPARE(result->changes.has_value(), expectedEdit.changes.has_value());
+ QCOMPARE(result->changeAnnotations.has_value(),
+ expectedEdit.changeAnnotations.has_value());
+ QCOMPARE(result->documentChanges.has_value(),
+ expectedEdit.documentChanges.has_value());
+
+ auto &documentChanges = *result->documentChanges;
+ auto &expectedDocumentChanges = *expectedEdit.documentChanges;
+
+ if (!expectedError.message.isEmpty())
+ QVERIFY2(false, "No expected error was thrown.");
+
+ QCOMPARE(documentChanges.size(), expectedDocumentChanges.size());
+
+ for (qsizetype i = 0; i < expectedDocumentChanges.size(); ++i) {
+ QCOMPARE(documentChanges[i].index(), expectedDocumentChanges[i].index());
+ if (std::holds_alternative<TextDocumentEdit>(documentChanges[i])) {
+ compareQTextDocumentEdit(
+ std::get<TextDocumentEdit>(documentChanges[i]),
+ std::get<TextDocumentEdit>(expectedDocumentChanges[i]));
+ } else if (std::holds_alternative<RenameFile>(documentChanges[i])) {
+ const auto &actual = std::get<RenameFile>(documentChanges[i]);
+ const auto &expected = std::get<RenameFile>(expectedDocumentChanges[i]);
+
+ QCOMPARE(actual.kind, expected.kind);
+ QCOMPARE(expected.kind, "rename");
+ QCOMPARE(actual.oldUri, expected.oldUri);
+ QCOMPARE(actual.newUri, expected.newUri);
+ QCOMPARE(actual.options.has_value(), expected.options.has_value());
+ if (expected.options.has_value()) {
+ QCOMPARE(actual.options->overwrite, expected.options->overwrite);
+ QCOMPARE(actual.options->ignoreIfExists,
+ expected.options->ignoreIfExists);
+ }
+ QCOMPARE(actual.annotationId, expected.annotationId);
+
+ } else {
+ QFAIL("TODO: implement me!");
+ }
+ }
+ },
+ [clean, &expectedError](const ResponseError &err) {
+ QScopeGuard cleanup(clean);
+ ProtocolBase::defaultResponseErrorHandler(err);
+ if (expectedError.message.isEmpty())
+ QVERIFY2(false, "unexpected error computing the completion");
+ QCOMPARE(err.code, expectedError.code);
+ QCOMPARE(err.message, expectedError.message);
+ });
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 3000);
+}
+
+struct EditingRecorder
+{
+ QList<DidChangeTextDocumentParams> actions;
+ QHash<int, QString> diagnosticsPerFileVersions;
+
+ /*!
+ All the indexes passed here must start at 1!
+
+ If you want to make sure that your own written changes make sense, use
+ \code
+ qputenv("QT_LOGGING_RULES",
+ "qt.languageserver.codemodel.debug=true;qt.languageserver.codemodel.warning=true"); \endcode
+ before starting qmlls. It will print the differences between the different versions, and helps
+ when some indices are off.
+ */
+ void changeText(int startLine, int startCharacter, int endLine, int endCharacter,
+ QString newText)
+ {
+ // The LSP starts at 0
+ QVERIFY(startLine > 0);
+ QVERIFY(startCharacter > 0);
+ QVERIFY(endLine > 0);
+ QVERIFY(endCharacter > 0);
+
+ --startLine;
+ --startCharacter;
+ --endLine;
+ --endCharacter;
+
+ DidChangeTextDocumentParams params;
+ params.textDocument = VersionedTextDocumentIdentifier{ { lastFileUri }, ++version };
+ params.contentChanges.append({
+ Range{ Position{ startLine, startCharacter }, Position{ endLine, endCharacter } },
+ std::nullopt, // deprecated range length
+ newText.toUtf8(),
+ });
+ actions.append(params);
+ }
+
+ void setFile(const QString &filePath) { lastFilePath = filePath; }
+
+ void setCurrentExpectedDiagnostic(const QString &diagnostic)
+ {
+ Q_ASSERT(diagnosticsPerFileVersions.find(version) == diagnosticsPerFileVersions.end());
+ diagnosticsPerFileVersions[version] = diagnostic;
+ }
+
+ QString lastFilePath;
+ QByteArray lastFileUri;
+ int version = 0;
+};
+
+static constexpr int characterAfter(const char *line)
+{
+ return std::char_traits<char>::length(line) + 1;
+}
+
+static EditingRecorder propertyTypoScenario(const QByteArray &fileUri)
+{
+ EditingRecorder propertyTypo;
+ propertyTypo.lastFileUri = fileUri;
+
+ propertyTypo.changeText(5, 1, 5, 1, u" property int t"_s);
+
+ // replace property by propertyt and expect a complaint from the parser
+ propertyTypo.changeText(5, characterAfter(" property"), 5, characterAfter(" property"),
+ u"t"_s);
+ propertyTypo.setCurrentExpectedDiagnostic(u"Expected token"_s);
+
+ // replace propertyt back to property and expect no complaint from the parser
+ propertyTypo.changeText(5, characterAfter(" property"), 5, characterAfter(" propertyt"),
+ u""_s);
+
+ // replace property by propertyt and expect a complaint from the parser
+ propertyTypo.changeText(5, characterAfter(" property"), 5, characterAfter(" property"),
+ u"t"_s);
+ propertyTypo.setCurrentExpectedDiagnostic(u"Expected token"_s);
+
+ // now, simulate some slow typing and expect the previous warning to not disappear
+ const QString data = u"Item {}\n"_s;
+ for (int i = 0; i < data.size(); ++i) {
+ propertyTypo.changeText(6, i + 1, 6, i + 1, data[i]);
+ propertyTypo.setCurrentExpectedDiagnostic(u"Expected token"_s);
+ }
+
+ // replace propertyt back to property and expect no complaint from the parser
+ propertyTypo.changeText(5, characterAfter(" property"), 5, characterAfter(" propertyt"),
+ u""_s);
+
+ return propertyTypo;
+}
+
+void tst_qmlls_modules::linting_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<EditingRecorder>("recorder");
+
+ QTest::addRow("property-typo")
+ << u"linting/SimpleItem.qml"_s
+ << propertyTypoScenario(testFileUrl(u"linting/SimpleItem.qml"_s).toEncoded());
+}
+
+void tst_qmlls_modules::linting()
+{
+ QFETCH(QString, filePath);
+ QFETCH(EditingRecorder, recorder);
+ bool diagnosticOk = false;
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+ recorder.lastFileUri = *uri;
+ m_protocol->registerPublishDiagnosticsNotificationHandler(
+ [&recorder, &diagnosticOk, &uri](const QByteArray &,
+ const PublishDiagnosticsParams &p) {
+ if (p.uri != *uri || !p.version)
+ return;
+ auto expectedMessage = recorder.diagnosticsPerFileVersions.find(*p.version);
+ if (expectedMessage == recorder.diagnosticsPerFileVersions.end()) {
+ if constexpr (enable_debug_output) {
+ if (p.diagnostics.size() > 0)
+ qDebug() << "Did not expect message" << p.diagnostics.front().message;
+ }
+
+ QVERIFY(p.diagnostics.size() == 0);
+ diagnosticOk = true;
+ return;
+ }
+ QVERIFY(p.diagnostics.size() > 0);
+ if constexpr (enable_debug_output) {
+ if (!p.diagnostics.front().message.contains(expectedMessage->toUtf8())) {
+ qDebug() << "expected a message with" << *expectedMessage << "but got"
+ << p.diagnostics.front().message;
+ }
+ }
+ QVERIFY(p.diagnostics.front().message.contains(expectedMessage->toUtf8()));
+ diagnosticOk = true;
+ });
+ for (const auto &action : recorder.actions) {
+ m_protocol->notifyDidChangeTextDocument(action);
+ QTRY_VERIFY_WITH_TIMEOUT(diagnosticOk, 5000);
+ diagnosticOk = false;
+ }
+}
+
+void tst_qmlls_modules::rangeFormatting_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<QLspSpecification::Range>("selectedRange");
+ QTest::addColumn<QLspSpecification::Range>("expectedRange");
+ QTest::addColumn<QString>("expectedAfterFormat");
+
+ const QString filePath = u"formatting/rangeFormatting.qml"_s;
+
+ {
+ QLspSpecification::Range selectedRange = { { 5, 0 }, { 9, 0 } };
+ QLspSpecification::Range expectedRange = { { 0, 0 }, { 24, 0 } };
+ QTest::addRow("selectRegion1") << filePath << selectedRange << expectedRange
+ << u"formatting/rangeFormatting.formatted1.qml"_s;
+ }
+
+ {
+ QLspSpecification::Range selectedRange = { { 10, 25 }, { 23, 0 } };
+ QLspSpecification::Range expectedRange = { { 0, 0 }, { 24, 0 } };
+ QTest::addRow("selectRegion2") << filePath << selectedRange << expectedRange
+ << u"formatting/rangeFormatting.formatted2.qml"_s;
+ }
+
+ {
+ QLspSpecification::Range selectedRange = { { 14, 36 }, { 14, 45 } };
+ QLspSpecification::Range expectedRange = { { 0, 0 }, { 24, 0 } };
+ QTest::addRow("selectSingleLine") << filePath << selectedRange << expectedRange
+ << u"formatting/rangeFormatting.formatted3.qml"_s;
+ }
+
+ {
+ QLspSpecification::Range selectedRange = { { 0, 0 }, { 24, 0 } };
+ QLspSpecification::Range expectedRange = { { 0, 0 }, { 24, 0 } };
+ QTest::addRow("selectEntireFile") << filePath << selectedRange << expectedRange
+ << u"formatting/rangeFormatting.formatted4.qml"_s;
+ }
+
+ {
+ QLspSpecification::Range selectedRange = { { 10, 3 }, { 20, 4 } };
+ QLspSpecification::Range expectedRange = { { 0, 0 }, { 24, 0 } };
+ QTest::addRow("selectUnbalanced") << filePath << selectedRange << expectedRange
+ << u"formatting/rangeFormatting.formatted5.qml"_s;
+ }
+}
+
+void tst_qmlls_modules::rangeFormatting()
+{
+ QFETCH(QString, filePath);
+ QFETCH(QLspSpecification::Range, selectedRange);
+ QFETCH(QLspSpecification::Range, expectedRange);
+ QFETCH(QString, expectedAfterFormat);
+
+ ignoreDiagnostics();
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+
+ QLspSpecification::DocumentRangeFormattingParams params;
+ params.textDocument.uri = *uri;
+ params.range = selectedRange;
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ const auto clean = [didFinish]() { *didFinish = true; };
+
+ auto &&responseHandler = [&](auto res) {
+ Q_UNUSED(res);
+ QScopeGuard cleanup(clean);
+ auto result = std::get_if<QList<TextEdit>>(&res);
+ QVERIFY(result);
+
+ QFile file(testFile(expectedAfterFormat));
+ if (!file.open(QIODevice::ReadOnly))
+ QFAIL("Error while opening the file ");
+
+ const auto text = result->first();
+ QCOMPARE(text.range.start.line, expectedRange.start.line);
+ QCOMPARE(text.range.start.character, expectedRange.start.character);
+ QCOMPARE(text.range.end.line, expectedRange.end.line);
+ QCOMPARE(text.range.end.character, expectedRange.end.character);
+ QCOMPARE(text.newText, file.readAll());
+ };
+
+ auto &&errorHandler = [&clean](auto &error) {
+ QScopeGuard cleanup(clean);
+ ProtocolBase::defaultResponseErrorHandler(error);
+ QVERIFY2(false, "error occurred while range formatting");
+ };
+
+ m_protocol->requestDocumentRangeFormatting(params, std::move(responseHandler),
+ std::move(errorHandler));
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 10000);
+}
+
+void tst_qmlls_modules::hover_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<QLspSpecification::Position>("hoveredPosition");
+ QTest::addColumn<QLspSpecification::MarkupContent>("expectedResult");
+
+ const QString filePath = u"hover/test.qml"_s;
+ {
+ QLspSpecification::MarkupContent content{ MarkupKind::PlainText, "should fail" };
+ QTest::addRow("hover") << filePath << QLspSpecification::Position{ 7, 24 } << content;
+ }
+}
+
+void tst_qmlls_modules::hover()
+{
+ QFETCH(QString, filePath);
+ QFETCH(QLspSpecification::Position, hoveredPosition);
+ QFETCH(QLspSpecification::MarkupContent, expectedResult);
+
+ ignoreDiagnostics();
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+
+ QLspSpecification::HoverParams params;
+ params.textDocument.uri = *uri;
+ params.position = hoveredPosition;
+
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ const auto clean = [didFinish]() { *didFinish = true; };
+
+ auto &&responseHandler = [&](auto res) {
+ QScopeGuard cleanup(clean);
+ const auto *const result = std::get_if<QLspSpecification::Hover>(&res);
+ QVERIFY(result);
+
+ const auto *const markupContent =
+ std::get_if<QLspSpecification::MarkupContent>(&result->contents);
+ QVERIFY(markupContent);
+
+ QEXPECT_FAIL("hover", "Should fail until we get the actual documentation for hovered items",
+ Continue);
+ QCOMPARE(markupContent->value, expectedResult.value);
+ QCOMPARE(markupContent->kind, expectedResult.kind);
+ };
+
+ auto &&errorHandler = [&clean](auto &error) {
+ QScopeGuard cleanup(clean);
+ ProtocolBase::defaultResponseErrorHandler(error);
+ QVERIFY2(false, "error occurred on hovering");
+ };
+
+ m_protocol->requestHover(params, std::move(responseHandler), std::move(errorHandler));
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 10000);
+}
+
+enum AddBuildDirOption : bool { AddBuildDir, DoNotAddBuildDir };
+
+void tst_qmlls_modules::qmldirImports_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<AddBuildDirOption>("addBuildDirectory");
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+ QTest::addColumn<QString>("expectedCompletion");
+
+ QTest::addRow("fromBuildFolder")
+ << u"completions/fromBuildDir.qml"_s << AddBuildDir << 3 << 1 << u"BuildDirType"_s;
+ QTest::addRow("fromSourceFolder")
+ << u"sourceDir/Main.qml"_s << DoNotAddBuildDir << 3 << 1 << u"Button"_s;
+}
+
+void tst_qmlls_modules::qmldirImports()
+{
+ QFETCH(QString, filePath);
+ QFETCH(AddBuildDirOption, addBuildDirectory);
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(QString, expectedCompletion);
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+
+ if (addBuildDirectory == AddBuildDir) {
+ Notifications::AddBuildDirsParams bDirs;
+ UriToBuildDirs ub;
+ ub.baseUri = *uri;
+ ub.buildDirs.append(testFile("buildDir").toUtf8());
+ bDirs.buildDirsToSet.append(ub);
+ m_protocol->typedRpc()->sendNotification(QByteArray(Notifications::AddBuildDirsMethod), bDirs);
+ }
+
+ bool diagnosticOk = false;
+ bool completionOk = false;
+ m_protocol->registerPublishDiagnosticsNotificationHandler(
+ [&diagnosticOk, &uri](const QByteArray &, const PublishDiagnosticsParams &p) {
+ if (p.uri != *uri)
+ return;
+
+ if constexpr (enable_debug_output) {
+ for (const auto &x : p.diagnostics) {
+ qDebug() << x.message;
+ }
+ }
+ QCOMPARE(p.diagnostics.size(), 0);
+ diagnosticOk = true;
+ });
+
+ // Currently, the Dom is created twice in qmlls: once for the linting and once for all other
+ // features. Therefore, also test that this second dom also uses the right resource files.
+ CompletionParams cParams;
+ cParams.position.line = line - 1; // LSP is 0 based
+ cParams.position.character = character - 1; // LSP is 0 based
+ cParams.textDocument.uri = *uri;
+
+ m_protocol->requestCompletion(cParams, [&completionOk, &expectedCompletion](auto res) {
+ const QList<CompletionItem> *cItems = std::get_if<QList<CompletionItem>>(&res);
+
+ QSet<QString> labels;
+ for (const CompletionItem &c : *cItems) {
+ labels << c.label;
+ }
+ QVERIFY(labels.contains(expectedCompletion));
+ completionOk = true;
+ });
+
+ QTRY_VERIFY_WITH_TIMEOUT(diagnosticOk && completionOk, 5000);
+}
+
+void tst_qmlls_modules::quickFixes_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<CodeActionParams>("codeActionParams");
+ QTest::addColumn<int>("diagnosticIndex");
+ QTest::addColumn<Range>("replacementRange");
+ QTest::addColumn<QString>("replacementText");
+
+ const QString filePath = u"quickfixes/INeedAQuickFix.qml"_s;
+
+ QString fileContent;
+ {
+ QFile file(testFile(filePath));
+ QVERIFY(file.open(QFile::Text | QFile::ReadOnly));
+ fileContent = file.readAll();
+ }
+
+ CodeActionParams firstCodeAction;
+ firstCodeAction.range = rangeFrom(fileContent, 10, 23, 1);
+ firstCodeAction.textDocument.uri = testFileUrl(filePath).toEncoded();
+
+ const Range firstRange = rangeFrom(fileContent, 10, 10, 0);
+ const QString firstReplacement = u"(xxx) => "_s;
+
+ QTest::addRow("injectedParameters")
+ << filePath << firstCodeAction << 0 << firstRange << firstReplacement;
+
+ CodeActionParams secondCodeAction;
+ secondCodeAction.textDocument.uri = testFileUrl(filePath).toEncoded();
+ secondCodeAction.range = rangeFrom(fileContent, 15, 20, 1);
+
+ const Range secondRange = rangeFrom(fileContent, 15, 20, 0);
+ const QString secondReplacement = u"hello."_s;
+
+ QTest::addRow("parentProperty")
+ << filePath << secondCodeAction << 1 << secondRange << secondReplacement;
+}
+
+std::tuple<int, int, int, int> rangeAsTuple(const Range &range)
+{
+ return std::make_tuple(range.start.line, range.start.character, range.end.line,
+ range.end.character);
+}
+
+void tst_qmlls_modules::quickFixes()
+{
+ QFETCH(QString, filePath);
+ QFETCH(CodeActionParams, codeActionParams);
+ // The index of the diagnostic that the quickFix belongs to.
+ // diagnostics are sorted by their range (= text position in the current file).
+ QFETCH(int, diagnosticIndex);
+ QFETCH(Range, replacementRange);
+ QFETCH(QString, replacementText);
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+
+ bool diagnosticOk = false;
+ QList<Diagnostic> diagnostics;
+
+ // run first the diagnostic that proposes a quickfix
+ m_protocol->registerPublishDiagnosticsNotificationHandler(
+ [&diagnosticOk, &uri, &diagnostics,
+ &diagnosticIndex](const QByteArray &, const PublishDiagnosticsParams &p) {
+ if (p.uri != *uri)
+ return;
+
+ if constexpr (enable_debug_output) {
+ for (const auto &x : p.diagnostics) {
+ qDebug() << x.message;
+ }
+ }
+ QCOMPARE_GE(p.diagnostics.size(), diagnosticIndex);
+
+ QList<Diagnostic> partially_sorted{ p.diagnostics };
+ std::nth_element(partially_sorted.begin(),
+ std::next(partially_sorted.begin(), diagnosticIndex),
+ partially_sorted.end(),
+ [](const Diagnostic &a, const Diagnostic &b) {
+ return rangeAsTuple(a.range) < rangeAsTuple(b.range);
+ });
+ diagnostics.append(partially_sorted[diagnosticIndex]);
+
+ diagnosticOk = true;
+ });
+
+ QTRY_VERIFY_WITH_TIMEOUT(diagnosticOk, 5000);
+
+ codeActionParams.context.diagnostics = diagnostics;
+
+ using InnerT = QList<std::variant<Command, CodeAction>>;
+ using T = std::variant<InnerT, std::nullptr_t>;
+
+ bool codeActionOk = false;
+
+ // request a quickfix with the obtained diagnostic
+ m_protocol->requestCodeAction(codeActionParams, [&](const T &result) {
+ QVERIFY(std::holds_alternative<InnerT>(result));
+ InnerT inner = std::get<InnerT>(result);
+ QCOMPARE(inner.size(), 1);
+ QVERIFY(std::holds_alternative<CodeAction>(inner.front()));
+ CodeAction codeAction = std::get<CodeAction>(inner.front());
+
+ QCOMPARE(codeAction.kind, "quickfix"); // everything else is ignored by QtC, VS Code, ...
+
+ QVERIFY(codeAction.edit);
+ QVERIFY(codeAction.edit->documentChanges);
+ const auto &edits = *codeAction.edit->documentChanges;
+ QCOMPARE(edits.size(), 1);
+ const auto& firstEdit = std::get<TextDocumentEdit>(edits.front());
+ QCOMPARE(firstEdit.edits.size(), 1);
+ QVERIFY(std::holds_alternative<TextEdit>(firstEdit.edits.front()));
+ auto textEdit = std::get<TextEdit>(firstEdit.edits.front());
+
+ // make sure that the quick fix does something
+ QCOMPARE(textEdit.newText, replacementText);
+ QCOMPARE(rangeAsTuple(textEdit.range), rangeAsTuple(replacementRange));
+
+ codeActionOk = true;
+ });
+
+ QTRY_VERIFY_WITH_TIMEOUT(codeActionOk, 5000);
+}
+
+static QQmlJS::Dom::DomItem fileObject(const QString &filePath)
+{
+ QFile f(filePath);
+ QQmlJS::Dom::DomItem file;
+ if (!f.open(QIODevice::ReadOnly))
+ return file;
+ QString code = f.readAll();
+ QQmlJS::Dom::DomCreationOptions options;
+ options.setFlag(QQmlJS::Dom::DomCreationOption::WithScriptExpressions);
+ options.setFlag(QQmlJS::Dom::DomCreationOption::WithSemanticAnalysis);
+ options.setFlag(QQmlJS::Dom::DomCreationOption::WithRecovery);
+
+ QStringList dirs = {QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath)};
+ auto envPtr = QQmlJS::Dom::DomEnvironment::create(dirs,
+ QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
+ | QQmlJS::Dom::DomEnvironment::Option::NoDependencies, options);
+ envPtr->loadBuiltins();
+ envPtr->loadFile(QQmlJS::Dom::FileToLoad::fromMemory(envPtr, filePath, code),
+ [&file](QQmlJS::Dom::Path, const QQmlJS::Dom::DomItem &, const QQmlJS::Dom::DomItem &newIt) {
+ file = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
+ return file;
+};
+
+void tst_qmlls_modules::semanticHighlightingFull_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addRow("bigfile") << u"highlighting/bigFile.qml"_s;
+}
+
+void tst_qmlls_modules::semanticHighlightingFull()
+{
+ QFETCH(QString, filePath);
+ const auto item = fileObject(testFile(filePath));
+ Highlights highlights;
+ const auto expectedData = highlights.collectTokens(item, std::nullopt);
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+ QLspSpecification::SemanticTokensParams params;
+ params.textDocument.uri = *uri;
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ const auto cleanup = [didFinish]() { *didFinish = true; };
+
+ auto &&responseHandler = [&](auto res) {
+ QScopeGuard callAtExit(cleanup);
+ const auto *const result = std::get_if<QLspSpecification::SemanticTokens>(&res);
+ QVERIFY(result);
+ QList<int> data = result->data;
+ QCOMPARE(data.size(), expectedData.size());
+ QCOMPARE(data, expectedData);
+ };
+
+ auto &&errorHandler = [&](auto &error) {
+ QScopeGuard callAtExit(cleanup);
+ ProtocolBase::defaultResponseErrorHandler(error);
+ QVERIFY2(false, "error occurred on full semantic tokens");
+ };
+
+ m_protocol->requestSemanticTokens(params, std::move(responseHandler), std::move(errorHandler));
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 10000);
+}
+
+void tst_qmlls_modules::semanticHighlightingRange_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<QLspSpecification::Range>("range");
+ QTest::addRow("bigfile") << u"highlighting/bigFile.qml"_s
+ << QLspSpecification::Range{ { 6, 0 }, { 15, 0 } };
+}
+
+void tst_qmlls_modules::semanticHighlightingRange()
+{
+ QFETCH(QString, filePath);
+ QFETCH(QLspSpecification::Range, range);
+
+ const auto item = fileObject(testFile(filePath));
+ Highlights highlights;
+ const auto qmlFile = item.as<QQmlJS::Dom::QmlFile>();
+ const auto code = qmlFile->code();
+ const int startOffset = int(QQmlLSUtils::textOffsetFrom(code, range.start.line, range.end.character));
+ const int endOffset = int(QQmlLSUtils::textOffsetFrom(code, range.end.line, range.end.character));
+ const auto expectedData = highlights.collectTokens(item, HighlightsRange{startOffset, endOffset});
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+ QLspSpecification::SemanticTokensRangeParams params;
+ params.textDocument.uri = *uri;
+ params.range = range;
+
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ const auto cleanup = [didFinish]() { *didFinish = true; };
+
+ auto &&responseHandler = [&](auto res) {
+ QScopeGuard callAtExit(cleanup);
+ const auto *const result = std::get_if<QLspSpecification::SemanticTokens>(&res);
+ QVERIFY(result);
+ QList<int> data = result->data;
+ QCOMPARE(data.size(), expectedData.size());
+ QCOMPARE(data, expectedData);
+ };
+
+ auto &&errorHandler = [&](auto &error) {
+ QScopeGuard callAtExit(cleanup);
+ ProtocolBase::defaultResponseErrorHandler(error);
+ QVERIFY2(false, "error occurred on full semantic tokens");
+ };
+
+ m_protocol->requestSemanticTokensRange(params, std::move(responseHandler),
+ std::move(errorHandler));
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 10000);
+}
+
+void tst_qmlls_modules::semanticHighlightingDelta_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addRow("basicDelta") << u"highlighting/basic.qml"_s;
+}
+
+void tst_qmlls_modules::semanticHighlightingDelta()
+{
+ QSKIP("This test should be skipped until QTBUG-124870 is fixed");
+ QFETCH(QString, filePath);
+ QFETCH(QString, deltaFilePath);
+
+ const auto fileItem = fileObject(testFile(filePath));
+ const auto deltaFileItem = fileObject(testFile(deltaFilePath));
+ Highlights highlights;
+ auto fullDocumentSemanticTokensData = highlights.collectTokens(fileItem, std::nullopt);
+ auto editedDocumentSemanticTokensData = highlights.collectTokens(deltaFileItem, std::nullopt);
+ const auto expectedEdits = HighlightingUtils::computeDiff(fullDocumentSemanticTokensData, editedDocumentSemanticTokensData);
+
+ const auto uri = openFile(filePath);
+ QVERIFY(uri);
+ const auto deltaUri = openFile(deltaFilePath);
+ QVERIFY(deltaUri);
+
+ std::shared_ptr<bool> didFinish = std::make_shared<bool>(false);
+ const auto cleanup = [didFinish]() { *didFinish = true; };
+
+ QLspSpecification::SemanticTokensDeltaParams params;
+ QLspSpecification::Responses::SemanticTokensDeltaResultType result;
+
+ auto &&errorHandler = [&](auto &error) {
+ QScopeGuard callAtExit(cleanup);
+ ProtocolBase::defaultResponseErrorHandler(error);
+ QVERIFY2(false, "error occurred on semantic tokens/delta");
+ };
+
+ QLspSpecification::SemanticTokensParams fullParams;
+ fullParams.textDocument.uri = *uri;
+ m_protocol->requestSemanticTokens(fullParams,
+ [&](auto res) {
+ QScopeGuard callAtExit(cleanup);
+ if (auto r = std::get_if<QLspSpecification::SemanticTokens>(&res)) {
+ params.previousResultId = r->resultId.value();
+ fullDocumentSemanticTokensData = r->data;
+ }
+ }, errorHandler);
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 10000);
+
+ // Change the file
+ DidChangeTextDocumentParams didChange;
+ didChange.textDocument.uri = *uri;
+ didChange.textDocument.version = 2;
+
+ TextDocumentContentChangeEvent change;
+ change.range = Range{ Position{ 8, 4 }, Position{ 8, 4 } };
+ change.text = "const Patron = 42";
+
+ didChange.contentChanges.append(change);
+ m_protocol->notifyDidChangeTextDocument(didChange);
+
+ *didFinish = false;
+ params.textDocument.uri = *uri;
+ m_protocol->requestSemanticTokensDelta(params,
+ [&](auto res) {
+ QScopeGuard callAtExit(cleanup);
+ result = res;
+ }, std::move(errorHandler));
+ QTRY_VERIFY_WITH_TIMEOUT(*didFinish, 10000);
+
+ if (const auto *const delta = std::get_if<QLspSpecification::SemanticTokensDelta>(&result)) {
+ QVERIFY(delta);
+ const auto data = delta->edits.front().data;
+ const auto start = delta->edits.front().start;
+ const auto deleteCount = delta->edits.front().deleteCount;
+ QCOMPARE(start, expectedEdits.front().start);
+ QCOMPARE(deleteCount, expectedEdits.front().deleteCount);
+ QCOMPARE(data, expectedEdits.front().data);
+ } else {
+ const auto *const full = std::get_if<QLspSpecification::SemanticTokens>(&result);
+ QVERIFY(full);
+ QCOMPARE(full->data, expectedEdits.front().data);
+ }
+}
+
+QTEST_MAIN(tst_qmlls_modules)
diff --git a/tests/auto/qmlls/modules/tst_qmlls_modules.h b/tests/auto/qmlls/modules/tst_qmlls_modules.h
new file mode 100644
index 0000000000..d7b601cf5a
--- /dev/null
+++ b/tests/auto/qmlls/modules/tst_qmlls_modules.h
@@ -0,0 +1,85 @@
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TST_QMLLSMODULES_H
+#define TST_QMLLSMODULES_H
+
+#include <QtJsonRpc/private/qjsonrpcprotocol_p.h>
+#include <QtLanguageServer/private/qlanguageserverprotocol_p.h>
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtCore/private/qduplicatetracker_p.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qprocess.h>
+#include <QtCore/qlibraryinfo.h>
+#include <QtCore/qstringlist.h>
+
+#include <QtTest/qtest.h>
+#include <QtQmlLS/private/qlspcustomtypes_p.h>
+
+#include <iostream>
+#include <variant>
+
+
+class tst_qmlls_modules : public QQmlDataTest
+{
+ using ExpectedCompletion = QPair<QString, QLspSpecification::CompletionItemKind>;
+ using ExpectedCompletions = QList<ExpectedCompletion>;
+
+ using ExpectedDocumentation = std::tuple<QString, QString, QString>;
+ using ExpectedDocumentations = QList<ExpectedDocumentation>;
+
+ Q_OBJECT
+public:
+ tst_qmlls_modules();
+ void checkCompletions(const QByteArray &filePath, int lineNr, int character,
+ ExpectedCompletions expected, QStringList notExpected);
+ std::optional<QByteArray> openFile(const QString &uri);
+ std::optional<QByteArray> openFileFromAbsolutePath(const QString &uri);
+ void ignoreDiagnostics();
+ void compareQTextDocumentEdit(const QLspSpecification::TextDocumentEdit &a,
+ const QLspSpecification::TextDocumentEdit &b);
+private slots:
+ void init() final;
+ void cleanup();
+ void initTestCase() final;
+ void function_documentations_data();
+ void function_documentations();
+ void buildDir();
+ void goToTypeDefinition_data();
+ void goToTypeDefinition();
+ void goToDefinition_data();
+ void goToDefinition();
+ void findUsages_data();
+ void findUsages();
+ void documentFormatting_data();
+ void documentFormatting();
+ void renameUsages_data();
+ void renameUsages();
+ void linting_data();
+ void linting();
+ void rangeFormatting_data();
+ void rangeFormatting();
+ void qmldirImports_data();
+ void qmldirImports();
+ void quickFixes_data();
+ void quickFixes();
+ void automaticSemicolonInsertionForCompletions_data();
+ void automaticSemicolonInsertionForCompletions();
+ void hover_data();
+ void hover();
+ void checkQuickSnippets();
+ void semanticHighlightingFull_data();
+ void semanticHighlightingFull();
+ void semanticHighlightingRange_data();
+ void semanticHighlightingRange();
+ void semanticHighlightingDelta_data();
+ void semanticHighlightingDelta();
+private:
+ QProcess m_server;
+ std::unique_ptr<QLanguageServerProtocol> m_protocol;
+ QString m_qmllsPath;
+ QList<QByteArray> m_uriToClose;
+};
+
+#endif // TST_QMLLSMODULES_H
diff --git a/tests/auto/qmlls/qmlls/CMakeLists.txt b/tests/auto/qmlls/qmlls/CMakeLists.txt
index e5f4bf822c..b3580c74e7 100644
--- a/tests/auto/qmlls/qmlls/CMakeLists.txt
+++ b/tests/auto/qmlls/qmlls/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlls LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
data)
@@ -25,3 +31,9 @@ qt_internal_extend_target(tst_qmlls CONDITION ANDROID OR IOS
DEFINES
QT_QMLTEST_DATADIR=":/domdata"
)
+
+if (TARGET qmlls)
+ # in a standalone build, the qmlls target won't exist
+ # but we assume that it is available if you manually set up the test
+ add_dependencies(tst_qmlls qmlls)
+endif()
diff --git a/tests/auto/qmlls/qmlls/tst_qmlls.cpp b/tests/auto/qmlls/qmlls/tst_qmlls.cpp
index 49d2de0583..9e057992c4 100644
--- a/tests/auto/qmlls/qmlls/tst_qmlls.cpp
+++ b/tests/auto/qmlls/qmlls/tst_qmlls.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtJsonRpc/private/qjsonrpcprotocol_p.h>
#include <QtLanguageServer/private/qlanguageserverprotocol_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -214,18 +214,17 @@ void tst_Qmlls::didOpenTextDocument()
QString title = QString::fromUtf8(action.title);
QVERIFY(action.kind.has_value());
- QCOMPARE(QString::fromUtf8(action.kind.value()),
- QLatin1StringView("refactor.rewrite"));
+ QCOMPARE(QString::fromUtf8(action.kind.value()), QLatin1StringView("quickfix"));
QVERIFY(action.edit.has_value());
WorkspaceEdit edit = action.edit.value();
QVERIFY(edit.documentChanges.has_value());
- auto docChangeVariant = edit.documentChanges.value();
- QVERIFY(std::holds_alternative<QList<TextDocumentEdit>>(docChangeVariant));
- auto documentChanges = std::get<QList<TextDocumentEdit>>(docChangeVariant);
+ auto documentChanges = edit.documentChanges.value();
QCOMPARE(documentChanges.size(), 1);
- TextDocumentEdit textDocEdit = documentChanges.first();
+ QVERIFY(std::holds_alternative<TextDocumentEdit>(documentChanges.first()));
+ TextDocumentEdit textDocEdit
+ = std::get<TextDocumentEdit>(documentChanges.first());
QCOMPARE(textDocEdit.textDocument.uri, textDocument.uri);
QVERIFY(std::holds_alternative<int>(textDocEdit.textDocument.version));
diff --git a/tests/auto/qmlls/qqmlcodemodel/CMakeLists.txt b/tests/auto/qmlls/qqmlcodemodel/CMakeLists.txt
new file mode 100644
index 0000000000..21b14a62a8
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/CMakeLists.txt
@@ -0,0 +1,33 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlls_qqmlcodemodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+file(GLOB_RECURSE test_data_glob
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ data)
+list(APPEND test_data ${test_data_glob})
+
+qt_internal_add_test(tst_qmlls_qqmlcodemodel
+ SOURCES
+ tst_qmlls_qqmlcodemodel.cpp tst_qmlls_qqmlcodemodel.h
+ LIBRARIES
+ Qt::Core
+ Qt::QmlDomPrivate
+ Qt::LanguageServerPrivate
+ Qt::Test
+ Qt::QuickTestUtilsPrivate
+ Qt::QmlLSPrivate
+ TESTDATA ${test_data}
+ DEFINES
+ QT_QQMLCODEMODEL_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+)
+
+qt_internal_extend_target(tst_qmlls_qqmlcodemodel CONDITION ANDROID OR IOS
+ DEFINES
+ QT_QQMLCODEMODEL_DATADIR=":/data"
+)
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/FileA.qml b/tests/auto/qmlls/qqmlcodemodel/data/FileA.qml
new file mode 100644
index 0000000000..5560aee727
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/FileA.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+
+}
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/FileA2.qml b/tests/auto/qmlls/qqmlcodemodel/data/FileA2.qml
new file mode 100644
index 0000000000..7680c63f95
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/FileA2.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int helloProperty
+} \ No newline at end of file
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/FileB.qml b/tests/auto/qmlls/qqmlcodemodel/data/FileB.qml
new file mode 100644
index 0000000000..03cd2f9fb3
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/FileB.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+FileA {
+ property int helloPropertyInB
+}
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/MyCppModule/Main.qml b/tests/auto/qmlls/qqmlcodemodel/data/MyCppModule/Main.qml
new file mode 100644
index 0000000000..6406952c27
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/MyCppModule/Main.qml
@@ -0,0 +1,5 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+
+HelloWorld { myP: 55; myPPP: 55 }
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/MyCppModule/mycppmodule.qmltypes b/tests/auto/qmlls/qqmlcodemodel/data/MyCppModule/mycppmodule.qmltypes
new file mode 100644
index 0000000000..8a2a1bc714
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/MyCppModule/mycppmodule.qmltypes
@@ -0,0 +1,36 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by qmltyperegistrar.
+
+Module {
+ Component {
+ file: "helloworld.h"
+ name: "HelloWorld"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["MyCppModule/HelloWorld 1.0"]
+ exportMetaObjectRevisions: [256]
+ Property {
+ name: "myP"
+ type: "int"
+ read: "myP"
+ write: "setMyP"
+ notify: "myPChanged"
+ index: 0
+ isFinal: true
+ }
+ Property {
+ name: "myPPP"
+ type: "int"
+ read: "myP"
+ write: "setMyP"
+ notify: "myPChanged"
+ index: 1
+ isFinal: true
+ }
+ Signal { name: "myPChanged" }
+ }
+}
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/MyCppModule/qmldir b/tests/auto/qmlls/qqmlcodemodel/data/MyCppModule/qmldir
new file mode 100644
index 0000000000..741dd5cbf8
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/MyCppModule/qmldir
@@ -0,0 +1,5 @@
+module MyCppModule
+typeinfo mycppmodule.qmltypes
+prefer :/MyCppModule/
+Main 1.0 Main.qml
+
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/MyCppModule/Main.qml b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/MyCppModule/Main.qml
new file mode 100644
index 0000000000..dbe18d54a6
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/MyCppModule/Main.qml
@@ -0,0 +1,13 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import autoGenCMake
+
+Window {
+ width: 640
+ height: 480
+ visible: true
+ title: qsTr("Hello World")
+ HelloWorld { myP: 55; myPPP: 55 }
+}
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/MyCppModule/helloworld.cpp b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/MyCppModule/helloworld.cpp
new file mode 100644
index 0000000000..445103c228
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/MyCppModule/helloworld.cpp
@@ -0,0 +1,8 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "helloworld.h"
+
+HelloWorld::HelloWorld(QObject *parent)
+ : QObject{parent}
+{}
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/MyCppModule/helloworld.h b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/MyCppModule/helloworld.h
new file mode 100644
index 0000000000..0a13344476
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/MyCppModule/helloworld.h
@@ -0,0 +1,29 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef HELLOWORLD_H
+#define HELLOWORLD_H
+
+#include <QObject>
+#include <QQmlEngine>
+
+class HelloWorld : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(int myP READ myP WRITE setMyP NOTIFY myPChanged FINAL)
+ Q_PROPERTY(int myPPP READ myP WRITE setMyP NOTIFY myPChanged FINAL)
+
+public:
+ explicit HelloWorld(QObject *parent = nullptr);
+
+ int myP() { return m_myP; }
+ void setMyP(int p) { m_myP = p; }
+private:
+ int m_myP;
+
+signals:
+ void myPChanged();
+};
+
+#endif // HELLOWORLD_H
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement.cpp b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement.cpp
new file mode 100644
index 0000000000..604e42f8b1
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement.cpp
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "myqmlelement.h"
+
+MyQmlElement::MyQmlElement(QObject *parent)
+ : QObject{parent}
+{
+
+}
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement.h b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement.h
new file mode 100644
index 0000000000..dd4e2e2cc4
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement.h
@@ -0,0 +1,21 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef MYQMLELEMENT_H
+#define MYQMLELEMENT_H
+
+#include <QObject>
+#include <QQmlEngine>
+
+class MyQmlElement : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ explicit MyQmlElement(QObject *parent = nullptr);
+
+signals:
+
+};
+
+#endif // MYQMLELEMENT_H
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement.qml b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement.qml
new file mode 100644
index 0000000000..226927e792
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement.qml
@@ -0,0 +1,8 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.15
+
+Item {
+
+}
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement2.cpp b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement2.cpp
new file mode 100644
index 0000000000..abeeb8f3b1
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement2.cpp
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "myqmlelement2.hpp"
+
+myQmlElement2::myQmlElement2(QObject *parent)
+ : QObject{parent}
+{
+
+}
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement2.hpp b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement2.hpp
new file mode 100644
index 0000000000..c7adf50e2e
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/myqmlelement2.hpp
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef MYQMLELEMENT2_H
+#define MYQMLELEMENT2_H
+
+#include <QObject>
+#include <QQmlEngine>
+
+class myQmlElement2 : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ explicit myQmlElement2(QObject *parent = nullptr);
+};
+
+#endif // MYQMLELEMENT2_H
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/somecppclass.cpp b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/somecppclass.cpp
new file mode 100644
index 0000000000..a3a73413eb
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/somecppclass.cpp
@@ -0,0 +1,9 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "somecppclass.h"
+
+SomeCppClass::SomeCppClass()
+{
+
+}
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/somecppclass.h b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/somecppclass.h
new file mode 100644
index 0000000000..06943515d8
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/somecppclass.h
@@ -0,0 +1,14 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef SOMECPPCLASS_H
+#define SOMECPPCLASS_H
+
+
+class SomeCppClass
+{
+public:
+ SomeCppClass();
+};
+
+#endif // SOMECPPCLASS_H
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/anotherqmlelement.cpp b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/anotherqmlelement.cpp
new file mode 100644
index 0000000000..9a89751eb8
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/anotherqmlelement.cpp
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "anotherqmlelement.h"
+
+AnotherQmlElement::AnotherQmlElement(QObject *parent)
+ : QObject{parent}
+{
+
+}
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/anotherqmlelement.h b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/anotherqmlelement.h
new file mode 100644
index 0000000000..1ddba88c6b
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/anotherqmlelement.h
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef ANOTHERQMLELEMENT_H
+#define ANOTHERQMLELEMENT_H
+
+#include <QObject>
+#include <QQmlEngine>
+
+class AnotherQmlElement : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ explicit AnotherQmlElement(QObject *parent = nullptr);
+};
+
+#endif // ANOTHERQMLELEMENT_H
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/myqmlelement.cpp b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/myqmlelement.cpp
new file mode 100644
index 0000000000..c448ea76f0
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/myqmlelement.cpp
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "myqmlelementx.h"
+
+MyQmlElementX::MyQmlElementX(QObject *parent)
+ : QObject{parent}
+{
+
+}
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/myqmlelement.h b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/myqmlelement.h
new file mode 100644
index 0000000000..f32756c7b1
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/myqmlelement.h
@@ -0,0 +1,21 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef MYQMLELEMENTX_H
+#define MYQMLELEMENTX_H
+
+#include <QObject>
+#include <QQmlEngine>
+
+class MyQmlElementX : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ explicit MyQmlElementX(QObject *parent = nullptr);
+
+signals:
+
+};
+
+#endif // MYQMLELEMENTX_H
diff --git a/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/myqmlelement.txt b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/myqmlelement.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/data/sourceFolder/subSourceFolder/subsubSourceFolder/myqmlelement.txt
diff --git a/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp b/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp
new file mode 100644
index 0000000000..a3293769e5
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp
@@ -0,0 +1,185 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "tst_qmlls_qqmlcodemodel.h"
+
+#include <QtQmlToolingSettings/private/qqmltoolingsettings_p.h>
+#include <QtQmlLS/private/qqmlcodemodel_p.h>
+#include <QtQmlLS/private/qqmllsutils_p.h>
+#include <QtQmlDom/private/qqmldomitem_p.h>
+#include <QtQmlDom/private/qqmldomtop_p.h>
+
+tst_qmlls_qqmlcodemodel::tst_qmlls_qqmlcodemodel() : QQmlDataTest(QT_QQMLCODEMODEL_DATADIR) { }
+
+void tst_qmlls_qqmlcodemodel::buildPathsForFileUrl_data()
+{
+ QTest::addColumn<QString>("pathFromIniFile");
+ QTest::addColumn<QString>("pathFromEnvironmentVariable");
+ QTest::addColumn<QString>("pathFromCommandLine");
+ QTest::addColumn<QString>("expectedPath");
+
+ const QString path1 = u"/Users/helloWorld/build-myProject"_s;
+ const QString path2 = u"/Users/helloWorld/build-custom"_s;
+ const QString path3 = u"/Users/helloWorld/build-12345678"_s;
+
+ QTest::addRow("justCommandLine") << QString() << QString() << path1 << path1;
+ QTest::addRow("all3") << path1 << path2 << path3 << path3;
+
+ QTest::addRow("commandLineOverridesEnvironmentVariable")
+ << QString() << path2 << path3 << path3;
+ QTest::addRow("commandLineOverridesIniFile") << path2 << QString() << path3 << path3;
+
+ QTest::addRow("EnvironmentVariableOverridesIniFile") << path1 << path2 << QString() << path2;
+ QTest::addRow("iniFile") << path1 << QString() << QString() << path1;
+ QTest::addRow("environmentVariable") << QString() << path3 << QString() << path3;
+}
+
+void tst_qmlls_qqmlcodemodel::buildPathsForFileUrl()
+{
+ QFETCH(QString, pathFromIniFile);
+ QFETCH(QString, pathFromEnvironmentVariable);
+ QFETCH(QString, pathFromCommandLine);
+ QFETCH(QString, expectedPath);
+
+ QQmlToolingSettings settings(u"qmlls"_s);
+ if (!pathFromIniFile.isEmpty())
+ settings.addOption("buildDir", pathFromIniFile);
+
+ constexpr char environmentVariable[] = "QMLLS_BUILD_DIRS";
+ qunsetenv(environmentVariable);
+ if (!pathFromEnvironmentVariable.isEmpty()) {
+ qputenv(environmentVariable, pathFromEnvironmentVariable.toUtf8());
+ }
+
+ QmlLsp::QQmlCodeModel model(nullptr, &settings);
+ if (!pathFromCommandLine.isEmpty())
+ model.setBuildPathsForRootUrl(QByteArray(), QStringList{ pathFromCommandLine });
+
+ // use nonexistent path to avoid loading random .qmlls.ini files that might be laying around.
+ // in this case, it should abort the search and the standard value we set in the settings
+ const QByteArray nonExistentUrl =
+ QUrl::fromLocalFile(u"./___thispathdoesnotexist123___/abcdefghijklmnop"_s).toEncoded();
+
+ QStringList result = model.buildPathsForFileUrl(nonExistentUrl);
+ QCOMPARE(result.size(), 1);
+ QCOMPARE(result.front(), expectedPath);
+}
+
+void tst_qmlls_qqmlcodemodel::findFilePathsFromFileNames_data()
+{
+ QTest::addColumn<QStringList>("fileNames");
+ QTest::addColumn<QStringList>("expectedPaths");
+
+ const QString folder = testFile("sourceFolder");
+ const QString subfolder = testFile("sourceFolder/subSourceFolder/subsubSourceFolder");
+
+ QTest::addRow("notExistingFile") << QStringList{ u"notExistingFile.h"_s } << QStringList{};
+
+ QTest::addRow("myqmlelement") << QStringList{ u"myqmlelement.h"_s }
+ << QStringList{ folder + u"/myqmlelement.h"_s,
+ subfolder + u"/myqmlelement.h"_s };
+
+ QTest::addRow("myqmlelement2") << QStringList{ u"myqmlelement2.hpp"_s }
+ << QStringList{ folder + u"/myqmlelement2.hpp"_s };
+
+ QTest::addRow("anotherqmlelement") << QStringList{ u"anotherqmlelement.cpp"_s }
+ << QStringList{ subfolder + u"/anotherqmlelement.cpp"_s };
+}
+
+void tst_qmlls_qqmlcodemodel::findFilePathsFromFileNames()
+{
+ QFETCH(QStringList, fileNames);
+ QFETCH(QStringList, expectedPaths);
+
+ QmlLsp::QQmlCodeModel model;
+ model.setRootUrls({ testFileUrl(u"sourceFolder"_s).toEncoded() });
+
+ auto result = model.findFilePathsFromFileNames(fileNames);
+ // the order only is required for the QCOMPARE
+ std::sort(result.begin(), result.end());
+ std::sort(expectedPaths.begin(), expectedPaths.end());
+
+ QCOMPARE(result, expectedPaths);
+}
+
+using namespace QQmlJS::Dom;
+
+void tst_qmlls_qqmlcodemodel::fileNamesToWatch()
+{
+ DomItem qmlFile;
+ DomCreationOptions options;
+ options.setFlag(DomCreationOption::WithSemanticAnalysis);
+
+ auto envPtr = DomEnvironment::create(QStringList(),
+ DomEnvironment::Option::SingleThreaded
+ | DomEnvironment::Option::NoDependencies, options);
+
+ envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, testFile("MyCppModule/Main.qml")),
+ [&qmlFile](Path, const DomItem &, const DomItem &newIt) {
+ qmlFile = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
+
+ const auto fileNames = QmlLsp::QQmlCodeModel::fileNamesToWatch(qmlFile);
+
+ // fileNames also contains some builtins it seems, like:
+ // QSet("qqmlcomponentattached_p.h", "qqmlcomponent.h", "qobject.h", "qqmllist.h",
+ // "helloworld.h", "qqmlengine_p.h")
+ QVERIFY(fileNames.contains(u"helloworld.h"_s));
+}
+
+QString tst_qmlls_qqmlcodemodel::readFile(const QString &filename) const
+{
+ QFile f(testFile(filename));
+ if (!f.open(QFile::ReadOnly)) {
+ QTest::qFail("Can't read test file", __FILE__, __LINE__);
+ return {};
+ }
+ return f.readAll();
+}
+
+void tst_qmlls_qqmlcodemodel::openFiles()
+{
+ QmlLsp::QQmlCodeModel model;
+
+ const QByteArray fileAUrl = testFileUrl(u"FileA.qml"_s).toEncoded();
+ const QString fileAPath = testFile(u"FileA.qml"_s);
+
+ // open file A
+ model.newOpenFile(fileAUrl, 0, readFile(u"FileA.qml"_s));
+
+ QTRY_VERIFY_WITH_TIMEOUT(model.validEnv().field(Fields::qmlFileWithPath).key(fileAPath), 3000);
+
+ {
+ const DomItem fileAComponents = model.validEnv()
+ .field(Fields::qmlFileWithPath)
+ .key(fileAPath)
+ .field(Fields::currentItem)
+ .field(Fields::components);
+ // if there is no component then the lazy qml file was not loaded correctly.
+ QCOMPARE(fileAComponents.size(), 1);
+ }
+
+ model.newDocForOpenFile(fileAUrl, 1, readFile(u"FileA2.qml"_s));
+
+ {
+ const DomItem fileAComponents = model.validEnv()
+ .field(Fields::qmlFileWithPath)
+ .key(fileAPath)
+ .field(Fields::currentItem)
+ .field(Fields::components);
+ // if there is no component then the lazy qml file was not loaded correctly.
+ QCOMPARE(fileAComponents.size(), 1);
+
+ // also check if the property is there
+ const DomItem properties = fileAComponents.key(QString())
+ .index(0)
+ .field(Fields::objects)
+ .index(0)
+ .field(Fields::propertyDefs);
+ QVERIFY(properties);
+ QVERIFY(properties.key(u"helloProperty"_s));
+ }
+}
+
+QTEST_MAIN(tst_qmlls_qqmlcodemodel)
diff --git a/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.h b/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.h
new file mode 100644
index 0000000000..a913f4bd19
--- /dev/null
+++ b/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.h
@@ -0,0 +1,37 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TST_QMLLS_QQMLCODEMODEL_H
+#define TST_QMLLS_QQMLCODEMODEL_H
+
+#include <QtJsonRpc/private/qjsonrpcprotocol_p.h>
+#include <QtLanguageServer/private/qlanguageserverprotocol_p.h>
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qprocess.h>
+#include <QtCore/qlibraryinfo.h>
+
+#include <QtTest/qtest.h>
+
+#include <iostream>
+
+using namespace Qt::StringLiterals;
+
+class tst_qmlls_qqmlcodemodel : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_qmlls_qqmlcodemodel();
+ QString readFile(const QString &filename) const;
+
+private slots:
+ void buildPathsForFileUrl_data();
+ void buildPathsForFileUrl();
+ void fileNamesToWatch();
+ void findFilePathsFromFileNames_data();
+ void findFilePathsFromFileNames();
+ void openFiles();
+};
+
+#endif // TST_QMLLS_QQMLCODEMODEL_H
diff --git a/tests/auto/qmlls/utils/CMakeLists.txt b/tests/auto/qmlls/utils/CMakeLists.txt
new file mode 100644
index 0000000000..ba81707b30
--- /dev/null
+++ b/tests/auto/qmlls/utils/CMakeLists.txt
@@ -0,0 +1,63 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlls_utils LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+file(GLOB_RECURSE test_data_glob
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ data)
+list(APPEND test_data ${test_data_glob})
+
+qt_internal_add_test(tst_qmlls_utils
+ SOURCES
+ tst_qmlls_utils.cpp
+ DEFINES
+ QT_QMLLS_UTILS_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+ LIBRARIES
+ Qt::Core
+ Qt::QmlDomPrivate
+ Qt::LanguageServerPrivate
+ Qt::Test
+ Qt::QuickTestUtilsPrivate
+ Qt::QmlLSPrivate
+ TESTDATA ${test_data}
+)
+
+qt_internal_add_test(tst_qmlls_highlighting
+ SOURCES
+ tst_qmlls_highlighting.cpp
+ DEFINES
+ QT_QMLLS_HIGHLIGHTS_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+ LIBRARIES
+ Qt::Core
+ Qt::QmlDomPrivate
+ Qt::LanguageServerPrivate
+ Qt::Test
+ Qt::QuickTestUtilsPrivate
+ Qt::QmlLSPrivate
+ TESTDATA ${test_data}
+)
+
+qt_internal_add_test(tst_qmlls_documentationHints
+ SOURCES
+ tst_qmlls_documentationHints.cpp
+ DEFINES
+ QT_QMLLS_DOCUMENTATION_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+ LIBRARIES
+ Qt::Core
+ Qt::QmlDomPrivate
+ Qt::LanguageServerPrivate
+ Qt::Test
+ Qt::QuickTestUtilsPrivate
+ Qt::QmlLSPrivate
+ TESTDATA ${test_data}
+)
+
+qt_internal_extend_target(tst_qmlls_utils CONDITION ANDROID OR IOS
+ DEFINES
+ QT_QMLLS_UTILS_DATADIR=":/domdata"
+)
diff --git a/tests/auto/qmlls/utils/data/BaseType.qml b/tests/auto/qmlls/utils/data/BaseType.qml
new file mode 100644
index 0000000000..168630f8ef
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/BaseType.qml
@@ -0,0 +1,28 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.15
+
+Item {
+ property string inBaseTypeDotQml: "Hello from BaseType!"
+
+ component MyBaseInlineComponent: Item {
+ id: baseIC
+ }
+
+ Item {
+ id: child
+
+ Item {
+ id: nestedChild
+
+ component MyNestedInlineComponent: Item {
+ property string inMyNestedInlineComponent: "world"
+ }
+ }
+ }
+ property int helloProperty: 123
+ function helloFunction() {
+ return helloProperty
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/JSDefinitions.qml b/tests/auto/qmlls/utils/data/JSDefinitions.qml
new file mode 100644
index 0000000000..20a1d34fe2
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/JSDefinitions.qml
@@ -0,0 +1,76 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.15
+
+Item {
+ id: rootId
+
+ property int i // (1)
+ function f(a /*(2)*/ , b) {return a /* go to definition on a leads to (2) */ > b} // (4)
+
+ Component.onCompleted: {
+ let x = 42 // (3)
+ f(x, i) // goto definition on f goes to 4, on x goes to (3) and on i goes to (1)
+ f(x, rootId.i) // goto definition on f goes to 4, on x goes to (3) and on i goes to (1)
+ }
+
+ function ffff() {
+ let scoped = 42;
+ {
+ let scoped = 666;
+ f(scoped, i);
+ {
+ let a = 12345, i = 32;
+ f(scoped, i);
+ }
+ }
+ f(scoped, i);
+ }
+
+ Rectangle {
+ id: nested
+
+ property int i
+
+ function f(n: int): int {
+ let x = i, y = nested.i, z = rootId.i;
+ if (x > 3)
+ return 1 + f(f(x-1) + f(x-2) - f(x-3));
+ else
+ return f(0);
+ }
+ function fff(n: int, m: int): int {
+ return f(n + m) / 42 + ffff()
+ }
+ }
+ function abc() {
+ return nested.f(42);
+ }
+
+ component MyIC: Rectangle {
+ id: helloIC
+
+ property int data: 42
+ Item {
+ property int data: helloIC.data
+ }
+ }
+
+ property MyIC ic: MyIC {}
+ function icProperty() {
+ return ic.data
+ }
+ property int propertyInBinding: i
+ property int propertyInBinding2: i * 42
+ property int propertyInBinding3: abc()[rootId.i ** 42 - 7]
+
+ property BaseType bt: BaseType {}
+ property int helloProperty: 1234567890 // BaseType also has a property helloProperty
+ function helloFunction() {} // BaseType also has a method helloFunction
+ function fromDifferentFiles() {
+ let x = bt.helloProperty + bt.helloFunction()
+ }
+
+ property BaseType.MyBaseInlineComponent inlineCompFromDifferentFile
+}
diff --git a/tests/auto/qmlls/utils/data/JSUsages.qml b/tests/auto/qmlls/utils/data/JSUsages.qml
new file mode 100644
index 0000000000..ce0cd1d046
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/JSUsages.qml
@@ -0,0 +1,196 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function f() {
+ let sum = 0, sum2 = 0
+ for(let i = 1; i < 42; i = i + 2) {
+ sum = sum + i
+ {
+ let sum = 42; // another unrelated sum
+ }
+ }
+ }
+
+ property int helloProperty: 0
+ property int p2: 1
+
+ function withProperty() {
+ let sum = 0, sum2 = 0
+ for(let i = 1; i < 42; i = i + 2) {
+ sum = sum + i
+ helloProperty = helloProperty + sum - i * p2;
+ {
+ let helloProperty = "evil"
+ }
+ }
+ }
+ Item {
+ function f() {
+ return helloProperty + p2
+ }
+ property string helloProperty
+ }
+ component IC: Item {
+ property var helloProperty
+ function f() {
+ return helloProperty + p2
+ }
+ }
+ component NestedComponent: Item {
+ property NestedComponent2 inner: NestedComponent2 {}
+ property int p2
+ }
+ component NestedComponent2: Item {
+ property NestedComponent3 inner
+ property int p2
+ inner: NestedComponent3 {}
+ }
+ component NestedComponent3: Item {
+ property NestedComponent4 inner
+ property int p2
+ inner: NestedComponent4 {}
+
+ }
+ component NestedComponent4: Item {
+ property int helloProperty
+ property int p2
+ }
+ NestedComponent {
+ id: myNested
+ }
+ function nestedUsages() {
+ let x = myNested.inner.inner.inner.helloProperty + helloProperty;
+ let a = myNested.p2 + p2
+ let b = myNested.inner.p2 + p2
+ let c = myNested.inner.inner.p2 + p2
+ let d = myNested.inner.inner.inner.p2 + p2
+ }
+
+ function recursive(n: int): int {
+ if (n > 3)
+ return 1 + recursive(recursive(x-1) + recursive(x-2) - recursive(x-3));
+ else
+ return recursive(0);
+ }
+
+ property int helloRecursive: recursive(42)
+
+ id: rootId
+ Rectangle {
+ function f() {
+ return rootId.recursive(123)
+ }
+ }
+
+ signal helloSignal()
+
+ function callSignals() {
+ helloSignal()
+ if (false) {
+ helloSignal()
+ } else {
+ // helloSignal() // not a usage btw
+ if (true)
+ helloSignal()
+ }
+ }
+ function callSignals2() {
+ helloSignal()
+ if (false) {
+ widthChanged()
+ } else {
+ // helloSignal() // not a usage btw
+ if (true)
+ widthChanged()
+ rootId.widthChanged()
+ }
+ }
+ Item {
+ function callSignalsInChild() {
+ widthChanged()
+ rootId.widthChanged()
+ }
+ }
+
+ function myHelloHandler() { let x = 32; }
+ onHelloSignal: myHelloHandler
+
+ property int helloPropertyBinding
+ helloPropertyBinding: 123
+
+ property int checkHandlers
+ onCheckHandlersChanged: myHelloHandler
+ onChildrenChanged: myHelloHandler
+ function callChanged() {
+ checkHandlersChanged()
+ childrenChanged()
+ }
+ property int _: 48
+ property int ______42: 48
+ property int _123a: 48
+ on_Changed: myHelloHandler
+ on______42Changed: myHelloHandler
+ on_123AChanged: myHelloHandler
+ function weirdPropertynames() {
+ _Changed()
+ ______42Changed()
+ _123aChanged()
+ }
+
+ TapHandler {
+ onTapped: myHelloHandler
+ function f() {
+ tapped()
+ }
+ }
+
+ function anotherF() {
+ helloPropertyChanged()
+ }
+ onHelloPropertyChanged: myHelloHandler
+ Type {}
+ function foo(mouse) {}
+
+ MouseArea {
+ id: area1
+ onClicked: foo
+ property int insideMouseArea1
+ }
+
+ MouseArea {
+ id: area2
+ Connections {
+ function onClicked(mouse) {
+ area1.clicked()
+ area3.clicked()
+ }
+ }
+ property int insideMouseArea2
+
+ MouseArea {id: area3}
+ }
+
+ property Connections c: Connections {
+ target: area3
+ onClicked: function(mouse) {
+ //
+ }
+ }
+ function useMouseAreas() {
+ area1.clicked()
+ area2.clicked()
+ area3.clicked()
+ }
+
+ function checkParameters(a: int, b: double, {x, y={}, z=[x,y]}) {
+ return a + b + c + x + y + z
+ }
+
+ function deconstructingUsages(xxx) {
+ let {a, b} = xxx;
+ let c = a + b;
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/JSUsagesFromAnotherFile.qml b/tests/auto/qmlls/utils/data/JSUsagesFromAnotherFile.qml
new file mode 100644
index 0000000000..eb0cbf70be
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/JSUsagesFromAnotherFile.qml
@@ -0,0 +1,16 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+JSUsages {
+ function f() {
+ // sanity check: reuse variable names from function f in JSUsages. Those should not appear
+ // as usages of the sum of JSUsages.
+ let sum = 0;
+ sum += 1;
+ sum += helloProperty + 32 // valid usage of JSUsages's helloProperty
+ return sum
+ }
+
+}
diff --git a/tests/auto/qmlls/utils/data/Type.qml b/tests/auto/qmlls/utils/data/Type.qml
new file mode 100644
index 0000000000..2d0a32cfb4
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/Type.qml
@@ -0,0 +1,30 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.15
+
+BaseType {
+ id: derived
+ property int inTypeDotQml
+
+ component MyInlineComponent: BaseType {
+ id: derivedInIC
+ property int inMyInlineComponent
+ }
+
+ property BaseType inlineType: BaseType {
+ id: derivedInline
+ }
+
+ property MyInlineComponent icType: MyInlineComponent {
+ id:derivedInIcInline
+ }
+
+ property var icType2: BaseType.MyBaseInlineComponent {
+ id:derivedInIcInline2
+ }
+
+ property var nestedIcType: BaseType.MyNestedInlineComponent {
+ id:derivedInIcInline3
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/Yyy.qml b/tests/auto/qmlls/utils/data/Yyy.qml
new file mode 100644
index 0000000000..6c3886c0a4
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/Yyy.qml
@@ -0,0 +1,143 @@
+import QtQuick 2.0
+import QtQuick as QQ
+import QtCore
+Zzz {
+ id: root
+ width: height
+ Rectangle {
+ color: "green"
+ anchors.fill: parent
+ width: root.height
+ height: root.foo.height
+
+ }
+ component MyRectangle: Rectangle {}
+ function lala() {}
+ property Rectangle foo: Rectangle{ height: 200 }
+ function longfunction(a, b, c = "c", d = "d"): string {
+ return "hehe: " + c + d
+ }
+
+ // documentedFunction: is documented
+ // returns 'Good'
+ function documentedFunction(arg1, arg2 = "Qt"): string {
+ return "Good"
+ }
+ QQ.Rectangle {
+ color:"red"
+ }
+
+ Item {
+ id: someItem
+ property int helloProperty
+ }
+
+ function parameterCompletion(helloWorld, helloMe: int) {
+ let helloVar = 42;
+ let result = someItem.helloProperty + helloWorld;
+ return result;
+ }
+
+ component Base: QtObject {
+ property int propertyInBase
+ function functionInBase(jsParameterInBase) {
+ let jsIdentifierInBase;
+ return jsIdentifierInBase;
+ }
+ }
+
+ Base {
+ property int propertyInDerived
+ function functionInDerived(jsParameterInDerived) {
+ let jsIdentifierInDerived;
+ return jsIdentifierInDerived;
+ }
+
+ property Base child: Base {
+ property int propertyInChild
+ function functionInChild(jsParameterInChild) {
+ let jsIdentifierInChild;
+ return someItem.helloProperty;
+ }
+ }
+ }
+ function test1() {
+ {
+ var helloVarVariable = 42;
+ }
+ // this is fine, var has no block scope
+ console.log(helloVarVariable);
+ }
+ function test2() {
+ {
+ let helloLetVariable = 42;
+ }
+ // this is not fine, let variables have block scope
+ console.log(helloLetVariable);
+ }
+ property var testSingleton: SystemInformation.byteOrder
+
+
+
+ enum Hello { World }
+ enum MyEnum { ValueOne, ValueTwo }
+
+
+ property var testEnums: Yyy.World
+ property var testEnums2: Yyy.Hello.World
+
+ Component.onCompleted: {}
+ property var anything: Rectangle{ height: 200 }
+ function createRectangle(): Rectangle {}
+ function createItem(): Item {}
+ function createAnything() {}
+ function helloJSStatements() {
+ let x = 3;
+ }
+ required property int requiredProperty
+ readonly property int readonlyProperty: 456
+ default property int defaultProperty
+ property int builtin: Math.abs(43)
+ signal handleMe()
+ function helloForStatement() {
+ for(let i = 0; i < 5; ++i) {
+
+ }
+ for(let j = 0; j < 5; ++j)
+ helloForStatement()
+ }
+ function helloIfStatement(hello) {
+ if (hello)
+ hello = !hello
+ else
+ hello = hello
+ if (hello == !hello) {
+ hello = hello / hello
+ } else {
+ hello += hello
+ }
+ if (hello)
+ hello = hello
+ else if (hello)
+ hello = hello + hello / 2
+ }
+ function helloReturnStatement(hello) {
+ return hello
+ }
+ function helloWhileStatement(hello) {
+ while (hello) --hello
+ }
+ function helloDoWhileStatement(hello) {
+ do --hello; while (hello);
+ }
+ function helloForEachStatement(hello) {
+ for(variable in hello) ++hello;
+ for(element of hello) ++hello;
+ }
+ function qualifiedScriptIdentifiers() {
+ console.l()
+ }
+ QtObject {
+
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/Zzz.qml b/tests/auto/qmlls/utils/data/Zzz.qml
new file mode 100644
index 0000000000..fa0edf69dc
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/Zzz.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.11
+
+Item {
+ id: zzz
+ height: 333
+
+ Rectangle {
+ width: zzz.height
+ }
+
+ property int propertyOfZZZ
+}
diff --git a/tests/auto/qmlls/utils/data/completions/afterDots.qml b/tests/auto/qmlls/utils/data/completions/afterDots.qml
new file mode 100644
index 0000000000..0659425195
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/afterDots.qml
@@ -0,0 +1,20 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+QtObject {
+ id: root
+ property int good
+ property var i: Item {
+ property int bad
+ property int myP: root.
+ Item { }
+ property int myP2: root.;
+ bad: 43
+ function f() {
+ root.;
+ for (;;) {}
+ }
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/completions/attachedAndGroupedProperty.qml b/tests/auto/qmlls/utils/data/completions/attachedAndGroupedProperty.qml
new file mode 100644
index 0000000000..5736938d73
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/attachedAndGroupedProperty.qml
@@ -0,0 +1,12 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ property int bad
+ Component.a: {}
+ Text {
+ font.f: ""
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/completions/attachedPropertyMissingRHS.qml b/tests/auto/qmlls/utils/data/completions/attachedPropertyMissingRHS.qml
new file mode 100644
index 0000000000..38aca7ef7a
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/attachedPropertyMissingRHS.qml
@@ -0,0 +1,8 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ Component.on
+}
diff --git a/tests/auto/qmlls/utils/data/completions/boundComponents.qml b/tests/auto/qmlls/utils/data/completions/boundComponents.qml
new file mode 100644
index 0000000000..343e7a3c7b
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/boundComponents.qml
@@ -0,0 +1,21 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ id: rootId
+ property int inRoot
+
+ DelegateModel {
+ delegate: Item {
+ id: childId
+
+ property int myInt: rootId.inRoot
+ property int inChild
+
+ }
+ }
+
+ property int myInt: childId.inChild
+}
diff --git a/tests/auto/qmlls/utils/data/completions/commaExpression.qml b/tests/auto/qmlls/utils/data/completions/commaExpression.qml
new file mode 100644
index 0000000000..de74d07c1d
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/commaExpression.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ function f(a,b,c) {
+ f(a,a,a), b += 55,c *= 24;
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/completions/conditionalExpression.qml b/tests/auto/qmlls/utils/data/completions/conditionalExpression.qml
new file mode 100644
index 0000000000..933c71d26c
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/conditionalExpression.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ function f(a,b,c) {
+ a == b ? b == c ? c : b + 3 : 42
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/completions/continueAndBreakStatement.qml b/tests/auto/qmlls/utils/data/completions/continueAndBreakStatement.qml
new file mode 100644
index 0000000000..243f206db9
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/continueAndBreakStatement.qml
@@ -0,0 +1,31 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function f(x) {
+ label1: f(f(x))
+
+ nestedLabel1: for (let i = 0; i < 3; ++i) {
+ nestedLabel2: for (let j = 0; j < 3; ++j) {
+ continue nestedLabel1;
+ break nestedLabel2;
+ }
+ }
+
+ multiLabel1:
+ multiLabel2: {
+ f(1 + f(x))
+ continue multiLabel1
+ break multiLabel2
+ }
+
+ for(;;) {
+ continue ;
+ break ;
+ }
+
+ return x + y
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/completions/functionBody.qml b/tests/auto/qmlls/utils/data/completions/functionBody.qml
new file mode 100644
index 0000000000..755f136d7d
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/functionBody.qml
@@ -0,0 +1,13 @@
+import QtQuick
+
+Item {
+ function f(x) {
+
+ }
+
+ property int badProperty
+ component IC: Item { property int helloProperty }
+ function g(x: IC) {
+ x.helloProperty
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/completions/groupedPropertyMissingRHS.qml b/tests/auto/qmlls/utils/data/completions/groupedPropertyMissingRHS.qml
new file mode 100644
index 0000000000..44fbd022ba
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/groupedPropertyMissingRHS.qml
@@ -0,0 +1,8 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Text {
+ font.fa
+}
diff --git a/tests/auto/qmlls/utils/data/completions/labelledStatement.qml b/tests/auto/qmlls/utils/data/completions/labelledStatement.qml
new file mode 100644
index 0000000000..e223d6465b
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/labelledStatement.qml
@@ -0,0 +1,20 @@
+import QtQuick
+
+Item {
+ function f(x) {
+ label1: f(f(x))
+
+ nestedLabel1: for (let i = 0; i < 3; ++i) {
+ nestedLabel2: for (let j = 0; j < 3; ++j) {
+ if (i === 1 && j === 1) {
+ continue nestedLabel1;
+ }
+ }
+ }
+
+ multilabel1:
+ multilabel2: f(1 + f(x))
+
+ return x + y
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/completions/missingRHS.parserfail.qml b/tests/auto/qmlls/utils/data/completions/missingRHS.parserfail.qml
new file mode 100644
index 0000000000..ce594d9f16
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/missingRHS.parserfail.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+Item {
+ function f() {
+ let x = root.
+ let y = root.
+ for(;;) {}
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/completions/missingRHS.qml b/tests/auto/qmlls/utils/data/completions/missingRHS.qml
new file mode 100644
index 0000000000..1423f5c17e
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/missingRHS.qml
@@ -0,0 +1,19 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+ import QtQuick
+
+ Item {
+ id: root
+ property int good
+ Item {
+ property int bad
+ function f() {
+ return root.
+ }
+ property int boom: root.
+ Item {
+ property int helloSubItem
+ }
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/completions/parenthesizedExpression.qml b/tests/auto/qmlls/utils/data/completions/parenthesizedExpression.qml
new file mode 100644
index 0000000000..567b543154
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/parenthesizedExpression.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function f(x) {
+ (x + 1)
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/completions/quickcontrols_and_quicktemplates/qualifiedTypesCompletion.qml b/tests/auto/qmlls/utils/data/completions/quickcontrols_and_quicktemplates/qualifiedTypesCompletion.qml
new file mode 100644
index 0000000000..50bc0976c8
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/quickcontrols_and_quicktemplates/qualifiedTypesCompletion.qml
@@ -0,0 +1,11 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Templates as T
+
+Item {
+ T.Button {}
+ function f(x: T.Button) {}
+}
diff --git a/tests/auto/qmlls/utils/data/completions/returnStatement.qml b/tests/auto/qmlls/utils/data/completions/returnStatement.qml
new file mode 100644
index 0000000000..e5203652b7
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/returnStatement.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function f(x) {
+ return
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/completions/suggestContinueAndBreak.qml b/tests/auto/qmlls/utils/data/completions/suggestContinueAndBreak.qml
new file mode 100644
index 0000000000..89855e1584
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/suggestContinueAndBreak.qml
@@ -0,0 +1,54 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function f(x) {
+ // sanity check: no break or continue allowed in function body
+
+ for(let i = 0; i < 5; ++i) {
+ // break and continue allowed in loop
+ }
+
+ switch(x) {
+ // no break allowed here
+ case 3:
+ // break allowed in case
+ default:
+ // break allowed in default
+ case f("helloWorld"):
+ // break allowed in moreCase
+ }
+
+ helloLabel: {
+ // break allowed in labelledstatement
+ }
+
+ // combinations:
+ combiLabel: {
+ // break allowed in labelledstatement
+ for(let i = 0; i < 5; ++i) {
+ // break and continue allowed in loop
+
+ switch(x) {
+ default:
+ // break allowed in default + continue for loop
+ }
+ }
+
+ switch(x) {
+ case 3:
+ default:
+ case f("helloWorld"):
+ // no continue allowed here
+
+ for(let i = 0; i < 5; ++i) {
+ // break and continue allowed in loop
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/tests/auto/qmlls/utils/data/completions/switchStatements.qml b/tests/auto/qmlls/utils/data/completions/switchStatements.qml
new file mode 100644
index 0000000000..f9ddf3f2a1
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/switchStatements.qml
@@ -0,0 +1,37 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ property int myProperty;
+ function g(x) { return x + 1; }
+ function f(x) {
+ switch(x) {
+
+ case 1:
+ return 0;
+ case g(x) + 3: {
+ return 1;
+ }
+ }
+
+ switch(x) {
+ case 42:
+ myProperty = x + f(x)
+ myProperty = myProperty * 0.33
+ default:
+ return 123456
+ case 666:
+ for(;;) {
+ g(x)
+ }
+ myProperty = "hello"
+ }
+ switch(x) {
+ default:
+ break;
+ }
+ }
+
+}
diff --git a/tests/auto/qmlls/utils/data/completions/throwStatement.qml b/tests/auto/qmlls/utils/data/completions/throwStatement.qml
new file mode 100644
index 0000000000..927c885f54
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/throwStatement.qml
@@ -0,0 +1,11 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function f(x) {
+ throw 1;
+ throw { x: "myError" };
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/completions/tryStatements.qml b/tests/auto/qmlls/utils/data/completions/tryStatements.qml
new file mode 100644
index 0000000000..5fb261a388
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/tryStatements.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ function f() {
+ try { } catch(x) { } finally { }
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/completions/unaryExpression.qml b/tests/auto/qmlls/utils/data/completions/unaryExpression.qml
new file mode 100644
index 0000000000..f2ba099a7a
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/unaryExpression.qml
@@ -0,0 +1,17 @@
+import QtQuick
+
+Item {
+ function f(x) {
+ -x;
+ +x;
+ ~x;
+ !x;
+ typeof x;
+ delete x;
+ void x;
+ x--;
+ x++;
+ --x;
+ ++x;
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/completions/variableDeclaration.qml b/tests/auto/qmlls/utils/data/completions/variableDeclaration.qml
new file mode 100644
index 0000000000..2a32c2ff44
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/completions/variableDeclaration.qml
@@ -0,0 +1,36 @@
+import QtQuick
+
+Item {
+ function data() { return 42; }
+
+ function f(x) {
+ let letStatement = data();
+ const constStatement = data();
+ var varStatement = data(); // bad?
+ }
+
+ function objects(x) {
+ let { deconstructed } = data();
+ let { deconstructedAloneWithInitializer = 55 } = data();
+ let { deconstructedWithInitializer1 = 55, deconstructedWithInitializer2 = 66 } = data(), { unused: deconstructedWithInitializer3 = 77, } = data() ;
+ }
+
+ function arrays(x) {
+ let [ deconstructed ] = data();
+ let [ deconstructedAloneWithInitializer = 55 ] = data();
+ let [ deconstructedWithInitializer1 = 55, deconstructedWithInitializer2 = 66 ] = data(), [ deconstructedWithInitializer3 = 77, ] = data() ;
+ }
+
+ function oneArrayingToRuleThemAll(x) {
+ let [ head, [headOfSecond = 44, secondOfSecond = 55], [_ = "useless", secondOfThird = g()], [ [ headOfHeadOfFourth = g() + 1] ] ] = data();
+ }
+
+ function needleInTheHarraystack(x) {
+ let [ head, [headOfSecond = 44, secondOfSecond = 55], [_ = "useless", secondOfThird = g(), { needle = "x" }], [ [ headOfHeadOfFourth = g() + 1] ] ] = data();
+ }
+
+ function arrayInTheObject(x) {
+ let { p: [first, second] } = { p: [1,2] };
+ }
+
+}
diff --git a/tests/auto/qmlls/utils/data/emptyFile.qml b/tests/auto/qmlls/utils/data/emptyFile.qml
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/emptyFile.qml
diff --git a/tests/auto/qmlls/utils/data/file1.qml b/tests/auto/qmlls/utils/data/file1.qml
new file mode 100644
index 0000000000..c069a62a43
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/file1.qml
@@ -0,0 +1,55 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.15
+
+Item {
+ component C: Item {}
+
+ property int a
+ property bool b
+ property C c
+ property var d
+ property list<int> e
+
+ component D: Item { id: icid }
+ C {id: firstC }D{id: firstD }
+ C { id: secondC } D{ id: secondD}
+ C {
+ C{}
+ C{
+ C {}
+ C {}
+ C {}
+ }
+ C{}
+ }
+
+ component IC: Item { property C myC }
+
+ a: 43
+ d: 123 + 7
+
+ function f(a: int, b: Item, c: C) : C {
+ return c;
+ }
+ function lala() {}
+
+ Rectangle {
+ color: "green"
+ anchors.fill: parent
+ width: root.height
+ height: root.foo.height
+ }
+ property Rectangle foo: Rectangle{ height: 200 }
+
+ c: C{}
+ property C ccc: c
+ property C cccc
+ cccc: c
+
+ function fff(a: int, b: Item, c: C) : C {
+ let x = c.children;
+ return x;
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/attachedPropertyUsage/attachedPropertyUsage.qml b/tests/auto/qmlls/utils/data/findUsages/attachedPropertyUsage/attachedPropertyUsage.qml
new file mode 100644
index 0000000000..897d153e84
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/attachedPropertyUsage/attachedPropertyUsage.qml
@@ -0,0 +1,14 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ id: root
+
+ Keys.onPressed: {}
+
+ MouseArea {
+ onClicked: root.Keys.enabled = false
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/binding/binding.qml b/tests/auto/qmlls/utils/data/findUsages/binding/binding.qml
new file mode 100644
index 0000000000..c0a06dd6fd
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/binding/binding.qml
@@ -0,0 +1,11 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Text {
+ id: textRoot
+
+ property int helloPropertyBinding
+ helloPropertyBinding: 123
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/bindings/bindings.qml b/tests/auto/qmlls/utils/data/findUsages/bindings/bindings.qml
new file mode 100644
index 0000000000..f4d4c74aff
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/bindings/bindings.qml
@@ -0,0 +1,39 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+import QtQuick
+
+Item {
+ id: root
+ property bool patronChanged // shouldn't be found
+
+ Item {
+ id: inner
+ property bool patronChanged
+
+ Binding on patronChanged {
+ value: !inner.patronChanged
+ when: root.patronChanged // // shouldn't be found
+ }
+
+ Binding {
+ target: inner
+ property: "patronChanged"
+ value: !inner.patronChanged
+ when: root.patronChanged // shouldn't be found
+ }
+
+ // generalized dot
+ Binding {
+ inner.patronChanged: !inner.patronChanged
+ when: root.patronChanged // // shouldn't be found
+ }
+
+ // generalized block
+ Binding {
+ inner {
+ patronChanged: false
+ }
+ when: root.patronChanged // // shouldn't be found
+ }
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/connections/connections.qml b/tests/auto/qmlls/utils/data/findUsages/connections/connections.qml
new file mode 100644
index 0000000000..c933faca09
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/connections/connections.qml
@@ -0,0 +1,37 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+Item {
+
+ MouseArea {
+ id: area1
+ onClicked: foo
+ property int insideMouseArea1
+ }
+
+ MouseArea {
+ id: area2
+ Connections {
+ function onClicked(mouse) {
+ area1.clicked()
+ area3.clicked()
+ }
+ }
+ property int insideMouseArea2
+
+ MouseArea {id: area3}
+ }
+
+ property Connections c: Connections {
+ target: area3
+ onClicked: function(mouse) {
+ //
+ }
+ }
+ function useMouseAreas() {
+ area1.clicked()
+ area2.clicked()
+ area3.clicked()
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/enums/Enums.qml b/tests/auto/qmlls/utils/data/findUsages/enums/Enums.qml
new file mode 100644
index 0000000000..a60bb38053
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/enums/Enums.qml
@@ -0,0 +1,27 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+
+ enum Cats {
+ Patron = 8,
+ Mafik = 7,
+ Kivrik = 2
+ }
+
+ property var inner: QtObject {
+ enum Cats {
+ Patron = -8, // Shouldn't be found
+ Mafik = -7,
+ Kivrik = -2
+ }
+ }
+
+ property int main: Enums.Cats.Patron
+ property int innerVal: Enums.Patron
+ property int illegal1: Cats.Patron // Shouldn't be found
+ property int illegal2: Patron // Shouldn't be found
+ property int alien: EnumsFromAnotherFile.FromAnotherUniverse
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/enums/EnumsFromAnotherFile.qml b/tests/auto/qmlls/utils/data/findUsages/enums/EnumsFromAnotherFile.qml
new file mode 100644
index 0000000000..9f5bf491fd
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/enums/EnumsFromAnotherFile.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Item {
+ enum FromAnotherFile { FromAnotherWorld, FromAnotherDimension, FromAnotherUniverse }
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/groupPropertyUsage/fontFamilyUsage.qml b/tests/auto/qmlls/utils/data/findUsages/groupPropertyUsage/fontFamilyUsage.qml
new file mode 100644
index 0000000000..61880d13ff
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/groupPropertyUsage/fontFamilyUsage.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ property font myFont
+ property var family: myFont.family
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/groupPropertyUsage/groupPropertyUsage.qml b/tests/auto/qmlls/utils/data/findUsages/groupPropertyUsage/groupPropertyUsage.qml
new file mode 100644
index 0000000000..167ccbb30e
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/groupPropertyUsage/groupPropertyUsage.qml
@@ -0,0 +1,35 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Text {
+ id: textRoot
+
+ Test {
+ id: test
+ myText {
+ font {
+ pixelSize: 12
+ family: "serif"
+ }
+ }
+ }
+
+ component Test : Text{
+ property Text myText
+ }
+
+ font.family: test.myText.font.family
+ font {
+ pixelSize: 12
+ }
+
+ Item {
+ property var family // should not be in groupPropertyUsages1
+ property int font // should not be in groupPropertyUsages2
+
+ property var realFont: textRoot.font // should be in groupPropertyUsages2
+ property var realFamily: textRoot.font.family // should be in groupPropertyUsages1
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/idUsages/idUsages.qml b/tests/auto/qmlls/utils/data/findUsages/idUsages/idUsages.qml
new file mode 100644
index 0000000000..14506b2202
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/idUsages/idUsages.qml
@@ -0,0 +1,19 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ id: rootId
+ Rectangle {
+ function f() {
+ if (widthChanged())
+ rootId.widthChanged();
+ return rootId.x
+ }
+ }
+
+ function t() {
+ rootId.widthChanged();
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/inlineComponents/InlineComponentProvider.qml b/tests/auto/qmlls/utils/data/findUsages/inlineComponents/InlineComponentProvider.qml
new file mode 100644
index 0000000000..bfe8d99020
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/inlineComponents/InlineComponentProvider.qml
@@ -0,0 +1,23 @@
+import QtQuick
+
+Item {
+ component IC1: Item { property int inIc1: 123 }
+ component IC2: Item { property IC1 inIc2 }
+
+ IC1 {
+ id: firstUsage
+ property int inFirstUsage
+ }
+ IC2 {
+ id: secondUsage
+ property int inSecondUsage
+ }
+ Item {
+ Item {
+ IC1 {
+ id: thirdUsage
+ property int inThirdUsage
+ }
+ }
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/inlineComponents/inlineComponents.qml b/tests/auto/qmlls/utils/data/findUsages/inlineComponents/inlineComponents.qml
new file mode 100644
index 0000000000..6631dc3448
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/inlineComponents/inlineComponents.qml
@@ -0,0 +1,26 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+
+ component Patron: QtObject {
+ property int foo
+ Component.onCompleted: console.log(foo)
+ }
+
+ component Mafik: Patron {
+ property int bar: foo
+ }
+
+ property int foo // should not be in inlineUsages
+ property var realFoo: Mafik {
+ function f() {
+ return foo; // should be in inlineUsages
+ }
+ }
+
+ property InlineComponentProvider fromAnotherFile: InlineComponentProvider {}
+ property InlineComponentProvider.IC1 fromAnotherFile2: InlineComponentProvider.IC1 {}
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/inlineComponents/inlineComponents2.qml b/tests/auto/qmlls/utils/data/findUsages/inlineComponents/inlineComponents2.qml
new file mode 100644
index 0000000000..49430d4b7d
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/inlineComponents/inlineComponents2.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+Item {
+ component MyIC: Item {}
+ MyIC { MyIC{} MyIC {}}
+ function f(x: MyIC): MyIC {
+ return x;
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/jsIdentifier/jsIdentifier.qml b/tests/auto/qmlls/utils/data/findUsages/jsIdentifier/jsIdentifier.qml
new file mode 100644
index 0000000000..9d844eab3b
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/jsIdentifier/jsIdentifier.qml
@@ -0,0 +1,16 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ function f() {
+ let sum = 0, sum2 = 0
+ for(let i = 1; i < 42; i = i + 2) {
+ sum = sum + i
+ {
+ let sum = 42; // another unrelated sum
+ }
+ }
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/parametersAndDeconstruction/parametersAndDeconstruction.qml b/tests/auto/qmlls/utils/data/findUsages/parametersAndDeconstruction/parametersAndDeconstruction.qml
new file mode 100644
index 0000000000..566b8648bb
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/parametersAndDeconstruction/parametersAndDeconstruction.qml
@@ -0,0 +1,16 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+
+ function checkParameters(a: int, b: double, {x, y={}, z=[x,y]}) {
+ return a + b + c + x + y + z
+ }
+
+ function deconstructingUsages(xxx) {
+ let {a, b} = xxx;
+ let c = a + b;
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/property/PropertyFromAnotherFile.qml b/tests/auto/qmlls/utils/data/findUsages/property/PropertyFromAnotherFile.qml
new file mode 100644
index 0000000000..b9197def63
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/property/PropertyFromAnotherFile.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int helloProperty
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/property/property.qml b/tests/auto/qmlls/utils/data/findUsages/property/property.qml
new file mode 100644
index 0000000000..25280c31f1
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/property/property.qml
@@ -0,0 +1,48 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ property int p2: 1
+ property int helloProperty: 0
+ function withProperty() {
+ let sum = 0, sum2 = 0
+ for(let i = 1; i < 42; i = i + 2) {
+ sum = sum + i
+ helloProperty = helloProperty + sum - i * p2;
+ {
+ let helloProperty = "evil"
+ }
+ }
+ }
+ function signalEmitter() {
+ helloProperty = 23;
+ helloPropertyChanged()
+ }
+ onHelloPropertyChanged: {}
+
+ // inline component
+ component IC: Item {
+ property var helloProperty
+ function f() {
+ return helloProperty + p2
+ }
+ }
+
+ //sub item
+ Item {
+ function f() {
+ return helloProperty + p2
+ }
+ property string helloProperty
+ }
+
+ PropertyFromAnotherFile {
+ helloProperty: 42
+ function f() {
+ return helloProperty + 53;
+ }
+ onHelloPropertyChanged: f()
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/propertyChanges/propertyChanges.qml b/tests/auto/qmlls/utils/data/findUsages/propertyChanges/propertyChanges.qml
new file mode 100644
index 0000000000..255f1c7ede
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/propertyChanges/propertyChanges.qml
@@ -0,0 +1,35 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+Item {
+ MouseArea {
+ id: mouse11
+ onClicked: doSomething()
+ property rect r
+ }
+
+ states: [
+ State {
+ PropertyChanges {
+ mouse11 { // block notation
+ onClicked: doSomethingElse()
+ r : 34
+ }
+ mouse11.onClicked: doSomething(); // dot notation
+ }
+
+ // with target property
+ PropertyChanges {
+ target: mouse11
+ onClicked: doSomethingElse()
+ r: 45
+ }
+ }
+ ]
+ function doSomething() {}
+ function doSomethingElse() {}
+
+ property rect r // shouldn't be found
+ property int clicked // shouldn't be gound
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile.qml b/tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile.qml
new file mode 100644
index 0000000000..c11802ffc2
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ property NestedComponentInFile2 inner
+ property int p2
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile2.qml b/tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile2.qml
new file mode 100644
index 0000000000..ece2913758
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile2.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ property NestedComponentInFile3 inner
+ property int p2
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile3.qml b/tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile3.qml
new file mode 100644
index 0000000000..4cddcb5cfe
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile3.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ property NestedComponentInFile4 inner
+ property int p2
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile4.qml b/tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile4.qml
new file mode 100644
index 0000000000..2dee832ff8
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/propertyInNested/NestedComponentInFile4.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ property int helloProperty
+ property int p2
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/propertyInNested/propertyInNested.qml b/tests/auto/qmlls/utils/data/findUsages/propertyInNested/propertyInNested.qml
new file mode 100644
index 0000000000..0eb493886a
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/propertyInNested/propertyInNested.qml
@@ -0,0 +1,56 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ property int p2: 1
+
+ component NestedComponent: Item {
+ property NestedComponent2 inner: NestedComponent2 {}
+ property int p2
+ }
+ component NestedComponent2: Item {
+ property NestedComponent3 inner
+ property int p2
+ inner: NestedComponent3 {}
+ }
+ component NestedComponent3: Item {
+ property NestedComponent4 inner
+ property int p2
+ inner: NestedComponent4 {}
+
+ }
+ component NestedComponent4: Item {
+ property int helloProperty
+ property int p2
+ }
+ NestedComponent {
+ id: myNested
+ }
+ function nestedUsages() {
+ let x = myNested.inner.inner.inner.helloProperty;
+ let a = myNested.p2 + p2
+ let b = myNested.inner.p2 + p2
+ let c = myNested.inner.inner.p2 + p2
+ let d = myNested.inner.inner.inner.p2 + p2
+ }
+
+ function f() {
+ {
+ let _p2 = 34;
+ return _p2 + p2
+ }
+ }
+
+ NestedComponentInFile {
+ id: myNestedInFile
+ }
+ function nestedUsagesInFile() {
+ let x = myNestedInFile.inner.inner.inner.helloProperty;
+ let a = myNestedInFile.p2
+ let b = myNestedInFile.inner.p2
+ let c = myNestedInFile.inner.inner.p2
+ let d = myNestedInFile.inner.inner.inner.p2
+ }
+} \ No newline at end of file
diff --git a/tests/auto/qmlls/utils/data/findUsages/recursive/RecursiveInOtherFile.qml b/tests/auto/qmlls/utils/data/findUsages/recursive/RecursiveInOtherFile.qml
new file mode 100644
index 0000000000..8a7f2d04ff
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/recursive/RecursiveInOtherFile.qml
@@ -0,0 +1,10 @@
+import QtQuick
+
+Item {
+ function recursive(n: int): int {
+ if (n > 3)
+ return 1 + recursive(recursive(x-1) + recursive(x-2) - recursive(x-3));
+ else
+ return recursive(0);
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/recursive/recursive.qml b/tests/auto/qmlls/utils/data/findUsages/recursive/recursive.qml
new file mode 100644
index 0000000000..45939bc89a
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/recursive/recursive.qml
@@ -0,0 +1,28 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ id: rootId
+ function recursive(n: int): int {
+ if (n > 3)
+ return 1 + recursive(recursive(x-1) + recursive(x-2) - recursive(x-3));
+ else
+ return recursive(0);
+ }
+
+ property int helloRecursive: recursive(42)
+
+ Rectangle {
+ function f() {
+ return rootId.recursive(123)
+ }
+ }
+
+ RecursiveInOtherFile {
+ id: fromOtherFile
+ }
+
+ property int helloRecursiveFromOtherFile: fromOtherFile.recursive(42)
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/signalsAndHandlers/signalAndHandlers2.qml b/tests/auto/qmlls/utils/data/findUsages/signalsAndHandlers/signalAndHandlers2.qml
new file mode 100644
index 0000000000..d10768dd42
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/signalsAndHandlers/signalAndHandlers2.qml
@@ -0,0 +1,43 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function myHelloHandler() { let x = 32; }
+ onHelloSignal: myHelloHandler
+
+ property int helloPropertyBinding
+ helloPropertyBinding: 123
+
+ property int checkHandlers
+ onCheckHandlersChanged: myHelloHandler
+ onChildrenChanged: myHelloHandler
+ function callChanged() {
+ checkHandlersChanged()
+ childrenChanged()
+ }
+ property int _: 48
+ property int ______42: 48
+ property int _123a: 48
+ on_Changed: myHelloHandler
+ on______42Changed: myHelloHandler
+ on_123AChanged: myHelloHandler
+ function weirdPropertynames() {
+ _Changed()
+ ______42Changed()
+ _123aChanged()
+ }
+
+ TapHandler {
+ onTapped: myHelloHandler
+ function f() {
+ tapped()
+ }
+ }
+
+ function anotherF() {
+ helloPropertyChanged()
+ }
+ onHelloPropertyChanged: myHelloHandler
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/signalsAndHandlers/signalsAndHandlers.qml b/tests/auto/qmlls/utils/data/findUsages/signalsAndHandlers/signalsAndHandlers.qml
new file mode 100644
index 0000000000..47280bca46
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/signalsAndHandlers/signalsAndHandlers.qml
@@ -0,0 +1,40 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ id: rootId
+ signal helloSignal()
+
+ function callSignals() {
+ helloSignal()
+ if (false) {
+ helloSignal()
+ } else {
+ // helloSignal() // not a usage btw
+ if (true)
+ helloSignal()
+ }
+ }
+ function callSignals2() {
+ helloSignal()
+ if (false) {
+ widthChanged()
+ } else {
+ // helloSignal() // not a usage btw
+ if (true)
+ widthChanged()
+ rootId.widthChanged()
+ }
+ }
+ Item {
+ function callSignalsInChild() {
+ widthChanged()
+ rootId.widthChanged()
+ }
+ }
+
+ function myHelloHandler() { let x = 32; }
+ onHelloSignal: myHelloHandler
+}
diff --git a/tests/auto/qmlls/utils/data/findUsages/signalsAndHandlers/widthChangedInAnotherFile.qml b/tests/auto/qmlls/utils/data/findUsages/signalsAndHandlers/widthChangedInAnotherFile.qml
new file mode 100644
index 0000000000..aecee2437a
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/findUsages/signalsAndHandlers/widthChangedInAnotherFile.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ function f() {}
+ onWidthChanged: f
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/Identifiers.qml b/tests/auto/qmlls/utils/data/highlights/Identifiers.qml
new file mode 100644
index 0000000000..7725b6d5e4
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/Identifiers.qml
@@ -0,0 +1,37 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ readonly property int test: 34
+ signal pressed()
+ function f() {
+ let sum = 0, sum2 = 0
+ for(let i = 1; i < 42; i = i + 2) {
+ sum = test + i
+ {
+ let sum = 42; // another unrelated sum
+ }
+ }
+ // signal and property changed
+ testChanged();
+ pressed();
+ }
+
+ // attached
+ Keys.onPressed: {
+ }
+
+ // propertychanged handler
+ onTestChanged: {
+ f(); // method identifier
+ }
+
+ // signal handler
+ onPressed: {}
+
+ enum K { Plus}
+ property int tt: Identifiers.Plus // component and enum value
+
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/bindings.qml b/tests/auto/qmlls/utils/data/highlights/bindings.qml
new file mode 100644
index 0000000000..ac1592e778
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/bindings.qml
@@ -0,0 +1,12 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ property int x: 45
+
+ Behavior on width {}
+
+ x: width
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/comments.qml b/tests/auto/qmlls/utils/data/highlights/comments.qml
new file mode 100644
index 0000000000..351aaee36c
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/comments.qml
@@ -0,0 +1,19 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+import QtQuick
+Item {
+/*
+ multiline comment
+*/
+
+/* single line comment */
+// another
+
+ function inc() {
+ // in
+
+ /*
+ inside js
+ */
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/enums.qml b/tests/auto/qmlls/utils/data/highlights/enums.qml
new file mode 100644
index 0000000000..22183bf37f
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/enums.qml
@@ -0,0 +1,11 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ enum Osc {
+ Sin,
+ Saw = 1
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/imports.qml b/tests/auto/qmlls/utils/data/highlights/imports.qml
new file mode 100644
index 0000000000..1e69077070
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/imports.qml
@@ -0,0 +1,9 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQml 2.15
+import "X" as Patron
+
+Item {
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/literals.qml b/tests/auto/qmlls/utils/data/highlights/literals.qml
new file mode 100644
index 0000000000..520ed5d2ef
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/literals.qml
@@ -0,0 +1,14 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ property int a: 123
+ property string b: "single"
+ property string c: "multi
+ line string";
+ property bool d: true
+ property var e: null
+
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/methodAndSignal.qml b/tests/auto/qmlls/utils/data/highlights/methodAndSignal.qml
new file mode 100644
index 0000000000..4e8319f049
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/methodAndSignal.qml
@@ -0,0 +1,11 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ signal p()
+ signal q(int a)
+ signal r(a: int)
+ function a(b: int) : int {}
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/objectAndComponent.qml b/tests/auto/qmlls/utils/data/highlights/objectAndComponent.qml
new file mode 100644
index 0000000000..9165e4b1b5
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/objectAndComponent.qml
@@ -0,0 +1,11 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ component Patron: Item {}
+ Item {
+ id: inner
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/pragmas.qml b/tests/auto/qmlls/utils/data/highlights/pragmas.qml
new file mode 100644
index 0000000000..cf99c93584
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/pragmas.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+pragma Singleton
+pragma FunctionSignatureBehavior: Enforced
+pragma ValueTypeBehavior: Copy,Addressable
+
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qmlls/utils/data/highlights/properties.qml b/tests/auto/qmlls/utils/data/highlights/properties.qml
new file mode 100644
index 0000000000..bde60915ca
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/properties.qml
@@ -0,0 +1,13 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ Item {
+ property int k
+ readonly property int kk
+ required property int kkk
+ default property int kkkk
+ }
+}
diff --git a/tests/auto/qmlls/utils/data/highlights/scriptExpressions.qml b/tests/auto/qmlls/utils/data/highlights/scriptExpressions.qml
new file mode 100644
index 0000000000..ee0b4ff5f8
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/highlights/scriptExpressions.qml
@@ -0,0 +1,116 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function k() {
+ }
+
+ function mafik() {
+ var patron = 34;
+ const upperLimit = 42;
+ do {
+ ++patron;
+ if (patron < 2)
+ continue;
+ else
+ ++patron;
+ } while (patron < upperLimit)
+ switch (patron) {
+ case 1:
+ return 23;
+ default:
+ break;
+ }
+ try {
+ {}
+ } catch (error) {
+ {}
+ } finally {}
+ for (const a in [1, 2, 3]) {
+ throw 2;
+ }
+ }
+
+ enum Test {
+ LOG
+ }
+
+ readonly property int t: 34
+ signal tt
+ required property int k
+
+ signal kkk(string a)
+ signal yyy(a: string)
+
+ function ttt() {
+
+ }
+
+function createComplexExpression(...objects) {
+ // Create an object that holds some data
+ let data = {
+ a: 5,
+ b: 10,
+ c: 3
+ };
+
+ // Create a complex expression using the data object
+ let expression = ((data.a + data.b * data.c) / (data.a - data.b)) ** data.c;
+
+ return expression;
+}
+
+ function set1() {
+ const array = [1,2,3,4];
+ const [a, b] = [1,2];
+ const [aa, , bb] = array;
+ const [aaa = 23, bbb] = array;
+ const [a1, b1, ...rest1] = array;
+ const [a2, , b2, ...rest2] = array;
+ const [a3, b3, ...{ pop, push }] = array;
+ const [a4, b4, ...[c, d]] = array;
+
+ const obj = {_a:1,_b:2};
+ const { a5, b5 } = obj;
+ const { a6: a_, b6: b1_ } = obj;
+ const { a7: a11 = 4, b11 = 34, c1: b111, d1 } = obj;
+ let key = a;
+ const { [key]: a___ } = obj;
+ }
+
+ function set2(s : int) : int {
+ // declare first
+ let a, b, a1, b1, c, d, rest, pop, push;
+ const array = [1,2,3,4];
+ [a, b] = array;
+ [a, , b] = array;
+ [a = aDefault, b] = array;
+ [a, b, ...rest] = array;
+ [a, , b, ...rest] = array;
+ [a, b, ...{ pop, push }] = array;
+ [a, b, ...[c, d]] = array;
+
+ const obj = {_a:1,_b:2};
+ ({ a, b } = obj); // brackets are required
+ ({ a: a1, b: b1 } = obj);
+
+ const complicatedObject = {
+ a: 1,
+ b: {
+ c: 2,
+ d: {
+ e: 3,
+ f: [4, 5, 6]
+ }
+ },
+ g: [7, 8, 9]
+ };
+
+ const { patron, b: { mafik, d: { e, f: [ , secondF, ...restF ] } }, g: [ firstG, ...restG ] } = complicatedObject;
+ }
+
+
+}
+
diff --git a/tests/auto/qmlls/utils/data/pragmas.qml b/tests/auto/qmlls/utils/data/pragmas.qml
new file mode 100644
index 0000000000..bcb73cf10b
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/pragmas.qml
@@ -0,0 +1,8 @@
+pragma Singleton
+pragma NativeMethodBehavior: AcceptThisObject;
+pragma ListPropertyAssignBehavior: Append, Replace;
+import QtQuick 2.15
+
+Item {
+
+}
diff --git a/tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtqml-qtobject-qt-5.html b/tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtqml-qtobject-qt-5.html
new file mode 100644
index 0000000000..9c3ce4e0f2
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtqml-qtobject-qt-5.html
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+<!-- qqmlengine.cpp -->
+ <title>QtObject QML Type | Qt QML 5.15.16</title>
+ <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
+ <script type="text/javascript">
+ document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
+ // loading style sheet breaks anchors that were jumped to before
+ // so force jumping to anchor again
+ setTimeout(function() {
+ var anchor = location.hash;
+ // need to jump to different anchor first (e.g. none)
+ location.hash = "#";
+ setTimeout(function() {
+ location.hash = anchor;
+ }, 0);
+ }, 0);
+ </script>
+</head>
+<body>
+<div class="header" id="qtdocheader">
+ <div class="main">
+ <div class="main-rounded">
+ <div class="navigationbar">
+ <ul>
+<li><a href="../qtdoc/index.html" translate="no">Qt 5.15</a></li>
+<li><a href="qtqml-index.html" translate="no">Qt QML</a></li>
+<li><a href="qtqml-qmlmodule.html" translate="no">QML Types</a></li>
+<li>QtObject QML Type</li>
+<li id="buildversion"><a href="qtqml-index.html" translate="no">Qt 5.15.16 Reference Documentation</a></li>
+ </ul>
+ </div>
+</div>
+<div class="content">
+<div class="line">
+<div class="content mainContent">
+<div class="sidebar">
+<div class="toc">
+<h3><a name="toc">Contents</a></h3>
+<ul>
+<li class="level1"><a href="#properties">Properties</a></li>
+<li class="level1"><a href="#details">Detailed Description</a></li>
+</ul>
+</div>
+<div class="sidebar-content" id="sidebar-content"></div></div>
+<h1 class="title" translate="no">QtObject QML Type</h1>
+<span class="subtitle" translate="no"></span>
+<!-- $$$QtObject-brief -->
+<p>A basic QML type. <a href="#details">More...</a></p>
+<!-- @@@QtObject -->
+<div class="table"><table class="alignedsummary" translate="no">
+<tr><td class="memItemLeft rightAlign topAlign"> Import Statement:</td><td class="memItemRight bottomAlign"> import QtQml 2.15</td></tr><tr><td class="memItemLeft rightAlign topAlign"> Instantiates:</td><td class="memItemRight bottomAlign"> <a href="qml-qtqml-qtobject.html" translate="no"><a href="../qtcore/qobject.html" translate="no">QObject</a></td></tr></table></div><ul>
+<li><a href="qml-qtqml-qtobject-members.html">List of all members, including inherited members</a></li>
+</ul>
+<a name="properties"></a>
+<h2 id="properties">Properties</h2>
+<ul>
+<li class="fn" translate="no"><b><b><a href="qml-qtqml-qtobject.html#objectName-prop" translate="no">objectName</a></b></b> : string</li>
+</ul>
+<!-- $$$QtObject-description -->
+<a name="details"></a>
+<h2 id="details">Detailed Description</h2>
+<p>The QtObject type is a non-visual element which contains only the <a href="qml-qtqml-qtobject.html#objectName-prop" translate="no">objectName</a> property.</p>
+<p>It can be useful to create a QtObject if you need an extremely lightweight type to enclose a set of custom properties:</p>
+<pre class="qml" translate="no">
+ import QtQuick 2.0
+
+ <span class="type"><a href="../qtquick/qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="type"><a href="qml-qtqml-qtobject.html" translate="no">QtObject</a></span> {
+ <span class="name">id</span>: <span class="name">attributes</span>
+ property <span class="type"><a href="qml-string.html" translate="no">string</a></span> <span class="name">name</span>
+ property <span class="type"><a href="qml-int.html" translate="no">int</a></span> <span class="name">size</span>
+ property <span class="type"><a href="qml-variant.html" translate="no">variant</a></span> <span class="name">attributes</span>
+ }
+
+ <span class="type"><a href="../qtquick/qml-qtquick-text.html" translate="no">Text</a></span> { <span class="name">text</span>: <span class="name">attributes</span>.<span class="name">name</span> }
+ }
+</pre>
+<p>It can also be useful for C++ integration, as it is just a plain <a href="../qtcore/qobject.html" translate="no">QObject</a>. See the <a href="../qtcore/qobject.html" translate="no">QObject</a> documentation for further details.</p>
+<!-- @@@QtObject -->
+<h2>Property Documentation</h2>
+<!-- $$$objectName -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="objectName-prop">
+<td class="tblQmlPropNode"><p>
+<a name="objectName-prop"></a><span class="name">objectName</span> : <span class="type"><a href="qml-string.html" translate="no">string</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the <a href="../qtcore/qobject.html#objectName-prop" translate="no">QObject::objectName</a> for this specific object instance.</p>
+<p>This allows a C++ application to locate an item within a QML component using the <a href="../qtcore/qobject.html#findChild" translate="no">QObject::findChild()</a> method. For example, the following C++ application locates the child <a href="../qtquick/qml-qtquick-rectangle.html" translate="no">Rectangle</a> item and dynamically changes its <code translate="no">color</code> value:</p>
+<pre class="qml" translate="no">
+ <span class="comment">// MyRect.qml</span>
+
+ import QtQuick 2.0
+
+ <span class="type"><a href="../qtquick/qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="name">width</span>: <span class="number">200</span>; <span class="name">height</span>: <span class="number">200</span>
+
+ <span class="type"><a href="../qtquick/qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">anchors</span>.fill: <span class="name">parent</span>
+ <span class="name">color</span>: <span class="string">&quot;red&quot;</span>
+ <span class="name">objectName</span>: <span class="string">&quot;myRect&quot;</span>
+ }
+ }
+</pre>
+<pre class="cpp" translate="no">
+ <span class="comment">// main.cpp</span>
+
+ <span class="type">QQuickView</span> view;
+ view<span class="operator">.</span>setSource(<span class="type">QUrl</span><span class="operator">::</span>fromLocalFile(<span class="string">&quot;MyRect.qml&quot;</span>));
+ view<span class="operator">.</span>show();
+
+ <span class="type">QQuickItem</span> <span class="operator">*</span>item <span class="operator">=</span> view<span class="operator">.</span>rootObject()<span class="operator">-</span><span class="operator">&gt;</span>findChild<span class="operator">&lt;</span><span class="type">QQuickItem</span><span class="operator">*</span><span class="operator">&gt;</span>(<span class="string">&quot;myRect&quot;</span>);
+ <span class="keyword">if</span> (item)
+ item<span class="operator">-</span><span class="operator">&gt;</span>setProperty(<span class="string">&quot;color&quot;</span><span class="operator">,</span> <span class="type">QColor</span>(<span class="type"><a href="qml-qtqml-qt.html" translate="no">Qt</a></span><span class="operator">::</span>yellow));
+</pre>
+</div></div><!-- @@@objectName -->
+<br/>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<div class="footer">
+ <p>
+ <acronym title="Copyright">&copy;</acronym> 2023 The Qt Company Ltd.
+ Documentation contributions included herein are the copyrights of
+ their respective owners.<br/> The documentation provided herein is licensed under the terms of the <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation License version 1.3</a> as published by the Free Software Foundation.<br/> Qt and respective logos are <a href="https://doc.qt.io/qt/trademarks.html"> trademarks</a> of The Qt Company Ltd. in Finland and/or other countries
+ worldwide. All other trademarks are property of their respective owners. </p>
+</div>
+</body>
+</html>
diff --git a/tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtqml-qtobject.html b/tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtqml-qtobject.html
new file mode 100644
index 0000000000..16c218d2ff
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtqml-qtobject.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+<!-- qqmlengine.cpp -->
+ <meta name="description" content="A basic QML type.">
+ <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
+ <script type="text/javascript">
+ document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
+ // loading style sheet breaks anchors that were jumped to before
+ // so force jumping to anchor again
+ setTimeout(function() {
+ var anchor = location.hash;
+ // need to jump to different anchor first (e.g. none)
+ location.hash = "#";
+ setTimeout(function() {
+ location.hash = anchor;
+ }, 0);
+ }, 0);
+ </script>
+</head>
+<body>
+<div class="header" id="qtdocheader">
+ <div class="main">
+ <div class="main-rounded">
+ <div class="navigationbar">
+ <ul>
+<li><a href="qtqml-index.html" translate="no">Qt QML</a></li>
+<li><a href="qtqml-qmlmodule.html" translate="no">QML Types</a></li>
+<li>QtObject</li>
+ </ul>
+ </div>
+</div>
+<div class="content">
+<div class="line">
+<div class="content mainContent">
+<div class="sidebar">
+<div class="toc">
+<h3 id="toc">Contents</h3>
+<ul>
+<li class="level1"><a href="#properties">Properties</a></li>
+<li class="level1"><a href="#details">Detailed Description</a></li>
+</ul>
+</div>
+<div class="sidebar-content" id="sidebar-content"></div></div>
+<h1 class="title" translate="no">QtObject QML Type</h1>
+<!-- $$$QtObject-brief -->
+<p>A basic QML type. <a href="#details">More...</a></p>
+<!-- @@@QtObject -->
+<div class="table"><table class="alignedsummary" translate="no">
+<tr><td class="memItemLeft rightAlign topAlign"> Import Statement:</td><td class="memItemRight bottomAlign"> import QtQml</td></tr><tr><td class="memItemLeft rightAlign topAlign"> Instantiates:</td><td class="memItemRight bottomAlign"> <a href="../qtcore/qobject.html" translate="no">QObject</a></td></tr></table></div><ul>
+<li><a href="qml-qtqml-qtobject-members.html">List of all members, including inherited members</a></li>
+</ul>
+<h2 id="properties">Properties</h2>
+<ul>
+<li class="fn" translate="no"><b><a href="qml-qtqml-qtobject.html#objectName-prop" translate="no">objectName</a></b> : string</li>
+</ul>
+<!-- $$$QtObject-description -->
+<h2 id="details">Detailed Description</h2>
+<p>The QtObject type is a non-visual element which contains only the <a href="qml-qtqml-qtobject.html#objectName-prop" translate="no">objectName</a> property.</p>
+<p>It can be useful to create a QtObject if you need an extremely lightweight type to enclose a set of custom properties:</p>
+<pre class="qml" translate="no">
+ import QtQuick
+
+ <span class="type"><a href="../qtquick/qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="type"><a href="qml-qtqml-qtobject.html" translate="no">QtObject</a></span> {
+ <span class="name">id</span>: <span class="name">attributes</span>
+ property <span class="type"><a href="qml-string.html" translate="no">string</a></span> <span class="name">name</span>
+ property <span class="type"><a href="qml-int.html" translate="no">int</a></span> <span class="name">size</span>
+ property <span class="type"><a href="qml-variant.html" translate="no">variant</a></span> <span class="name">attributes</span>
+ }
+
+ <span class="type"><a href="../qtquick/qml-qtquick-text.html" translate="no">Text</a></span> { <span class="name">text</span>: <span class="name">attributes</span>.<span class="name">name</span> }
+ }
+</pre>
+<p>It can also be useful for C++ integration, as it is just a plain <a href="../qtcore/qobject.html" translate="no">QObject</a>. See the <a href="../qtcore/qobject.html" translate="no">QObject</a> documentation for further details.</p>
+<!-- @@@QtObject -->
+<h2>Property Documentation</h2>
+<!-- $$$objectName -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="objectName-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">objectName</span> : <span class="type"><a href="qml-string.html" translate="no">string</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the <a href="../qtcore/qobject.html#objectName-prop" translate="no">QObject::objectName</a> for this specific object instance.</p>
+<p>This allows a C++ application to locate an item within a QML component using the <a href="../qtcore/qobject.html#findChild" translate="no">QObject::findChild</a>() method. For example, the following C++ application locates the child <a href="../qtquick/qml-qtquick-rectangle.html" translate="no">Rectangle</a> item and dynamically changes its <code translate="no">color</code> value:</p>
+<pre class="qml" translate="no">
+ <span class="comment">// MyRect.qml</span>
+
+ import QtQuick 2.0
+
+ <span class="type"><a href="../qtquick/qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="name">width</span>: <span class="number">200</span>; <span class="name">height</span>: <span class="number">200</span>
+
+ <span class="type"><a href="../qtquick/qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">anchors</span>.fill: <span class="name">parent</span>
+ <span class="name">color</span>: <span class="string">&quot;red&quot;</span>
+ <span class="name">objectName</span>: <span class="string">&quot;myRect&quot;</span>
+ }
+ }
+</pre>
+<pre class="cpp" translate="no">
+ <span class="comment">// main.cpp</span>
+
+ <span class="type">QQuickView</span> view;
+ view<span class="operator">.</span>setSource(<span class="type">QUrl</span><span class="operator">::</span>fromLocalFile(<span class="string">&quot;MyRect.qml&quot;</span>));
+ view<span class="operator">.</span>show();
+
+ <span class="type">QQuickItem</span> <span class="operator">*</span>item <span class="operator">=</span> view<span class="operator">.</span>rootObject()<span class="operator">-</span><span class="operator">&gt;</span>findChild<span class="operator">&lt;</span><span class="type">QQuickItem</span><span class="operator">*</span><span class="operator">&gt;</span>(<span class="string">&quot;myRect&quot;</span>);
+ <span class="keyword">if</span> (item)
+ item<span class="operator">-</span><span class="operator">&gt;</span>setProperty(<span class="string">&quot;color&quot;</span><span class="operator">,</span> <span class="type">QColor</span>(<span class="type"><a href="qml-qtqml-qt.html" translate="no">Qt</a></span><span class="operator">::</span>yellow));
+</pre>
+</div></div><!-- @@@objectName -->
+<br/>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<div class="footer">
+ <p>
+ <acronym title="Copyright">&copy;</acronym> 2023 The Qt Company Ltd.
+ Documentation contributions included herein are the copyrights of
+ their respective owners.<br/> The documentation provided herein is licensed under the terms of the <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation License version 1.3</a> as published by the Free Software Foundation.<br/> Qt and respective logos are <a href="https://doc.qt.io/qt/trademarks.html"> trademarks</a> of The Qt Company Ltd. in Finland and/or other countries
+ worldwide. All other trademarks are property of their respective owners. </p>
+</div>
+</body>
+</html>
diff --git a/tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtquick-item.html b/tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtquick-item.html
new file mode 100644
index 0000000000..fc34b2d5db
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtquick-item.html
@@ -0,0 +1,1486 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+<!-- qquickitem.cpp -->
+ <meta name="description" content="A basic visual QML type.">
+ <title>Item QML Type | Qt Quick 6.8.0</title>
+ <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
+ <script type="text/javascript">
+ document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
+ // loading style sheet breaks anchors that were jumped to before
+ // so force jumping to anchor again
+ setTimeout(function() {
+ var anchor = location.hash;
+ // need to jump to different anchor first (e.g. none)
+ location.hash = "#";
+ setTimeout(function() {
+ location.hash = anchor;
+ }, 0);
+ }, 0);
+ </script>
+</head>
+<body>
+<div class="header" id="qtdocheader">
+ <div class="main">
+ <div class="main-rounded">
+ <div class="navigationbar">
+ <ul>
+<li><a href="../qtdoc/index.html" translate="no">Qt 6.8</a></li>
+<li><a href="qtquick-index.html" translate="no">Qt Quick</a></li>
+<li><a href="qtquick-qmlmodule.html" translate="no">QML Types</a></li>
+<li>Item</li>
+<li id="buildversion"><a href="qtquick-index.html" translate="no">Qt 6.8.0 Reference Documentation</a></li>
+ </ul>
+ </div>
+</div>
+<div class="content">
+<div class="line">
+<div class="content mainContent">
+<div class="sidebar">
+<div class="toc">
+<h3 id="toc">Contents</h3>
+<ul>
+<li class="level1"><a href="#properties">Properties</a></li>
+<li class="level1"><a href="#methods">Methods</a></li>
+<li class="level1"><a href="#details">Detailed Description</a></li>
+<li class="level2"><a href="#item-layers">Item Layers</a></li>
+</ul>
+</div>
+<div class="sidebar-content" id="sidebar-content"></div></div>
+<h1 class="title" translate="no">Item QML Type</h1>
+<!-- $$$Item-brief -->
+<p>A basic visual QML type. <a href="#details">More...</a></p>
+<!-- @@@Item -->
+<div class="table"><table class="alignedsummary" translate="no">
+<tr><td class="memItemLeft rightAlign topAlign"> Import Statement:</td><td class="memItemRight bottomAlign"> import QtQuick</td></tr><tr><td class="memItemLeft rightAlign topAlign"> Instantiates:</td><td class="memItemRight bottomAlign"> <a href="qquickitem.html" translate="no">QQuickItem</a></td></tr><tr><td class="memItemLeft rightAlign topAlign"> Inherits:</td><td class="memItemRight bottomAlign"> <p><a href="../qtqml/qml-qtqml-qtobject.html" translate="no">QtObject</a></p>
+</td></tr><tr><td class="memItemLeft rightAlign topAlign"> Inherited By:</td><td class="memItemRight bottomAlign"> <p><a href="qml-qtquick-animatedsprite.html" translate="no">AnimatedSprite</a>, <a href="qml-qtquick-borderimage.html" translate="no">BorderImage</a>, <a href="qml-qtquick-canvas.html" translate="no">Canvas</a>, <a href="qml-qtquick-column.html" translate="no">Column</a>, <a href="qml-qtquick-layouts-columnlayout.html" translate="no">ColumnLayout</a>, <a href="qml-qtquick-droparea.html" translate="no">DropArea</a>, <a href="qml-qtquick-flickable.html" translate="no">Flickable</a>, <a href="qml-qtquick-flipable.html" translate="no">Flipable</a>, <a href="qml-qtquick-flow.html" translate="no">Flow</a>, <a href="qml-qtquick-focusscope.html" translate="no">FocusScope</a>, <a href="qml-qtquick-grid.html" translate="no">Grid</a>, <a href="qml-qtquick-layouts-gridlayout.html" translate="no">GridLayout</a>, <a href="qml-qtquick-image.html" translate="no">Image</a>, <a href="qml-qtquick-layouts-layoutitemproxy.html" translate="no">LayoutItemProxy</a>, <a href="qml-qtquick-loader.html" translate="no">Loader</a>, <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a>, <a href="qml-qtquick-effects-multieffect.html" translate="no">MultiEffect</a>, <a href="qml-qtquick-multipointtoucharea.html" translate="no">MultiPointTouchArea</a>, <a href="qml-qtquick-particles-particlepainter.html" translate="no">ParticlePainter</a>, <a href="qml-qtquick-pathview.html" translate="no">PathView</a>, <a href="qml-qtquick-pincharea.html" translate="no">PinchArea</a>, <a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a>, <a href="qml-qtquick-repeater.html" translate="no">Repeater</a>, <a href="qml-qtquick-row.html" translate="no">Row</a>, <a href="qml-qtquick-layouts-rowlayout.html" translate="no">RowLayout</a>, <a href="qml-qtquick-shadereffect.html" translate="no">ShaderEffect</a>, <a href="qml-qtquick-shadereffectsource.html" translate="no">ShaderEffectSource</a>, <a href="qml-qtquick-shapes-shape.html" translate="no">Shape</a>, <a href="qml-qtquick-spritesequence.html" translate="no">SpriteSequence</a>, <a href="qml-qtquick-layouts-stacklayout.html" translate="no">StackLayout</a>, <a href="qml-qtquick-text.html" translate="no">Text</a>, <a href="qml-qtquick-textedit.html" translate="no">TextEdit</a>, <a href="qml-qtquick-textinput.html" translate="no">TextInput</a>, and <a href="qml-qtquick-windowcontainer.html" translate="no">WindowContainer</a></p>
+</td></tr></table></div><ul>
+<li><a href="qml-qtquick-item-members.html">List of all members, including inherited members</a></li>
+</ul>
+<h2 id="properties">Properties</h2>
+<ul>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#activeFocus-prop" translate="no">activeFocus</a></b> : bool</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#activeFocusOnTab-prop" translate="no">activeFocusOnTab</a></b> : bool</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors-prop" translate="no">anchors</a></b><ul>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.alignWhenCentered-prop" translate="no">anchors.alignWhenCentered</a></b> : bool</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.baseline-prop" translate="no">anchors.baseline</a></b> : AnchorLine</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.baselineOffset-prop" translate="no">anchors.baselineOffset</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.bottom-prop" translate="no">anchors.bottom</a></b> : AnchorLine</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.bottomMargin-prop" translate="no">anchors.bottomMargin</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.centerIn-prop" translate="no">anchors.centerIn</a></b> : Item</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.fill-prop" translate="no">anchors.fill</a></b> : Item</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.horizontalCenter-prop" translate="no">anchors.horizontalCenter</a></b> : AnchorLine</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.horizontalCenterOffset-prop" translate="no">anchors.horizontalCenterOffset</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.left-prop" translate="no">anchors.left</a></b> : AnchorLine</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.leftMargin-prop" translate="no">anchors.leftMargin</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.margins-prop" translate="no">anchors.margins</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.right-prop" translate="no">anchors.right</a></b> : AnchorLine</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.rightMargin-prop" translate="no">anchors.rightMargin</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.top-prop" translate="no">anchors.top</a></b> : AnchorLine</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.topMargin-prop" translate="no">anchors.topMargin</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.verticalCenter-prop" translate="no">anchors.verticalCenter</a></b> : AnchorLine</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#anchors.verticalCenterOffset-prop" translate="no">anchors.verticalCenterOffset</a></b> : real</li>
+</ul>
+</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#antialiasing-prop" translate="no">antialiasing</a></b> : bool</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#baselineOffset-prop" translate="no">baselineOffset</a></b> : int</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#children-prop" translate="no">children</a></b> : list&lt;Item&gt;</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#childrenRect-prop" translate="no">childrenRect</a></b><ul>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#childrenRect.height-prop" translate="no">childrenRect.height</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#childrenRect.width-prop" translate="no">childrenRect.width</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#childrenRect.x-prop" translate="no">childrenRect.x</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#childrenRect.y-prop" translate="no">childrenRect.y</a></b> : real</li>
+</ul>
+</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#clip-prop" translate="no">clip</a></b> : bool</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#containmentMask-prop" translate="no">containmentMask</a></b> : QObject*</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#data-prop" translate="no">data</a></b> : list&lt;QtObject&gt;</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#enabled-prop" translate="no">enabled</a></b> : bool</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#focus-prop" translate="no">focus</a></b> : bool</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#focusPolicy-prop" translate="no">focusPolicy</a></b> : enumeration <code class="summary extra" translate="no">(since 6.7)</code></li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#height-prop" translate="no">height</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#implicitHeight-prop" translate="no">implicitHeight</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#implicitWidth-prop" translate="no">implicitWidth</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#layer.effect-prop" translate="no">layer.effect</a></b> : Component</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#layer.enabled-prop" translate="no">layer.enabled</a></b> : bool</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#layer.format-prop" translate="no">layer.format</a></b> : enumeration</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#layer.live-prop" translate="no">layer.live</a></b> : bool <code class="summary extra" translate="no">(since 6.5)</code></li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#layer.mipmap-prop" translate="no">layer.mipmap</a></b> : bool</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#layer.samplerName-prop" translate="no">layer.samplerName</a></b> : string</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#layer.samples-prop" translate="no">layer.samples</a></b> : enumeration</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#layer.smooth-prop" translate="no">layer.smooth</a></b> : bool</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#layer.sourceRect-prop" translate="no">layer.sourceRect</a></b> : rect</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#layer.textureMirroring-prop" translate="no">layer.textureMirroring</a></b> : enumeration</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#layer.textureSize-prop" translate="no">layer.textureSize</a></b> : size</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#layer.wrapMode-prop" translate="no">layer.wrapMode</a></b> : enumeration</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#opacity-prop" translate="no">opacity</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#palette-prop" translate="no">palette</a></b> : Palette <code class="summary extra" translate="no">(since 6.0)</code></li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#parent-prop" translate="no">parent</a></b> : Item</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#resources-prop" translate="no">resources</a></b> : list&lt;QtObject&gt;</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#rotation-prop" translate="no">rotation</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#scale-prop" translate="no">scale</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#smooth-prop" translate="no">smooth</a></b> : bool</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#state-prop" translate="no">state</a></b> : string</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#states-prop" translate="no">states</a></b> : list&lt;State&gt;</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#transform-prop" translate="no">transform</a></b> : list&lt;Transform&gt;</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#transformOrigin-prop" translate="no">transformOrigin</a></b> : enumeration</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#transitions-prop" translate="no">transitions</a></b> : list&lt;Transition&gt;</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#visible-prop" translate="no">visible</a></b> : bool</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#visibleChildren-prop" translate="no">visibleChildren</a></b> : list&lt;Item&gt;</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#width-prop" translate="no">width</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#x-prop" translate="no">x</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#y-prop" translate="no">y</a></b> : real</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#z-prop" translate="no">z</a></b> : real</li>
+</ul>
+<h2 id="methods">Methods</h2>
+<ul>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#childAt-method" translate="no">childAt</a></b>(real <i>x</i>, real <i>y</i>)</li>
+<li class="fn" translate="no">bool <b><a href="qml-qtquick-item.html#contains-method" translate="no">contains</a></b>(point <i>point</i>)</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#dumpItemTree-method" translate="no">dumpItemTree</a></b>() <code class="summary extra" translate="no">(since 6.3)</code></li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#forceActiveFocus-method" translate="no">forceActiveFocus</a></b>()</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#forceActiveFocus-method-1" translate="no">forceActiveFocus</a></b>(Qt::FocusReason <i>reason</i>)</li>
+<li class="fn" translate="no">bool <b><a href="qml-qtquick-item.html#grabToImage-method" translate="no">grabToImage</a></b>(<i>callback</i>, <i>targetSize</i>)</li>
+<li class="fn" translate="no">point <b><a href="qml-qtquick-item.html#mapFromGlobal-method" translate="no">mapFromGlobal</a></b>(real <i>x</i>, real <i>y</i>)</li>
+<li class="fn" translate="no">point <b><a href="qml-qtquick-item.html#mapFromItem-method" translate="no">mapFromItem</a></b>(Item <i>item</i>, real <i>x</i>, real <i>y</i>)</li>
+<li class="fn" translate="no">point <b><a href="qml-qtquick-item.html#mapFromItem-method-1" translate="no">mapFromItem</a></b>(Item <i>item</i>, point <i>p</i>)</li>
+<li class="fn" translate="no">rect <b><a href="qml-qtquick-item.html#mapFromItem-method-2" translate="no">mapFromItem</a></b>(Item <i>item</i>, real <i>x</i>, real <i>y</i>, real <i>width</i>, real <i>height</i>)</li>
+<li class="fn" translate="no">rect <b><a href="qml-qtquick-item.html#mapFromItem-method-3" translate="no">mapFromItem</a></b>(Item <i>item</i>, rect <i>r</i>)</li>
+<li class="fn" translate="no">point <b><a href="qml-qtquick-item.html#mapToGlobal-method" translate="no">mapToGlobal</a></b>(real <i>x</i>, real <i>y</i>)</li>
+<li class="fn" translate="no">point <b><a href="qml-qtquick-item.html#mapToItem-method" translate="no">mapToItem</a></b>(Item <i>item</i>, real <i>x</i>, real <i>y</i>)</li>
+<li class="fn" translate="no">point <b><a href="qml-qtquick-item.html#mapToItem-method-1" translate="no">mapToItem</a></b>(Item <i>item</i>, point <i>p</i>)</li>
+<li class="fn" translate="no">rect <b><a href="qml-qtquick-item.html#mapToItem-method-2" translate="no">mapToItem</a></b>(Item <i>item</i>, real <i>x</i>, real <i>y</i>, real <i>width</i>, real <i>height</i>)</li>
+<li class="fn" translate="no">rect <b><a href="qml-qtquick-item.html#mapToItem-method-3" translate="no">mapToItem</a></b>(Item <i>item</i>, rect <i>r</i>)</li>
+<li class="fn" translate="no"><b><a href="qml-qtquick-item.html#nextItemInFocusChain-method" translate="no">nextItemInFocusChain</a></b>(bool <i>forward</i>)</li>
+</ul>
+<!-- $$$Item-description -->
+<h2 id="details">Detailed Description</h2>
+<p>The Item type is the base type for all visual items in Qt Quick.</p>
+<p>All visual items in Qt Quick inherit from Item. Although an Item object has no visual appearance, it defines all the attributes that are common across visual items, such as x and y position, width and height, <a href="qtquick-positioning-anchors.html" translate="no">anchoring</a> and key handling support.</p>
+<p>The Item type can be useful for grouping several items under a single root visual item. For example:</p>
+<pre class="qml" translate="no">
+ import QtQuick 2.0
+
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="type"><a href="qml-qtquick-image.html" translate="no">Image</a></span> {
+ <span class="name">source</span>: <span class="string">&quot;tile.png&quot;</span>
+ }
+ <span class="type"><a href="qml-qtquick-image.html" translate="no">Image</a></span> {
+ <span class="name">x</span>: <span class="number">80</span>
+ <span class="name">width</span>: <span class="number">100</span>
+ <span class="name">height</span>: <span class="number">100</span>
+ <span class="name">source</span>: <span class="string">&quot;tile.png&quot;</span>
+ }
+ <span class="type"><a href="qml-qtquick-image.html" translate="no">Image</a></span> {
+ <span class="name">x</span>: <span class="number">190</span>
+ <span class="name">width</span>: <span class="number">100</span>
+ <span class="name">height</span>: <span class="number">100</span>
+ <span class="name">fillMode</span>: <span class="name">Image</span>.<span class="name">Tile</span>
+ <span class="name">source</span>: <span class="string">&quot;tile.png&quot;</span>
+ }
+ }
+</pre>
+<h3 id="event-handling">Event Handling</h3>
+<p>All Item-based visual types can use <a href="qtquickhandlers-index.html" translate="no">Input Handlers</a> to handle incoming input events (subclasses of <a href="../qtgui/qinputevent.html" translate="no">QInputEvent</a>), such as mouse, touch and key events. This is the preferred declarative way to handle events.</p>
+<p>An alternative way to handle touch events is to subclass <a href="qquickitem.html" translate="no">QQuickItem</a>, call setAcceptTouchEvents() in the constructor, and override touchEvent(). <a href="../qtcore/qevent.html#accepted-prop" translate="no">Accept</a> the entire event to stop delivery to items underneath, and to exclusively grab for all the event's touch points. Use <a href="../qtgui/qpointerevent.html#setExclusiveGrabber" translate="no">QPointerEvent::setExclusiveGrabber</a>() to grab only certain touchpoints, and allow the event to be delivered further.</p>
+<p>Likewise, a <a href="qquickitem.html" translate="no">QQuickItem</a> subclass can call setAcceptedMouseButtons() to register to receive mouse button events, setAcceptHoverEvents() to receive hover events (mouse movements while no button is pressed), and override the virtual functions mousePressEvent(), mouseMoveEvent(), and mouseReleaseEvent(). Those can also accept the event to prevent further delivery and get an implicit grab at the same time; or explicitly <a href="../qtgui/qpointerevent.html#setExclusiveGrabber" translate="no">grab</a> the single <a href="../qtgui/qeventpoint.html" translate="no">QEventPoint</a> that the <a href="../qtgui/qmouseevent.html" translate="no">QMouseEvent</a> carries.</p>
+<p>Key handling is available to all Item-based visual types via the <a href="qml-qtquick-keys.html" translate="no">Keys</a> attached property. The <i>Keys</i> attached property provides basic signals such as <a href="qml-qtquick-keys.html#pressed-signal" translate="no">pressed</a> and <a href="qml-qtquick-keys.html#released-signal" translate="no">released</a>, as well as signals for specific keys, such as <a href="qml-qtquick-keys.html#spacePressed-signal" translate="no">spacePressed</a>. The example below assigns <a href="qtquick-input-focus.html" translate="no">keyboard focus</a> to the item and handles the left key via the general <code translate="no">onPressed</code> handler and the return key via the <code translate="no">onReturnPressed</code> handler:</p>
+<pre class="qml" translate="no">
+ import QtQuick 2.0
+
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="name">focus</span>: <span class="number">true</span>
+ <span class="name">Keys</span>.onPressed: (<span class="keyword"></span>event)=&gt; {
+ <span class="keyword">if</span> (<span class="name">event</span>.<span class="name">key</span> <span class="operator">==</span> <span class="name">Qt</span>.<span class="name">Key_Left</span>) {
+ <span class="name">console</span>.<span class="name">log</span>(<span class="string">&quot;move left&quot;</span>);
+ <span class="name">event</span>.<span class="name">accepted</span> <span class="operator">=</span> <span class="number">true</span>;
+ }
+ }
+ <span class="name">Keys</span>.onReturnPressed: <span class="name">console</span>.<span class="name">log</span>(<span class="string">&quot;Pressed return&quot;</span>);
+ }
+</pre>
+<p>See the <a href="qml-qtquick-keys.html" translate="no">Keys</a> attached property for detailed documentation.</p>
+<h3 id="layout-mirroring">Layout Mirroring</h3>
+<p>Item layouts can be mirrored using the <a href="qml-qtquick-layoutmirroring.html" translate="no">LayoutMirroring</a> attached property. This causes <a href="qml-qtquick-item.html#anchors.top-prop" translate="no">anchors</a> to be horizontally reversed, and also causes items that lay out or position their children (such as <a href="qml-qtquick-listview.html" translate="no">ListView</a> or <a href="qml-qtquick-row.html" translate="no">Row</a>) to horizontally reverse the direction of their layouts.</p>
+<p>See <a href="qml-qtquick-layoutmirroring.html" translate="no">LayoutMirroring</a> for more details.</p>
+<h2 id="item-layers">Item Layers</h2>
+<p>An Item will normally be rendered directly into the window it belongs to. However, by setting <a href="qml-qtquick-item.html#layer.enabled-prop" translate="no">layer.enabled</a>, it is possible to delegate the item and its entire subtree into an offscreen surface. Only the offscreen surface, a texture, will be then drawn into the window.</p>
+<p>If it is desired to have a texture size different from that of the item, this is possible using <a href="qml-qtquick-item.html#layer.textureSize-prop" translate="no">layer.textureSize</a>. To render only a section of the item into the texture, use <a href="qml-qtquick-item.html#layer.sourceRect-prop" translate="no">layer.sourceRect</a>. It is also possible to specify <a href="qml-qtquick-item.html#layer.sourceRect-prop" translate="no">layer.sourceRect</a> so it extends beyond the bounds of the item. In this case, the exterior will be padded with transparent pixels.</p>
+<p>The item will use linear interpolation for scaling if <a href="qml-qtquick-item.html#layer.smooth-prop" translate="no">layer.smooth</a> is set to <code translate="no">true</code> and will use mipmap for downsampling if <a href="qml-qtquick-item.html#layer.mipmap-prop" translate="no">layer.mipmap</a> is set to <code translate="no">true</code>. Mipmapping may improve visual quality of downscaled items. For mipmapping of single Image items, prefer <a href="qml-qtquick-image.html#mipmap-prop" translate="no">Image::mipmap</a>.</p>
+<h3 id="layer-opacity-vs-item-opacity">Layer Opacity vs Item Opacity</h3>
+<p>When applying <a href="qml-qtquick-item.html#opacity-prop" translate="no">opacity</a> to an item hierarchy the opacity is applied to each item individually. This can lead to undesired visual results when the opacity is applied to a subtree. Consider the following example:</p>
+<div class="table"><table class="generic">
+ <tr valign="top" class="odd"><td ><img src="images/qml-blending-nonlayered.png" alt="" /></td><td ><b>Non-layered Opacity</b><pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="name">id</span>: <span class="name">nonLayered</span>
+
+ <span class="name">opacity</span>: <span class="number">0.5</span>
+
+ <span class="name">width</span>: <span class="number">100</span>
+ <span class="name">height</span>: <span class="number">100</span>
+
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> { <span class="name">width</span>: <span class="number">80</span>; <span class="name">height</span>: <span class="number">80</span>; <span class="name">border</span>.width: <span class="number">1</span> }
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> { <span class="name">x</span>: <span class="number">20</span>; <span class="name">y</span>: <span class="number">20</span>; <span class="name">width</span>: <span class="number">80</span>; <span class="name">height</span>: <span class="number">80</span>; <span class="name">border</span>.width: <span class="number">1</span> }
+ }
+</pre>
+</td></tr>
+</table></div>
+<p>A layer is rendered with the root item's opacity being 1, and then the root item's opacity is applied to the texture when it is drawn. This means that fading in a large item hierarchy from transparent to opaque, or vice versa, can be done without the overlap artifacts that the normal item by item alpha blending has. Here is the same example with layer enabled:</p>
+<div class="table"><table class="generic">
+ <tr valign="top" class="odd"><td ><p class="centerAlign"><img src="images/qml-blending-layered.png" alt="" /></p></td><td ><b>Layered Opacity</b><pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="name">id</span>: <span class="name">layered</span>
+
+ <span class="name">opacity</span>: <span class="number">0.5</span>
+
+ <span class="name">layer</span>.enabled: <span class="number">true</span>
+
+ <span class="name">width</span>: <span class="number">100</span>
+ <span class="name">height</span>: <span class="number">100</span>
+
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> { <span class="name">width</span>: <span class="number">80</span>; <span class="name">height</span>: <span class="number">80</span>; <span class="name">border</span>.width: <span class="number">1</span> }
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> { <span class="name">x</span>: <span class="number">20</span>; <span class="name">y</span>: <span class="number">20</span>; <span class="name">width</span>: <span class="number">80</span>; <span class="name">height</span>: <span class="number">80</span>; <span class="name">border</span>.width: <span class="number">1</span> }
+ }
+</pre>
+</td></tr>
+</table></div>
+<h3 id="combined-with-shadereffects">Combined with ShaderEffects</h3>
+<p>Setting <a href="qml-qtquick-item.html#layer.enabled-prop" translate="no">layer.enabled</a> to true will turn the item into a <a href="qquickitem.html#isTextureProvider" translate="no">texture provider</a>, making it possible to use the item directly as a texture, for instance in combination with the <a href="qml-qtquick-shadereffect.html" translate="no">ShaderEffect</a> type.</p>
+<p>It is possible to apply an effect on a layer at runtime using layer.effect:</p>
+<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="name">id</span>: <span class="name">layerRoot</span>
+ <span class="name">layer</span>.enabled: <span class="number">true</span>
+ <span class="name">layer</span>.effect: <span class="name">ShaderEffect</span> {
+ <span class="name">fragmentShader</span>: <span class="string">&quot;effect.frag.qsb&quot;</span>
+ }
+ }
+</pre>
+<p>See <a href="qml-qtquick-shadereffect.html" translate="no">ShaderEffect</a> for more information about using effects.</p>
+<div class="admonition note">
+<p><b>Note: </b><a href="qml-qtquick-item.html#layer.enabled-prop" translate="no">layer.enabled</a> is actually just a more convenient way of using <a href="qml-qtquick-shadereffectsource.html" translate="no">ShaderEffectSource</a>.</p>
+</div>
+<h3 id="memory-and-performance">Memory and Performance</h3>
+<p>When an item's layer is enabled, the scene graph will allocate memory in the GPU equal to <code translate="no">width x height x 4</code>. In memory constrained configurations, large layers should be used with care.</p>
+<p>In the <a href="../qtgui/qpainter.html" translate="no">QPainter</a> / <a href="../qtwidgets/qwidget.html" translate="no">QWidget</a> world, it is sometimes favorable to cache complex content in a pixmap, image or texture. In Qt Quick, because of the techniques already applied by the <a href="qtquick-visualcanvas-scenegraph-renderer.html" translate="no">scene graph renderer</a>, this will in most cases not be the case. Excessive draw calls are already reduced because of batching and a cache will in most cases end up blending more pixels than the original content. The overhead of rendering to an offscreen and the blending involved with drawing the resulting texture is therefore often more costly than simply letting the item and its children be drawn normally.</p>
+<p>Also, an item using a layer can not be <a href="qtquick-visualcanvas-scenegraph-renderer.html#batching" translate="no">batched</a> during rendering. This means that a scene with many layered items may have performance problems.</p>
+<p>Layering can be convenient and useful for visual effects, but should in most cases be enabled for the duration of the effect and disabled afterwards.</p>
+<!-- @@@Item -->
+<h2>Property Documentation</h2>
+<!-- $$$ -->
+<div class="qmlitem"><div class="fngroup">
+<div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="children-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">children</span> : <span class="type"><a href="../qtqml/qml-list.html" translate="no">list</a></span>&lt;<span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span>&gt;</p></td></tr>
+<tr valign="top" class="odd" id="resources-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">resources</span> : <span class="type"><a href="../qtqml/qml-list.html" translate="no">list</a></span>&lt;<span class="type"><a href="../qtqml/qml-qtqml-qtobject.html" translate="no">QtObject</a></span>&gt;</p></td></tr>
+</table></div></div>
+</div><div class="qmldoc"><p>The children property contains the list of visual children of this item. The resources property contains non-visual resources that you want to reference by name.</p>
+<p>It is not generally necessary to refer to these properties when adding child items or resources, as the default <a href="qml-qtquick-item.html#data-prop" translate="no">data</a> property will automatically assign child objects to the <code translate="no">children</code> and <code translate="no">resources</code> properties as appropriate. See the <a href="qml-qtquick-item.html#data-prop" translate="no">data</a> documentation for details.</p>
+</div></div><!-- @@@ -->
+<br/>
+<!-- $$$ -->
+<div class="qmlitem"><div class="fngroup">
+<div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="height-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">height</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="width-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">width</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="x-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">x</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="y-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">y</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+</table></div></div>
+</div><div class="qmldoc"><p>Defines the item's position and size. The default value is <code translate="no">0</code>.</p>
+<p>The (x,y) position is relative to the <a href="qml-qtquick-item.html#parent-prop" translate="no">parent</a>.</p>
+<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> { <span class="name">x</span>: <span class="number">100</span>; <span class="name">y</span>: <span class="number">100</span>; <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span> }
+</pre>
+</div></div><!-- @@@ -->
+<br/>
+<!-- $$$ -->
+<div class="qmlitem"><div class="fngroup">
+<div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="implicitHeight-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">implicitHeight</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="implicitWidth-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">implicitWidth</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+</table></div></div>
+</div><div class="qmldoc"><p>Defines the preferred width or height of the Item.</p>
+<p>If <a href="qml-qtquick-item.html#width-prop" translate="no">width</a> or <a href="qml-qtquick-item.html#height-prop" translate="no">height</a> is not specified, an item's effective size will be determined by its <a href="qml-qtquick-item.html#implicitWidth-prop" translate="no">implicitWidth</a> or <a href="qml-qtquick-item.html#implicitHeight-prop" translate="no">implicitHeight</a>.</p>
+<p>However, if an item is the child of a <a href="qtquicklayouts-index.html" translate="no">layout</a>, the layout will determine the item's preferred size using its implicit size. In such a scenario, the explicit <a href="qml-qtquick-item.html#width-prop" translate="no">width</a> or <a href="qml-qtquick-item.html#height-prop" translate="no">height</a> will be ignored.</p>
+<p>The default implicit size for most items is 0x0, however some items have an inherent implicit size which cannot be overridden, for example, <a href="qml-qtquick-image.html" translate="no">Image</a> and <a href="qml-qtquick-text.html" translate="no">Text</a>.</p>
+<p>Setting the implicit size is useful for defining components that have a preferred size based on their content, for example:</p>
+<pre class="qml" translate="no">
+ <span class="comment">// Label.qml</span>
+ import QtQuick 2.0
+
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ property <span class="type">alias</span> <span class="name">icon</span>: <span class="name">image</span>.<span class="name">source</span>
+ property <span class="type">alias</span> <span class="name">label</span>: <span class="name">text</span>.<span class="name">text</span>
+ <span class="name">implicitWidth</span>: <span class="name">text</span>.<span class="name">implicitWidth</span> <span class="operator">+</span> <span class="name">image</span>.<span class="name">implicitWidth</span>
+ <span class="name">implicitHeight</span>: <span class="name">Math</span>.<span class="name">max</span>(<span class="name">text</span>.<span class="name">implicitHeight</span>, <span class="name">image</span>.<span class="name">implicitHeight</span>)
+ <span class="type"><a href="qml-qtquick-image.html" translate="no">Image</a></span> { <span class="name">id</span>: <span class="name">image</span> }
+ <span class="type"><a href="qml-qtquick-text.html" translate="no">Text</a></span> {
+ <span class="name">id</span>: <span class="name">text</span>
+ <span class="name">wrapMode</span>: <span class="name">Text</span>.<span class="name">Wrap</span>
+ <span class="name">anchors</span>.left: <span class="name">image</span>.<span class="name">right</span>; <span class="name">anchors</span>.right: <span class="name">parent</span>.<span class="name">right</span>
+ <span class="name">anchors</span>.verticalCenter: <span class="name">parent</span>.<span class="name">verticalCenter</span>
+ }
+ }
+</pre>
+<div class="admonition note">
+<p><b>Note: </b>Using <a href="qml-qtquick-item.html#implicitWidth-prop" translate="no">implicitWidth</a> of <a href="qml-qtquick-text.html" translate="no">Text</a> or <a href="qml-qtquick-textedit.html" translate="no">TextEdit</a> and setting the width explicitly incurs a performance penalty as the text must be laid out twice.</p>
+</div>
+</div></div><!-- @@@ -->
+<br/>
+<!-- $$$activeFocus -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="activeFocus-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">activeFocus</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span> <code class="details extra" translate="no">[read-only]</code></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This read-only property indicates whether the item has active focus.</p>
+<p>If activeFocus is true, either this item is the one that currently receives keyboard input, or it is a <a href="qml-qtquick-focusscope.html" translate="no">FocusScope</a> ancestor of the item that currently receives keyboard input.</p>
+<p>Usually, activeFocus is gained by setting <a href="qml-qtquick-item.html#focus-prop" translate="no">focus</a> on an item and its enclosing <a href="qml-qtquick-focusscope.html" translate="no">FocusScope</a> objects. In the following example, the <code translate="no">input</code> and <code translate="no">focusScope</code> objects will have active focus, while the root rectangle object will not.</p>
+<pre class="qml" translate="no">
+ import QtQuick 2.0
+
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+
+ <span class="type"><a href="qml-qtquick-focusscope.html" translate="no">FocusScope</a></span> {
+ <span class="name">id</span>: <span class="name">focusScope</span>
+ <span class="name">focus</span>: <span class="number">true</span>
+
+ <span class="type"><a href="qml-qtquick-textinput.html" translate="no">TextInput</a></span> {
+ <span class="name">id</span>: <span class="name">input</span>
+ <span class="name">focus</span>: <span class="number">true</span>
+ }
+ }
+ }
+</pre>
+<p><b>See also </b><a href="qml-qtquick-item.html#focus-prop" translate="no">focus</a> and <a href="qtquick-input-focus.html" translate="no">Keyboard Focus in Qt Quick</a>.</p>
+</div></div><!-- @@@activeFocus -->
+<br/>
+<!-- $$$activeFocusOnTab -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="activeFocusOnTab-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">activeFocusOnTab</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds whether the item wants to be in the tab focus chain. By default, this is set to <code translate="no">false</code>.</p>
+<p>The tab focus chain traverses elements by first visiting the parent, and then its children in the order they occur in the children property. Pressing the tab key on an item in the tab focus chain will move keyboard focus to the next item in the chain. Pressing BackTab (normally Shift+Tab) will move focus to the previous item.</p>
+<p>To set up a manual tab focus chain, see <a href="qml-qtquick-keynavigation.html" translate="no">KeyNavigation</a>. Tab key events used by Keys or <a href="qml-qtquick-keynavigation.html" translate="no">KeyNavigation</a> have precedence over focus chain behavior; ignore the events in other key handlers to allow it to propagate.</p>
+</div></div><!-- @@@activeFocusOnTab -->
+<br/>
+<!-- $$$anchors -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="even" id="anchors-prop"><th class="centerAlign"><p><b>anchors group</b></p></th></tr>
+<tr valign="top" class="odd" id="anchors.alignWhenCentered-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.alignWhenCentered</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.baseline-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.baseline</span> : <span class="type">AnchorLine</span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.baselineOffset-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.baselineOffset</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.bottom-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.bottom</span> : <span class="type">AnchorLine</span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.bottomMargin-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.bottomMargin</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.centerIn-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.centerIn</span> : <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.fill-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.fill</span> : <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.horizontalCenter-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.horizontalCenter</span> : <span class="type">AnchorLine</span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.horizontalCenterOffset-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.horizontalCenterOffset</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.left-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.left</span> : <span class="type">AnchorLine</span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.leftMargin-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.leftMargin</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.margins-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.margins</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.right-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.right</span> : <span class="type">AnchorLine</span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.rightMargin-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.rightMargin</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.top-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.top</span> : <span class="type">AnchorLine</span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.topMargin-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.topMargin</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.verticalCenter-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.verticalCenter</span> : <span class="type">AnchorLine</span></p></td></tr>
+<tr valign="top" class="odd" id="anchors.verticalCenterOffset-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">anchors.verticalCenterOffset</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Anchors provide a way to position an item by specifying its relationship with other items.</p>
+<p>Margins apply to top, bottom, left, right, and fill anchors. The <a href="qml-qtquick-item.html#anchors.margins-prop" translate="no">anchors.margins</a> property can be used to set all of the various margins at once, to the same value. It will not override a specific margin that has been previously set; to clear an explicit margin set its value to <code translate="no">undefined</code>. Note that margins are anchor-specific and are not applied if an item does not use anchors.</p>
+<p>Offsets apply for horizontal center, vertical center, and baseline anchors.</p>
+<div class="table"><table class="generic">
+ <tr valign="top" class="odd"><td ><p class="centerAlign"><img src="images/declarative-anchors_example.png" alt="" /></p></td><td >Text anchored to Image, horizontally centered and vertically below, with a margin.<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="type"><a href="qml-qtquick-image.html" translate="no">Image</a></span> {
+ <span class="name">id</span>: <span class="name">pic</span>
+ <span class="comment">// ...</span>
+ }
+ <span class="type"><a href="qml-qtquick-text.html" translate="no">Text</a></span> {
+ <span class="name">id</span>: <span class="name">label</span>
+ <span class="name">anchors</span>.horizontalCenter: <span class="name">pic</span>.<span class="name">horizontalCenter</span>
+ <span class="name">anchors</span>.top: <span class="name">pic</span>.<span class="name">bottom</span>
+ <span class="name">anchors</span>.topMargin: <span class="number">5</span>
+ <span class="comment">// ...</span>
+ }
+ }
+</pre>
+</td></tr>
+<tr valign="top" class="even"><td ><p class="centerAlign"><img src="images/declarative-anchors_example2.png" alt="" /></p></td><td >Left of Text anchored to right of Image, with a margin. The y property of both defaults to 0.<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="type"><a href="qml-qtquick-image.html" translate="no">Image</a></span> {
+ <span class="name">id</span>: <span class="name">pic</span>
+ <span class="comment">// ...</span>
+ }
+ <span class="type"><a href="qml-qtquick-text.html" translate="no">Text</a></span> {
+ <span class="name">id</span>: <span class="name">label</span>
+ <span class="name">anchors</span>.left: <span class="name">pic</span>.<span class="name">right</span>
+ <span class="name">anchors</span>.leftMargin: <span class="number">5</span>
+ <span class="comment">// ...</span>
+ }
+ }
+</pre>
+</td></tr>
+</table></div>
+<p><a href="qml-qtquick-item.html#anchors.fill-prop" translate="no">anchors.fill</a> provides a convenient way for one item to have the same geometry as another item, and is equivalent to connecting all four directional anchors.</p>
+<p>To clear an anchor value, set it to <code translate="no">undefined</code>.</p>
+<p><a href="qml-qtquick-item.html#anchors.alignWhenCentered-prop" translate="no">anchors.alignWhenCentered</a> (default <code translate="no">true</code>) forces centered anchors to align to a whole pixel; if the item being centered has an odd <a href="qml-qtquick-item.html#width-prop" translate="no">width</a> or <a href="qml-qtquick-item.html#height-prop" translate="no">height</a>, the item will be positioned on a whole pixel rather than being placed on a half-pixel. This ensures the item is painted crisply. There are cases where this is not desirable, for example when rotating the item jitters may be apparent as the center is rounded.</p>
+<div class="admonition note">
+<p><b>Note: </b>You can only anchor an item to siblings or a parent.</p>
+</div>
+<p>For more information see <a href="qtquick-positioning-anchors.html" translate="no">Anchor Layouts</a>.</p>
+</div></div><!-- @@@anchors -->
+<br/>
+<!-- $$$antialiasing -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="antialiasing-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">antialiasing</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Used by visual elements to decide if the item should use antialiasing or not. In some cases items with antialiasing require more memory and are potentially slower to render (see <a href="qtquick-visualcanvas-scenegraph-renderer.html#antialiasing" translate="no">Antialiasing</a> for more details).</p>
+<p>The default is false, but may be overridden by derived elements.</p>
+</div></div><!-- @@@antialiasing -->
+<br/>
+<!-- $$$baselineOffset -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="baselineOffset-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">baselineOffset</span> : <span class="type"><a href="../qtqml/qml-int.html" translate="no">int</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Specifies the position of the item's baseline in local coordinates.</p>
+<p>The baseline of a <a href="qml-qtquick-text.html" translate="no">Text</a> item is the imaginary line on which the text sits. Controls containing text usually set their baseline to the baseline of their text.</p>
+<p>For non-text items, a default baseline offset of 0 is used.</p>
+</div></div><!-- @@@baselineOffset -->
+<br/>
+<!-- $$$childrenRect -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="even" id="childrenRect-prop"><th class="centerAlign"><p><b>childrenRect group</b></p></th></tr>
+<tr valign="top" class="odd" id="childrenRect.height-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">childrenRect.height</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <code class="details extra" translate="no">[read-only]</code></p></td></tr>
+<tr valign="top" class="odd" id="childrenRect.width-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">childrenRect.width</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <code class="details extra" translate="no">[read-only]</code></p></td></tr>
+<tr valign="top" class="odd" id="childrenRect.x-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">childrenRect.x</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <code class="details extra" translate="no">[read-only]</code></p></td></tr>
+<tr valign="top" class="odd" id="childrenRect.y-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">childrenRect.y</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <code class="details extra" translate="no">[read-only]</code></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This read-only property holds the collective position and size of the item's children.</p>
+<p>This property is useful if you need to access the collective geometry of an item's children in order to correctly size the item.</p>
+<p>The geometry that is returned is local to the item. For example:</p>
+<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="name">x</span>: <span class="number">50</span>
+ <span class="name">y</span>: <span class="number">100</span>
+
+ <span class="comment">// prints: QRectF(-10, -20, 30, 40)</span>
+ <span class="name">Component</span>.onCompleted: <span class="name">print</span>(<span class="name">childrenRect</span>)
+
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="name">x</span>: -<span class="number">10</span>
+ <span class="name">y</span>: -<span class="number">20</span>
+ <span class="name">width</span>: <span class="number">30</span>
+ <span class="name">height</span>: <span class="number">40</span>
+ }
+ }
+</pre>
+</div></div><!-- @@@childrenRect -->
+<br/>
+<!-- $$$clip -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="clip-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">clip</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds whether clipping is enabled. The default clip value is <code translate="no">false</code>.</p>
+<p>If clipping is enabled, an item will clip its own painting, as well as the painting of its children, to its bounding rectangle.</p>
+<div class="admonition note">
+<p><b>Note: </b>Clipping can affect rendering performance. See <a href="qtquick-visualcanvas-scenegraph-renderer.html#clipping" translate="no">Clipping</a> for more information.</p>
+</div>
+</div></div><!-- @@@clip -->
+<br/>
+<!-- $$$containmentMask -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="containmentMask-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">containmentMask</span> : <span class="type">QObject</span>*</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds an optional mask for the Item to be used in the <a href="qml-qtquick-item.html#contains-method" translate="no">contains</a>() method. Its main use is currently to determine whether a <a href="../qtgui/qpointerevent.html" translate="no">pointer event</a> has landed into the item or not.</p>
+<p>By default the <code translate="no">contains()</code> method will return true for any point within the Item's bounding box. <code translate="no">containmentMask</code> allows for more fine-grained control. For example, if a custom C++ <a href="qquickitem.html" translate="no">QQuickItem</a> subclass with a specialized <a href="qml-qtquick-item.html#contains-method" translate="no">contains</a>() method is used as containmentMask:</p>
+<pre class="cpp" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> { <span class="name">id</span>: <span class="name">item</span>; <span class="name">containmentMask</span>: <span class="name">AnotherItem</span> { <span class="name">id</span>: <span class="name">anotherItem</span> } }
+</pre>
+<p><i>item</i>'s contains method would then return <code translate="no">true</code> only if <i>anotherItem</i>'s <a href="qml-qtquick-item.html#contains-method" translate="no">contains</a>() implementation returns <code translate="no">true</code>.</p>
+<p>A <a href="qml-qtquick-shapes-shape.html" translate="no">Shape</a> can be used as a mask, to make an item react to <a href="../qtgui/qpointerevent.html" translate="no">pointer events</a> only within a non-rectangular region:</p>
+<div class="table"><table class="generic">
+ <tr valign="top" class="odd"><td ><p class="centerAlign"><img src="images/containmentMask-shape.gif" alt="" /></p></td><td ><pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">width</span>: <span class="number">90</span>; <span class="name">height</span>: <span class="number">100</span>
+ <span class="name">color</span>: <span class="name">hoverHandler</span>.<span class="name">hovered</span> ? <span class="string">&quot;wheat&quot;</span> : <span class="string">&quot;lightgray&quot;</span>
+ <span class="name">containmentMask</span>: <span class="name">shape</span>
+
+ <span class="type"><a href="qml-qtquick-hoverhandler.html" translate="no">HoverHandler</a></span> { <span class="name">id</span>: <span class="name">hoverHandler</span> }
+
+ <span class="type"><a href="qml-qtquick-shapes-shape.html" translate="no">Shape</a></span> {
+ <span class="name">id</span>: <span class="name">shape</span>
+ <span class="name">containsMode</span>: <span class="name">Shape</span>.<span class="name">FillContains</span>
+
+ <span class="type"><a href="qml-qtquick-shapes-shapepath.html" translate="no">ShapePath</a></span> {
+ <span class="name">fillColor</span>: <span class="string">&quot;lightsteelblue&quot;</span>
+ <span class="name">startX</span>: <span class="number">10</span>; <span class="name">startY</span>: <span class="number">20</span>
+ <span class="type"><a href="qml-qtquick-patharc.html" translate="no">PathArc</a></span> {
+ <span class="name">x</span>: <span class="number">10</span>; <span class="name">y</span>: <span class="number">80</span>
+ <span class="name">radiusX</span>: <span class="number">40</span>; <span class="name">radiusY</span>: <span class="number">40</span>
+ <span class="name">useLargeArc</span>: <span class="number">true</span>
+ }
+ <span class="type"><a href="qml-qtquick-pathline.html" translate="no">PathLine</a></span> {
+ <span class="name">x</span>: <span class="number">10</span>; <span class="name">y</span>: <span class="number">20</span>
+ }
+ }
+ }
+ }
+</pre>
+</td></tr>
+</table></div>
+<p>It is also possible to define the contains method in QML. For example, to create a circular item that only responds to events within its actual bounds:</p>
+<div class="table"><table class="generic">
+ <tr valign="top" class="odd"><td ><p class="centerAlign"><img src="images/containmentMask-circle.gif" alt="" /></p></td><td ><pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">id</span>: <span class="name">circle</span>
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="name">width</span>
+ <span class="name">radius</span>: <span class="name">width</span> <span class="operator">/</span> <span class="number">2</span>
+ <span class="name">color</span>: <span class="name">tapHandler</span>.<span class="name">pressed</span> ? <span class="string">&quot;tomato&quot;</span> : <span class="name">hoverHandler</span>.<span class="name">hovered</span> ? <span class="string">&quot;darkgray&quot;</span> : <span class="string">&quot;lightgray&quot;</span>
+
+ <span class="type"><a href="qml-qtquick-taphandler.html" translate="no">TapHandler</a></span> { <span class="name">id</span>: <span class="name">tapHandler</span> }
+ <span class="type"><a href="qml-qtquick-hoverhandler.html" translate="no">HoverHandler</a></span> { <span class="name">id</span>: <span class="name">hoverHandler</span> }
+
+ <span class="name">containmentMask</span>: <span class="name">QtObject</span> {
+ property <span class="type">alias</span> <span class="name">radius</span>: <span class="name">circle</span>.<span class="name">radius</span>
+ <span class="keyword">function </span><span class="name">contains</span>(point: <span class="name">point</span>) : bool {
+ <span class="keyword">return</span> (<span class="name">Math</span>.<span class="name">pow</span>(<span class="name">point</span>.<span class="name">x</span> <span class="operator">-</span> <span class="name">radius</span>, <span class="number">2</span>) <span class="operator">+</span> <span class="name">Math</span>.<span class="name">pow</span>(<span class="name">point</span>.<span class="name">y</span> <span class="operator">-</span> <span class="name">radius</span>, <span class="number">2</span>)) <span class="operator">&lt;</span> <span class="name">Math</span>.<span class="name">pow</span>(<span class="name">radius</span>, <span class="number">2</span>)
+ }
+ }
+ }
+</pre>
+</td></tr>
+</table></div>
+<p><b>See also </b><a href="qtquick-shapes-example.html" translate="no">Qt Quick Examples - Shapes</a>.</p>
+</div></div><!-- @@@containmentMask -->
+<br/>
+<!-- $$$data -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="data-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">data</span> : <span class="type"><a href="../qtqml/qml-list.html" translate="no">list</a></span>&lt;<span class="type"><a href="../qtqml/qml-qtqml-qtobject.html" translate="no">QtObject</a></span>&gt; <code class="details extra" translate="no">[default]</code></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>The data property allows you to freely mix visual children and resources in an item. If you assign a visual item to the data list it becomes a child and if you assign any other object type, it is added as a resource.</p>
+<p>So you can write:</p>
+<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="type"><a href="qml-qtquick-text.html" translate="no">Text</a></span> {}
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {}
+ <span class="type"><a href="../qtqml/qml-qtqml-timer.html" translate="no">Timer</a></span> {}
+ }
+</pre>
+<p>instead of:</p>
+<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="name">children</span>: [
+ <span class="type"><a href="qml-qtquick-text.html" translate="no">Text</a></span> {},
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {}
+ ]
+ <span class="name">resources</span>: [
+ <span class="type"><a href="../qtqml/qml-qtqml-timer.html" translate="no">Timer</a></span> {}
+ ]
+ }
+</pre>
+<p>It should not generally be necessary to refer to the <code translate="no">data</code> property, as it is the default property for Item and thus all child items are automatically assigned to this property.</p>
+</div></div><!-- @@@data -->
+<br/>
+<!-- $$$enabled -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="enabled-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">enabled</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds whether the item receives mouse and keyboard events. By default this is true.</p>
+<p>Setting this property directly affects the <code translate="no">enabled</code> value of child items. When set to <code translate="no">false</code>, the <code translate="no">enabled</code> values of all child items also become <code translate="no">false</code>. When set to <code translate="no">true</code>, the <code translate="no">enabled</code> values of child items are returned to <code translate="no">true</code>, unless they have explicitly been set to <code translate="no">false</code>.</p>
+<p>Setting this property to <code translate="no">false</code> automatically causes <a href="qml-qtquick-item.html#activeFocus-prop" translate="no">activeFocus</a> to be set to <code translate="no">false</code>, and this item will no longer receive keyboard events.</p>
+<p><b>See also </b><a href="qml-qtquick-item.html#visible-prop" translate="no">visible</a>.</p>
+</div></div><!-- @@@enabled -->
+<br/>
+<!-- $$$focus -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="focus-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">focus</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds whether the item has focus within the enclosing <a href="qml-qtquick-focusscope.html" translate="no">FocusScope</a>. If true, this item will gain active focus when the enclosing <a href="qml-qtquick-focusscope.html" translate="no">FocusScope</a> gains active focus.</p>
+<p>In the following example, <code translate="no">input</code> will be given active focus when <code translate="no">scope</code> gains active focus:</p>
+<pre class="qml" translate="no">
+ import QtQuick 2.0
+
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+
+ <span class="type"><a href="qml-qtquick-focusscope.html" translate="no">FocusScope</a></span> {
+ <span class="name">id</span>: <span class="name">scope</span>
+
+ <span class="type"><a href="qml-qtquick-textinput.html" translate="no">TextInput</a></span> {
+ <span class="name">id</span>: <span class="name">input</span>
+ <span class="name">focus</span>: <span class="number">true</span>
+ }
+ }
+ }
+</pre>
+<p>For the purposes of this property, the scene as a whole is assumed to act like a focus scope. On a practical level, that means the following QML will give active focus to <code translate="no">input</code> on startup.</p>
+<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+
+ <span class="type"><a href="qml-qtquick-textinput.html" translate="no">TextInput</a></span> {
+ <span class="name">id</span>: <span class="name">input</span>
+ <span class="name">focus</span>: <span class="number">true</span>
+ }
+ }
+</pre>
+<p><b>See also </b><a href="qml-qtquick-item.html#activeFocus-prop" translate="no">activeFocus</a> and <a href="qtquick-input-focus.html" translate="no">Keyboard Focus in Qt Quick</a>.</p>
+</div></div><!-- @@@focus -->
+<br/>
+<!-- $$$focusPolicy -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="focusPolicy-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">focusPolicy</span> : <span class="type"><a href="../qtqml/qml-enumeration.html" translate="no">enumeration</a></span> <code class="details extra" translate="no">[since 6.7]</code></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property determines the way the item accepts focus.</p>
+<div class="table"><table class="valuelist"><tr valign="top" class="odd"><th class="tblConst">Constant</th><th class="tbldscr">Description</th></tr>
+<tr><td class="topAlign"><code translate="no">Qt.TabFocus</code></td><td class="topAlign">The item accepts focus by tabbing.</td></tr>
+<tr><td class="topAlign"><code translate="no">Qt.ClickFocus</code></td><td class="topAlign">The item accepts focus by clicking.</td></tr>
+<tr><td class="topAlign"><code translate="no">Qt.StrongFocus</code></td><td class="topAlign">The item accepts focus by both tabbing and clicking.</td></tr>
+<tr><td class="topAlign"><code translate="no">Qt.WheelFocus</code></td><td class="topAlign">The item accepts focus by tabbing, clicking, and using the mouse wheel.</td></tr>
+<tr><td class="topAlign"><code translate="no">Qt.NoFocus</code></td><td class="topAlign">The item does not accept focus.</td></tr>
+</table></div>
+<div class="admonition note">
+<p><b>Note: </b>This property was a member of Control until Qt 6.7.</p>
+</div>
+<p>This property was introduced in Qt 6.7.</p>
+</div></div><!-- @@@focusPolicy -->
+<br/>
+<!-- $$$layer.effect -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="layer.effect-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">layer.effect</span> : <span class="type">Component</span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Holds the effect that is applied to this layer.</p>
+<p>The effect is typically a <a href="qml-qtquick-shadereffect.html" translate="no">ShaderEffect</a> component, although any <a href="qml-qtquick-item.html" translate="no">Item</a> component can be assigned. The effect should have a source texture property with a name matching <a href="qml-qtquick-item.html#layer.samplerName-prop" translate="no">layer.samplerName</a>.</p>
+<p><b>See also </b><a href="qml-qtquick-item.html#layer.samplerName-prop" translate="no">layer.samplerName</a> and <a href="qml-qtquick-item.html#item-layers" translate="no">Item Layers</a>.</p>
+</div></div><!-- @@@layer.effect -->
+<br/>
+<!-- $$$layer.enabled -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="layer.enabled-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">layer.enabled</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Holds whether the item is layered or not. Layering is disabled by default.</p>
+<p>A layered item is rendered into an offscreen surface and cached until it is changed. Enabling layering for complex QML item hierarchies can sometimes be an optimization.</p>
+<p>None of the other layer properties have any effect when the layer is disabled.</p>
+<p><b>See also </b><a href="qml-qtquick-item.html#item-layers" translate="no">Item Layers</a>.</p>
+</div></div><!-- @@@layer.enabled -->
+<br/>
+<!-- $$$layer.format -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="layer.format-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">layer.format</span> : <span class="type"><a href="../qtqml/qml-enumeration.html" translate="no">enumeration</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property defines the format of the backing texture. Modifying this property makes most sense when the <i translate="no">layer.effect</i> is also specified.</p>
+<div class="table"><table class="valuelist"><tr valign="top" class="odd"><th class="tblConst">Constant</th><th class="tbldscr">Description</th></tr>
+<tr><td class="topAlign"><code translate="no">ShaderEffectSource.RGBA8</code></td><td class="topAlign">&nbsp;</td></tr>
+<tr><td class="topAlign"><code translate="no">ShaderEffectSource.RGBA16F</code></td><td class="topAlign">&nbsp;</td></tr>
+<tr><td class="topAlign"><code translate="no">ShaderEffectSource.RGBA32F</code></td><td class="topAlign">&nbsp;</td></tr>
+<tr><td class="topAlign"><code translate="no">ShaderEffectSource.Alpha</code></td><td class="topAlign">Starting with Qt 6.0, this value is not in use and has the same effect as <code translate="no">RGBA8</code> in practice.</td></tr>
+<tr><td class="topAlign"><code translate="no">ShaderEffectSource.RGB</code></td><td class="topAlign">Starting with Qt 6.0, this value is not in use and has the same effect as <code translate="no">RGBA8</code> in practice.</td></tr>
+<tr><td class="topAlign"><code translate="no">ShaderEffectSource.RGBA</code></td><td class="topAlign">Starting with Qt 6.0, this value is not in use and has the same effect as <code translate="no">RGBA8</code> in practice.</td></tr>
+</table></div>
+<p><b>See also </b><a href="qml-qtquick-item.html#item-layers" translate="no">Item Layers</a>.</p>
+</div></div><!-- @@@layer.format -->
+<br/>
+<!-- $$$layer.live -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="layer.live-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">layer.live</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span> <code class="details extra" translate="no">[since 6.5]</code></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>When this property is true the layer texture is updated whenever the item updates. Otherwise it will always be a frozen image.</p>
+<p>By default, this property is set to <code translate="no">true</code>.</p>
+<p>This property was introduced in Qt 6.5.</p>
+<p><b>See also </b><a href="qml-qtquick-item.html#item-layers" translate="no">Item Layers</a>.</p>
+</div></div><!-- @@@layer.live -->
+<br/>
+<!-- $$$layer.mipmap -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="layer.mipmap-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">layer.mipmap</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>If this property is true, mipmaps are generated for the texture.</p>
+<div class="admonition note">
+<p><b>Note: </b>Some OpenGL ES 2 implementations do not support mipmapping of non-power-of-two textures.</p>
+</div>
+<p><b>See also </b><a href="qml-qtquick-item.html#item-layers" translate="no">Item Layers</a>.</p>
+</div></div><!-- @@@layer.mipmap -->
+<br/>
+<!-- $$$layer.samplerName -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="layer.samplerName-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">layer.samplerName</span> : <span class="type"><a href="../qtqml/qml-string.html" translate="no">string</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Holds the name of the effect's source texture property.</p>
+<p>This value must match the name of the effect's source texture property so that the Item can pass the layer's offscreen surface to the effect correctly.</p>
+<p><b>See also </b><a href="qml-qtquick-item.html#layer.effect-prop" translate="no">layer.effect</a>, <a href="qml-qtquick-shadereffect.html" translate="no">ShaderEffect</a>, and <a href="qml-qtquick-item.html#item-layers" translate="no">Item Layers</a>.</p>
+</div></div><!-- @@@layer.samplerName -->
+<br/>
+<!-- $$$layer.samples -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="layer.samples-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">layer.samples</span> : <span class="type"><a href="../qtqml/qml-enumeration.html" translate="no">enumeration</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property allows requesting multisampled rendering in the layer.</p>
+<p>By default multisampling is enabled whenever multisampling is enabled for the entire window, assuming the scenegraph renderer in use and the underlying graphics API supports this.</p>
+<p>By setting the value to 2, 4, etc. multisampled rendering can be requested for a part of the scene without enabling multisampling for the entire scene. This way multisampling is applied only to a given subtree, which can lead to significant performance gains since multisampling is not applied to other parts of the scene.</p>
+<div class="admonition note">
+<p><b>Note: </b>Enabling multisampling can be potentially expensive regardless of the layer's size, as it incurs a hardware and driver dependent performance and memory cost.</p>
+</div>
+<div class="admonition note">
+<p><b>Note: </b>This property is only functional when support for multisample renderbuffers and framebuffer blits is available. Otherwise the value is silently ignored.</p>
+</div>
+</div></div><!-- @@@layer.samples -->
+<br/>
+<!-- $$$layer.smooth -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="layer.smooth-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">layer.smooth</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Holds whether the layer is smoothly transformed. When enabled, sampling the layer's texture is performed using <code translate="no">linear</code> interpolation, while non-smooth results in using the <code translate="no">nearest</code> filtering mode.</p>
+<p>By default, this property is set to <code translate="no">false</code>.</p>
+<p><b>See also </b><a href="qml-qtquick-item.html#item-layers" translate="no">Item Layers</a>.</p>
+</div></div><!-- @@@layer.smooth -->
+<br/>
+<!-- $$$layer.sourceRect -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="layer.sourceRect-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">layer.sourceRect</span> : <span class="type"><a href="../qtqml/qml-rect.html" translate="no">rect</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property defines the rectangular area of the item that should be rendered into the texture. The source rectangle can be larger than the item itself. If the rectangle is null, which is the default, then the whole item is rendered to the texture.</p>
+<p><b>See also </b><a href="qml-qtquick-item.html#item-layers" translate="no">Item Layers</a>.</p>
+</div></div><!-- @@@layer.sourceRect -->
+<br/>
+<!-- $$$layer.textureMirroring -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="layer.textureMirroring-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">layer.textureMirroring</span> : <span class="type"><a href="../qtqml/qml-enumeration.html" translate="no">enumeration</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property defines how the generated texture should be mirrored. The default value is <code translate="no">ShaderEffectSource.MirrorVertically</code>. Custom mirroring can be useful if the generated texture is directly accessed by custom shaders, such as those specified by <a href="qml-qtquick-shadereffect.html" translate="no">ShaderEffect</a>. If no effect is specified for the layered item, mirroring has no effect on the UI representation of the item.</p>
+<div class="table"><table class="valuelist"><tr valign="top" class="odd"><th class="tblConst">Constant</th><th class="tbldscr">Description</th></tr>
+<tr><td class="topAlign"><code translate="no">ShaderEffectSource.NoMirroring</code></td><td class="topAlign">No mirroring</td></tr>
+<tr><td class="topAlign"><code translate="no">ShaderEffectSource.MirrorHorizontally</code></td><td class="topAlign">The generated texture is flipped along X-axis.</td></tr>
+<tr><td class="topAlign"><code translate="no">ShaderEffectSource.MirrorVertically</code></td><td class="topAlign">The generated texture is flipped along Y-axis.</td></tr>
+</table></div>
+</div></div><!-- @@@layer.textureMirroring -->
+<br/>
+<!-- $$$layer.textureSize -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="layer.textureSize-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">layer.textureSize</span> : <span class="type"><a href="../qtqml/qml-size.html" translate="no">size</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the requested pixel size of the layers texture. If it is empty, which is the default, the size of the item is used.</p>
+<div class="admonition note">
+<p><b>Note: </b>Some platforms have a limit on how small framebuffer objects can be, which means the actual texture size might be larger than the requested size.</p>
+</div>
+<p><b>See also </b><a href="qml-qtquick-item.html#item-layers" translate="no">Item Layers</a>.</p>
+</div></div><!-- @@@layer.textureSize -->
+<br/>
+<!-- $$$layer.wrapMode -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="layer.wrapMode-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">layer.wrapMode</span> : <span class="type"><a href="../qtqml/qml-enumeration.html" translate="no">enumeration</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property defines the wrap modes associated with the texture. Modifying this property makes most sense when the <i translate="no">layer.effect</i> is specified.</p>
+<div class="table"><table class="valuelist"><tr valign="top" class="odd"><th class="tblConst">Constant</th><th class="tbldscr">Description</th></tr>
+<tr><td class="topAlign"><code translate="no">ShaderEffectSource.ClampToEdge</code></td><td class="topAlign">GL_CLAMP_TO_EDGE both horizontally and vertically</td></tr>
+<tr><td class="topAlign"><code translate="no">ShaderEffectSource.RepeatHorizontally</code></td><td class="topAlign">GL_REPEAT horizontally, GL_CLAMP_TO_EDGE vertically</td></tr>
+<tr><td class="topAlign"><code translate="no">ShaderEffectSource.RepeatVertically</code></td><td class="topAlign">GL_CLAMP_TO_EDGE horizontally, GL_REPEAT vertically</td></tr>
+<tr><td class="topAlign"><code translate="no">ShaderEffectSource.Repeat</code></td><td class="topAlign">GL_REPEAT both horizontally and vertically</td></tr>
+</table></div>
+<div class="admonition note">
+<p><b>Note: </b>Some OpenGL ES 2 implementations do not support the GL_REPEAT wrap mode with non-power-of-two textures.</p>
+</div>
+<p><b>See also </b><a href="qml-qtquick-item.html#item-layers" translate="no">Item Layers</a>.</p>
+</div></div><!-- @@@layer.wrapMode -->
+<br/>
+<!-- $$$opacity -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="opacity-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">opacity</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the opacity of the item. Opacity is specified as a number between 0.0 (fully transparent) and 1.0 (fully opaque). The default value is 1.0.</p>
+<p>When this property is set, the specified opacity is also applied individually to child items. This may have an unintended effect in some circumstances. For example in the second set of rectangles below, the red rectangle has specified an opacity of 0.5, which affects the opacity of its blue child rectangle even though the child has not specified an opacity.</p>
+<div class="table"><table class="generic">
+ <tr valign="top" class="odd"><td ><p class="centerAlign"><img src="images/declarative-item_opacity1.png" alt="" /></p></td><td ><pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;red&quot;</span>
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;blue&quot;</span>
+ <span class="name">x</span>: <span class="number">50</span>; <span class="name">y</span>: <span class="number">50</span>; <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ }
+ }
+ }
+</pre>
+</td></tr>
+<tr valign="top" class="even"><td ><p class="centerAlign"><img src="images/declarative-item_opacity2.png" alt="" /></p></td><td ><pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">opacity</span>: <span class="number">0.5</span>
+ <span class="name">color</span>: <span class="string">&quot;red&quot;</span>
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;blue&quot;</span>
+ <span class="name">x</span>: <span class="number">50</span>; <span class="name">y</span>: <span class="number">50</span>; <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ }
+ }
+ }
+</pre>
+</td></tr>
+</table></div>
+<p>Changing an item's opacity does not affect whether the item receives user input events. (In contrast, setting <a href="qml-qtquick-item.html#visible-prop" translate="no">visible</a> property to <code translate="no">false</code> stops mouse events, and setting the <a href="qml-qtquick-item.html#enabled-prop" translate="no">enabled</a> property to <code translate="no">false</code> stops mouse and keyboard events, and also removes active focus from the item.)</p>
+<p><b>See also </b><a href="qml-qtquick-item.html#visible-prop" translate="no">visible</a>.</p>
+</div></div><!-- @@@opacity -->
+<br/>
+<!-- $$$palette -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="palette-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">palette</span> : <span class="type"><a href="qml-qtquick-palette.html" translate="no">Palette</a></span> <code class="details extra" translate="no">[since 6.0]</code></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the palette currently set for the item.</p>
+<p>This property describes the item's requested palette. The palette is used by the item's style when rendering all controls, and is available as a means to ensure that custom controls can maintain consistency with the native platform's native look and feel. It's common that different platforms, or different styles, define different palettes for an application.</p>
+<p>The default palette depends on the system environment. <a href="../qtquickcontrols/qml-qtquick-controls-applicationwindow.html" translate="no">ApplicationWindow</a> maintains a system/theme palette which serves as a default for all controls. There may also be special palette defaults for certain types of controls. You can also set the default palette for controls by either:</p>
+<ul>
+<li>passing a custom palette to <a href="../qtgui/qguiapplication.html#setPalette" translate="no">QGuiApplication::setPalette</a>(), before loading any QML; or</li>
+<li>specifying the colors in the <a href="../qtquickcontrols/qtquickcontrols-configuration.html" translate="no">qtquickcontrols2.conf file</a>.</li>
+</ul>
+<p>Items propagate explicit palette properties from parents to children. If you change a specific property on a items's palette, that property propagates to all of the item's children, overriding any system defaults for that property.</p>
+<pre class="cpp" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="type">palette</span> {
+ <span class="name">buttonText</span>: <span class="string">&quot;maroon&quot;</span>
+ <span class="name">button</span>: <span class="string">&quot;lavender&quot;</span>
+ }
+
+ <span class="type"><a href="../qtquickcontrols/qml-qtquick-controls-button.html" translate="no">Button</a></span> {
+ <span class="name">text</span>: <span class="string">&quot;Click Me&quot;</span>
+ }
+ }
+</pre>
+<p>This property was introduced in Qt 6.0.</p>
+<p><b>See also </b><a href="qml-qtquick-window.html#palette-prop" translate="no">Window::palette</a>, <a href="../qtquickcontrols/qml-qtquick-controls-popup.html#palette-prop" translate="no">Popup::palette</a>, <a href="qml-qtquick-colorgroup.html" translate="no">ColorGroup</a>, <a href="qml-qtquick-palette.html" translate="no">Palette</a>, and <a href="qml-qtquick-systempalette.html" translate="no">SystemPalette</a>.</p>
+</div></div><!-- @@@palette -->
+<br/>
+<!-- $$$parent -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="parent-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">parent</span> : <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the visual parent of the item.</p>
+<div class="admonition note">
+<p><b>Note: </b>The concept of the <i>visual parent</i> differs from that of the <i><a href="../qtcore/qobject.html" translate="no">QObject</a> parent</i>. An item's visual parent may not necessarily be the same as its object parent. See <a href="qtquick-visualcanvas-visualparent.html" translate="no">Concepts - Visual Parent in Qt Quick</a> for more details.</p>
+</div>
+</div></div><!-- @@@parent -->
+<br/>
+<!-- $$$rotation -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="rotation-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">rotation</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the rotation of the item in degrees clockwise around its <a href="qml-qtquick-item.html#transformOrigin-prop" translate="no">transformOrigin</a>.</p>
+<p>The default value is 0 degrees (that is, no rotation).</p>
+<div class="table"><table class="generic">
+ <tr valign="top" class="odd"><td ><p class="centerAlign"><img src="images/declarative-rotation.png" alt="" /></p></td><td ><pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;blue&quot;</span>
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;red&quot;</span>
+ <span class="name">x</span>: <span class="number">25</span>; <span class="name">y</span>: <span class="number">25</span>; <span class="name">width</span>: <span class="number">50</span>; <span class="name">height</span>: <span class="number">50</span>
+ <span class="name">rotation</span>: <span class="number">30</span>
+ }
+ }
+</pre>
+</td></tr>
+</table></div>
+<p><b>See also </b><a href="qml-qtquick-transform.html" translate="no">Transform</a> and <a href="qml-qtquick-rotation.html" translate="no">Rotation</a>.</p>
+</div></div><!-- @@@rotation -->
+<br/>
+<!-- $$$scale -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="scale-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">scale</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the scale factor for this item.</p>
+<p>A scale of less than 1.0 causes the item to be rendered at a smaller size, and a scale greater than 1.0 renders the item at a larger size. A negative scale causes the item to be mirrored when rendered.</p>
+<p>The default value is 1.0.</p>
+<p>Scaling is applied from the <a href="qml-qtquick-item.html#transformOrigin-prop" translate="no">transformOrigin</a>.</p>
+<div class="table"><table class="generic">
+ <tr valign="top" class="odd"><td ><p class="centerAlign"><img src="images/declarative-scale.png" alt="" /></p></td><td ><pre class="qml" translate="no">
+ import QtQuick 2.0
+
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;blue&quot;</span>
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;green&quot;</span>
+ <span class="name">width</span>: <span class="number">25</span>; <span class="name">height</span>: <span class="number">25</span>
+ }
+
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;red&quot;</span>
+ <span class="name">x</span>: <span class="number">25</span>; <span class="name">y</span>: <span class="number">25</span>; <span class="name">width</span>: <span class="number">50</span>; <span class="name">height</span>: <span class="number">50</span>
+ <span class="name">scale</span>: <span class="number">1.4</span>
+ <span class="name">transformOrigin</span>: <span class="name">Item</span>.<span class="name">TopLeft</span>
+ }
+ }
+</pre>
+</td></tr>
+</table></div>
+<p><b>See also </b><a href="qml-qtquick-transform.html" translate="no">Transform</a> and <a href="qml-qtquick-scale.html" translate="no">Scale</a>.</p>
+</div></div><!-- @@@scale -->
+<br/>
+<!-- $$$smooth -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="smooth-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">smooth</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Primarily used in image based items to decide if the item should use smooth sampling or not. Smooth sampling is performed using linear interpolation, while non-smooth is performed using nearest neighbor.</p>
+<p>In Qt Quick 2.0, this property has minimal impact on performance.</p>
+<p>By default, this property is set to <code translate="no">true</code>.</p>
+</div></div><!-- @@@smooth -->
+<br/>
+<!-- $$$state -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="state-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">state</span> : <span class="type"><a href="../qtqml/qml-string.html" translate="no">string</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the name of the current state of the item.</p>
+<p>If the item is in its default state, that is, no explicit state has been set, then this property holds an empty string. Likewise, you can return an item to its default state by setting this property to an empty string.</p>
+<p><b>See also </b><a href="qtquick-statesanimations-states.html" translate="no">Qt Quick States</a>.</p>
+</div></div><!-- @@@state -->
+<br/>
+<!-- $$$states -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="states-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">states</span> : <span class="type"><a href="../qtqml/qml-list.html" translate="no">list</a></span>&lt;<span class="type"><a href="qml-qtquick-state.html" translate="no">State</a></span>&gt;</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the list of possible states for this item. To change the state of this item, set the <a href="qml-qtquick-item.html#state-prop" translate="no">state</a> property to one of these states, or set the <a href="qml-qtquick-item.html#state-prop" translate="no">state</a> property to an empty string to revert the item to its default state.</p>
+<p>This property is specified as a list of <a href="qml-qtquick-state.html" translate="no">State</a> objects. For example, below is an item with &quot;red_color&quot; and &quot;blue_color&quot; states:</p>
+<pre class="qml" translate="no">
+ import QtQuick 2.0
+
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">id</span>: <span class="name">root</span>
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+
+ <span class="name">states</span>: [
+ <span class="type"><a href="qml-qtquick-state.html" translate="no">State</a></span> {
+ <span class="name">name</span>: <span class="string">&quot;red_color&quot;</span>
+ <span class="type"><a href="qml-qtquick-propertychanges.html" translate="no">PropertyChanges</a></span> { <span class="name">root</span>.color: <span class="string">&quot;red&quot;</span> }
+ },
+ <span class="type"><a href="qml-qtquick-state.html" translate="no">State</a></span> {
+ <span class="name">name</span>: <span class="string">&quot;blue_color&quot;</span>
+ <span class="type"><a href="qml-qtquick-propertychanges.html" translate="no">PropertyChanges</a></span> { <span class="name">root</span>.color: <span class="string">&quot;blue&quot;</span> }
+ }
+ ]
+ }
+</pre>
+<p>See <a href="qtquick-statesanimations-states.html" translate="no">Qt Quick States</a> and <a href="qtquick-statesanimations-animations.html" translate="no">Animation and Transitions in Qt Quick</a> for more details on using states and transitions.</p>
+<p><b>See also </b><a href="qml-qtquick-item.html#transitions-prop" translate="no">transitions</a>.</p>
+</div></div><!-- @@@states -->
+<br/>
+<!-- $$$transform -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="transform-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">transform</span> : <span class="type"><a href="../qtqml/qml-list.html" translate="no">list</a></span>&lt;<span class="type"><a href="qml-qtquick-transform.html" translate="no">Transform</a></span>&gt; <code class="details extra" translate="no">[read-only]</code></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the list of transformations to apply.</p>
+<p>For more information see <a href="qml-qtquick-transform.html" translate="no">Transform</a>.</p>
+</div></div><!-- @@@transform -->
+<br/>
+<!-- $$$transformOrigin -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="transformOrigin-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">transformOrigin</span> : <span class="type"><a href="../qtqml/qml-enumeration.html" translate="no">enumeration</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the origin point around which scale and rotation transform.</p>
+<p>Nine transform origins are available, as shown in the image below. The default transform origin is <code translate="no">Item.Center</code>.</p>
+<p class="centerAlign"><img src="images/declarative-transformorigin.png" alt="" /></p><p>This example rotates an image around its bottom-right corner.</p>
+<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-image.html" translate="no">Image</a></span> {
+ <span class="name">source</span>: <span class="string">&quot;myimage.png&quot;</span>
+ <span class="name">transformOrigin</span>: <span class="name">Item</span>.<span class="name">BottomRight</span>
+ <span class="name">rotation</span>: <span class="number">45</span>
+ }
+</pre>
+<p>To set an arbitrary transform origin point use the <a href="qml-qtquick-scale.html" translate="no">Scale</a> or <a href="qml-qtquick-rotation.html" translate="no">Rotation</a> transform types with <a href="qml-qtquick-item.html#transform-prop" translate="no">transform</a>.</p>
+</div></div><!-- @@@transformOrigin -->
+<br/>
+<!-- $$$transitions -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="transitions-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">transitions</span> : <span class="type"><a href="../qtqml/qml-list.html" translate="no">list</a></span>&lt;<span class="type"><a href="qml-qtquick-transition.html" translate="no">Transition</a></span>&gt;</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the list of transitions for this item. These define the transitions to be applied to the item whenever it changes its <a href="qml-qtquick-item.html#state-prop" translate="no">state</a>.</p>
+<p>This property is specified as a list of <a href="qml-qtquick-transition.html" translate="no">Transition</a> objects. For example:</p>
+<pre class="qml" translate="no">
+ import QtQuick 2.0
+
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="name">transitions</span>: [
+ <span class="type"><a href="qml-qtquick-transition.html" translate="no">Transition</a></span> {
+ <span class="comment">//...</span>
+ },
+ <span class="type"><a href="qml-qtquick-transition.html" translate="no">Transition</a></span> {
+ <span class="comment">//...</span>
+ }
+ ]
+ }
+</pre>
+<p>See <a href="qtquick-statesanimations-states.html" translate="no">Qt Quick States</a> and <a href="qtquick-statesanimations-animations.html" translate="no">Animation and Transitions in Qt Quick</a> for more details on using states and transitions.</p>
+<p><b>See also </b><a href="qml-qtquick-item.html#states-prop" translate="no">states</a>.</p>
+</div></div><!-- @@@transitions -->
+<br/>
+<!-- $$$visible -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="visible-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">visible</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds whether the item is visible. By default this is true.</p>
+<p>Setting this property directly affects the <code translate="no">visible</code> value of child items. When set to <code translate="no">false</code>, the <code translate="no">visible</code> values of all child items also become <code translate="no">false</code>. When set to <code translate="no">true</code>, the <code translate="no">visible</code> values of child items are returned to <code translate="no">true</code>, unless they have explicitly been set to <code translate="no">false</code>.</p>
+<p>(Because of this flow-on behavior, using the <code translate="no">visible</code> property may not have the intended effect if a property binding should only respond to explicit property changes. In such cases it may be better to use the <a href="qml-qtquick-item.html#opacity-prop" translate="no">opacity</a> property instead.)</p>
+<p>If this property is set to <code translate="no">false</code>, the item will no longer receive mouse events, but will continue to receive key events and will retain the keyboard <a href="qml-qtquick-item.html#focus-prop" translate="no">focus</a> if it has been set. (In contrast, setting the <a href="qml-qtquick-item.html#enabled-prop" translate="no">enabled</a> property to <code translate="no">false</code> stops both mouse and keyboard events, and also removes focus from the item.)</p>
+<div class="admonition note">
+<p><b>Note: </b>This property's value is only affected by changes to this property or the parent's <code translate="no">visible</code> property. It does not change, for example, if this item moves off-screen, or if the <a href="qml-qtquick-item.html#opacity-prop" translate="no">opacity</a> changes to 0.</p>
+</div>
+<p><b>See also </b><a href="qml-qtquick-item.html#opacity-prop" translate="no">opacity</a> and <a href="qml-qtquick-item.html#enabled-prop" translate="no">enabled</a>.</p>
+</div></div><!-- @@@visible -->
+<br/>
+<!-- $$$visibleChildren -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="visibleChildren-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">visibleChildren</span> : <span class="type"><a href="../qtqml/qml-list.html" translate="no">list</a></span>&lt;<span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span>&gt;</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This read-only property lists all of the item's children that are currently visible. Note that a child's visibility may have changed explicitly, or because the visibility of this (it's parent) item or another grandparent changed.</p>
+</div></div><!-- @@@visibleChildren -->
+<br/>
+<!-- $$$z -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="z-prop">
+<td class="tblQmlPropNode"><p>
+<span class="name">z</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Sets the stacking order of sibling items. By default the stacking order is 0.</p>
+<p>Items with a higher stacking value are drawn on top of siblings with a lower stacking order. Items with the same stacking value are drawn bottom up in the order they appear. Items with a negative stacking value are drawn under their parent's content.</p>
+<p>The following example shows the various effects of stacking order.</p>
+<div class="table"><table class="generic">
+ <tr valign="top" class="odd"><td ><p class="centerAlign"><img src="images/declarative-item_stacking1.png" alt="" /></p></td><td >Same <code translate="no">z</code> - later children above earlier children:<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;red&quot;</span>
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ }
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;blue&quot;</span>
+ <span class="name">x</span>: <span class="number">50</span>; <span class="name">y</span>: <span class="number">50</span>; <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ }
+ }
+</pre>
+</td></tr>
+<tr valign="top" class="even"><td ><p class="centerAlign"><img src="images/declarative-item_stacking2.png" alt="" /></p></td><td >Higher <code translate="no">z</code> on top:<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">z</span>: <span class="number">1</span>
+ <span class="name">color</span>: <span class="string">&quot;red&quot;</span>
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ }
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;blue&quot;</span>
+ <span class="name">x</span>: <span class="number">50</span>; <span class="name">y</span>: <span class="number">50</span>; <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ }
+ }
+</pre>
+</td></tr>
+<tr valign="top" class="odd"><td ><p class="centerAlign"><img src="images/declarative-item_stacking3.png" alt="" /></p></td><td >Same <code translate="no">z</code> - children above parents:<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;red&quot;</span>
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;blue&quot;</span>
+ <span class="name">x</span>: <span class="number">50</span>; <span class="name">y</span>: <span class="number">50</span>; <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ }
+ }
+ }
+</pre>
+</td></tr>
+<tr valign="top" class="even"><td ><p class="centerAlign"><img src="images/declarative-item_stacking4.png" alt="" /></p></td><td >Lower <code translate="no">z</code> below:<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> {
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;red&quot;</span>
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">z</span>: -<span class="number">1</span>
+ <span class="name">color</span>: <span class="string">&quot;blue&quot;</span>
+ <span class="name">x</span>: <span class="number">50</span>; <span class="name">y</span>: <span class="number">50</span>; <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ }
+ }
+ }
+</pre>
+</td></tr>
+</table></div>
+</div></div><!-- @@@z -->
+<br/>
+<h2>Method Documentation</h2>
+<!-- $$$ -->
+<div class="qmlitem"><div class="fngroup">
+<div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="mapFromItem-method-1">
+<td class="tblQmlFuncNode"><p>
+<span class="type"><a href="../qtqml/qml-point.html" translate="no">point</a></span> <span class="name">mapFromItem</span>(<span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> <i>item</i>, <span class="type"><a href="../qtqml/qml-point.html" translate="no">point</a></span> <i>p</i>)</p></td></tr>
+<tr valign="top" class="odd" id="mapFromItem-method">
+<td class="tblQmlFuncNode"><p>
+<span class="type"><a href="../qtqml/qml-point.html" translate="no">point</a></span> <span class="name">mapFromItem</span>(<span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> <i>item</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>x</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>y</i>)</p></td></tr>
+<tr valign="top" class="odd" id="mapFromItem-method-2">
+<td class="tblQmlFuncNode"><p>
+<span class="type"><a href="../qtqml/qml-rect.html" translate="no">rect</a></span> <span class="name">mapFromItem</span>(<span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> <i>item</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>x</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>y</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>width</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>height</i>)</p></td></tr>
+<tr valign="top" class="odd" id="mapFromItem-method-3">
+<td class="tblQmlFuncNode"><p>
+<span class="type"><a href="../qtqml/qml-rect.html" translate="no">rect</a></span> <span class="name">mapFromItem</span>(<span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> <i>item</i>, <span class="type"><a href="../qtqml/qml-rect.html" translate="no">rect</a></span> <i>r</i>)</p></td></tr>
+</table></div></div>
+</div><div class="qmldoc"><p>Maps the point (<i translate="no">x</i>, <i translate="no">y</i>) or rect (<i translate="no">x</i>, <i translate="no">y</i>, <i translate="no">width</i>, <i translate="no">height</i>), which is in <i translate="no">item</i>'s coordinate system, to this item's coordinate system, and returns a <a href="../qtqml/qml-point.html" translate="no">point</a> or <a href="../qtqml/qml-rect.html" translate="no">rect</a> matching the mapped coordinate.</p>
+<p>The following properties of the item are used in the mapping: <a href="qml-qtquick-item.html#x-prop" translate="no">x</a>, <a href="qml-qtquick-item.html#y-prop" translate="no">y</a>, <a href="qml-qtquick-item.html#scale-prop" translate="no">scale</a>, <a href="qml-qtquick-item.html#rotation-prop" translate="no">rotation</a>, <a href="qml-qtquick-item.html#transformOrigin-prop" translate="no">transformOrigin</a>, and <a href="qml-qtquick-item.html#transform-prop" translate="no">transform</a>.</p>
+<p>If the items are part of different scenes, the mapping includes the relative position of the two scenes.</p>
+<p>If <i translate="no">item</i> is a <code translate="no">null</code> value, this maps the point or rect from the coordinate system of the <a href="qtquick-visualcanvas-coordinates.html#scene-coordinates" translate="no">scene</a>.</p>
+<p>The versions accepting point and rect are since Qt 5.15.</p>
+</div></div><!-- @@@ -->
+<br/>
+<!-- $$$ -->
+<div class="qmlitem"><div class="fngroup">
+<div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="mapToItem-method-1">
+<td class="tblQmlFuncNode"><p>
+<span class="type"><a href="../qtqml/qml-point.html" translate="no">point</a></span> <span class="name">mapToItem</span>(<span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> <i>item</i>, <span class="type"><a href="../qtqml/qml-point.html" translate="no">point</a></span> <i>p</i>)</p></td></tr>
+<tr valign="top" class="odd" id="mapToItem-method">
+<td class="tblQmlFuncNode"><p>
+<span class="type"><a href="../qtqml/qml-point.html" translate="no">point</a></span> <span class="name">mapToItem</span>(<span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> <i>item</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>x</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>y</i>)</p></td></tr>
+<tr valign="top" class="odd" id="mapToItem-method-2">
+<td class="tblQmlFuncNode"><p>
+<span class="type"><a href="../qtqml/qml-rect.html" translate="no">rect</a></span> <span class="name">mapToItem</span>(<span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> <i>item</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>x</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>y</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>width</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>height</i>)</p></td></tr>
+<tr valign="top" class="odd" id="mapToItem-method-3">
+<td class="tblQmlFuncNode"><p>
+<span class="type"><a href="../qtqml/qml-rect.html" translate="no">rect</a></span> <span class="name">mapToItem</span>(<span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span> <i>item</i>, <span class="type"><a href="../qtqml/qml-rect.html" translate="no">rect</a></span> <i>r</i>)</p></td></tr>
+</table></div></div>
+</div><div class="qmldoc"><p>Maps the point (<i translate="no">x</i>, <i translate="no">y</i>) or rect (<i translate="no">x</i>, <i translate="no">y</i>, <i translate="no">width</i>, <i translate="no">height</i>), which is in this item's coordinate system, to <i translate="no">item</i>'s coordinate system, and returns a <a href="../qtqml/qml-point.html" translate="no">point</a> or <a href="../qtqml/qml-rect.html" translate="no">rect</a> matching the mapped coordinate.</p>
+<p>The following properties of the item are used in the mapping: <a href="qml-qtquick-item.html#x-prop" translate="no">x</a>, <a href="qml-qtquick-item.html#y-prop" translate="no">y</a>, <a href="qml-qtquick-item.html#scale-prop" translate="no">scale</a>, <a href="qml-qtquick-item.html#rotation-prop" translate="no">rotation</a>, <a href="qml-qtquick-item.html#transformOrigin-prop" translate="no">transformOrigin</a>, and <a href="qml-qtquick-item.html#transform-prop" translate="no">transform</a>.</p>
+<p>If the items are part of different scenes, the mapping includes the relative position of the two scenes.</p>
+<p>If <i translate="no">item</i> is a <code translate="no">null</code> value, this maps the point or rect to the coordinate system of the <a href="qtquick-visualcanvas-coordinates.html#scene-coordinates" translate="no">scene</a>.</p>
+<p>The versions accepting point and rect are since Qt 5.15.</p>
+</div></div><!-- @@@ -->
+<br/>
+<!-- $$$childAt[overload1]$$$childAtrealreal -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="childAt-method">
+<td class="tblQmlFuncNode"><p>
+<span class="name">childAt</span>(<span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>x</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>y</i>)</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Returns the first visible child item found at point (<i translate="no">x</i>, <i translate="no">y</i>) within the coordinate system of this item.</p>
+<p>Returns <code translate="no">null</code> if there is no such item.</p>
+</div></div><!-- @@@childAt -->
+<br/>
+<!-- $$$contains[overload1]$$$containspoint -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="contains-method">
+<td class="tblQmlFuncNode"><p>
+<span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span> <span class="name">contains</span>(<span class="type"><a href="../qtqml/qml-point.html" translate="no">point</a></span> <i>point</i>)</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Returns <code translate="no">true</code> if this item contains <i translate="no">point</i>, which is in local coordinates; returns <code translate="no">false</code> otherwise. This is the same check that is used for hit-testing a <a href="../qtgui/qeventpoint.html" translate="no">QEventPoint</a> during event delivery, and is affected by <a href="qml-qtquick-item.html#containmentMask-prop" translate="no">containmentMask</a> if it is set.</p>
+</div></div><!-- @@@contains -->
+<br/>
+<!-- $$$dumpItemTree[overload1]$$$dumpItemTree -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="dumpItemTree-method">
+<td class="tblQmlFuncNode"><p>
+<code class="details extra" translate="no">[since 6.3]</code> <span class="name">dumpItemTree</span>()</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Dumps some details about the <a href="qtquick-visualcanvas-visualparent.html" translate="no">visual tree of Items</a> starting with this item and its children, recursively.</p>
+<p>The output looks similar to that of this QML code:</p>
+<pre class="qml" translate="no">
+ function dump(object, indent) {
+ console.log(indent + object)
+ for (const i in object.children)
+ dump(object.children[i], indent + &quot; &quot;)
+ }
+
+ dump(myItem, &quot;&quot;)
+</pre>
+<p>So if you want more details, you can implement your own function and add extra output to the console.log, such as values of specific properties.</p>
+<p>This method was introduced in Qt 6.3.</p>
+<p><b>See also </b><a href="../qtcore/qobject.html#dumpObjectTree" translate="no">QObject::dumpObjectTree</a>().</p>
+</div></div><!-- @@@dumpItemTree -->
+<br/>
+<!-- $$$forceActiveFocus[overload1]$$$forceActiveFocus -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="forceActiveFocus-method">
+<td class="tblQmlFuncNode"><p>
+<span class="name">forceActiveFocus</span>()</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Forces active focus on the item.</p>
+<p>This method sets focus on the item and ensures that all ancestor <a href="qml-qtquick-focusscope.html" translate="no">FocusScope</a> objects in the object hierarchy are also given <a href="qml-qtquick-item.html#focus-prop" translate="no">focus</a>.</p>
+<p>The reason for the focus change will be <a href="../qtcore/qt.html#FocusReason-enum" translate="no">Qt::OtherFocusReason</a>. Use the overloaded method to specify the focus reason to enable better handling of the focus change.</p>
+<p><b>See also </b><a href="qml-qtquick-item.html#activeFocus-prop" translate="no">activeFocus</a>.</p>
+</div></div><!-- @@@forceActiveFocus -->
+<br/>
+<!-- $$$forceActiveFocus$$$forceActiveFocusQt::FocusReason -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="forceActiveFocus-method-1">
+<td class="tblQmlFuncNode"><p>
+<span class="name">forceActiveFocus</span>(<span class="type">Qt::FocusReason</span> <i>reason</i>)</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This is an overloaded function.</p>
+<p>Forces active focus on the item with the given <i translate="no">reason</i>.</p>
+<p>This method sets focus on the item and ensures that all ancestor <a href="qml-qtquick-focusscope.html" translate="no">FocusScope</a> objects in the object hierarchy are also given <a href="qml-qtquick-item.html#focus-prop" translate="no">focus</a>.</p>
+<p><b>See also </b><a href="qml-qtquick-item.html#activeFocus-prop" translate="no">activeFocus</a> and <a href="../qtcore/qt.html#FocusReason-enum" translate="no">Qt::FocusReason</a>.</p>
+</div></div><!-- @@@forceActiveFocus -->
+<br/>
+<!-- $$$grabToImage[overload1]$$$grabToImage -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="grabToImage-method">
+<td class="tblQmlFuncNode"><p>
+<span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span> <span class="name">grabToImage</span>(<i>callback</i>, <i>targetSize</i>)</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Grabs the item into an in-memory image.</p>
+<p>The grab happens asynchronously and the JavaScript function <i translate="no">callback</i> is invoked when the grab is completed. The callback takes one argument, which is the result of the grab operation; an <a href="qml-qtquick-itemgrabresult.html" translate="no">ItemGrabResult</a> object.</p>
+<p>Use <i translate="no">targetSize</i> to specify the size of the target image. By default, the result will have the same size as the item.</p>
+<p>If the grab could not be initiated, the function returns <code translate="no">false</code>.</p>
+<p>The following snippet shows how to grab an item and store the results in a file:</p>
+<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">id</span>: <span class="name">sourceRectangle</span>
+ <span class="name">width</span>: <span class="number">100</span>
+ <span class="name">height</span>: <span class="number">100</span>
+ <span class="name">focus</span>: <span class="number">true</span>
+ <span class="name">gradient</span>: <span class="name">Gradient</span> {
+ <span class="type"><a href="qml-qtquick-gradientstop.html" translate="no">GradientStop</a></span> { <span class="name">position</span>: <span class="number">0</span>; <span class="name">color</span>: <span class="string">&quot;steelblue&quot;</span> }
+ <span class="type"><a href="qml-qtquick-gradientstop.html" translate="no">GradientStop</a></span> { <span class="name">position</span>: <span class="number">1</span>; <span class="name">color</span>: <span class="string">&quot;black&quot;</span> }
+ }
+
+ <span class="name">Keys</span>.onSpacePressed: {
+ <span class="name">sourceRectangle</span>.<span class="name">grabToImage</span>(<span class="keyword">function</span>(result) {
+ <span class="name">result</span>.<span class="name">saveToFile</span>(<span class="string">&quot;something.png&quot;</span>)
+ })
+ }
+ }
+</pre>
+<p>The following snippet shows how to grab an item and use the results in another image element:</p>
+<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-image.html" translate="no">Image</a></span> {
+ <span class="name">id</span>: <span class="name">image</span>
+ }
+
+ <span class="name">Keys</span>.onSpacePressed: {
+ <span class="name">sourceRectangle</span>.<span class="name">grabToImage</span>(<span class="keyword">function</span>(result) {
+ <span class="name">image</span>.<span class="name">source</span> <span class="operator">=</span> <span class="name">result</span>.<span class="name">url</span>
+ }, <span class="name">Qt</span>.<span class="name">size</span>(<span class="number">50</span>, <span class="number">50</span>))
+ }
+</pre>
+<div class="admonition note">
+<p><b>Note: </b>This function will render the item to an offscreen surface and copy that surface from the GPU's memory into the CPU's memory, which can be quite costly. For &quot;live&quot; preview, use <a href="qml-qtquick-item.html#layer.enabled-prop" translate="no">layers</a> or <a href="qml-qtquick-shadereffectsource.html" translate="no">ShaderEffectSource</a>.</p>
+</div>
+</div></div><!-- @@@grabToImage -->
+<br/>
+<!-- $$$mapFromGlobal[overload1]$$$mapFromGlobalrealreal -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="mapFromGlobal-method">
+<td class="tblQmlFuncNode"><p>
+<span class="type"><a href="../qtqml/qml-point.html" translate="no">point</a></span> <span class="name">mapFromGlobal</span>(<span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>x</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>y</i>)</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Maps the point (<i translate="no">x</i>, <i translate="no">y</i>), which is in the global coordinate system, to the item's coordinate system, and returns a <a href="../qtqml/qml-point.html" translate="no">point</a> matching the mapped coordinate.</p>
+<p>The following properties of the item are used in the mapping: <a href="qml-qtquick-item.html#x-prop" translate="no">x</a>, <a href="qml-qtquick-item.html#y-prop" translate="no">y</a>, <a href="qml-qtquick-item.html#scale-prop" translate="no">scale</a>, <a href="qml-qtquick-item.html#rotation-prop" translate="no">rotation</a>, <a href="qml-qtquick-item.html#transformOrigin-prop" translate="no">transformOrigin</a>, and <a href="qml-qtquick-item.html#transform-prop" translate="no">transform</a>.</p>
+<p>If the items are part of different scenes, the mapping includes the relative position of the two scenes.</p>
+</div></div><!-- @@@mapFromGlobal -->
+<br/>
+<!-- $$$mapToGlobal[overload1]$$$mapToGlobalrealreal -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="mapToGlobal-method">
+<td class="tblQmlFuncNode"><p>
+<span class="type"><a href="../qtqml/qml-point.html" translate="no">point</a></span> <span class="name">mapToGlobal</span>(<span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>x</i>, <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span> <i>y</i>)</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Maps the point (<i translate="no">x</i>, <i translate="no">y</i>), which is in this item's coordinate system, to the global coordinate system, and returns a <a href="../qtqml/qml-point.html" translate="no">point</a> matching the mapped coordinate.</p>
+<p>The following properties of the item are used in the mapping: <a href="qml-qtquick-item.html#x-prop" translate="no">x</a>, <a href="qml-qtquick-item.html#y-prop" translate="no">y</a>, <a href="qml-qtquick-item.html#scale-prop" translate="no">scale</a>, <a href="qml-qtquick-item.html#rotation-prop" translate="no">rotation</a>, <a href="qml-qtquick-item.html#transformOrigin-prop" translate="no">transformOrigin</a>, and <a href="qml-qtquick-item.html#transform-prop" translate="no">transform</a>.</p>
+<p>If the items are part of different scenes, the mapping includes the relative position of the two scenes.</p>
+</div></div><!-- @@@mapToGlobal -->
+<br/>
+<!-- $$$nextItemInFocusChain[overload1]$$$nextItemInFocusChainbool -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="nextItemInFocusChain-method">
+<td class="tblQmlFuncNode"><p>
+<span class="name">nextItemInFocusChain</span>(<span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span> <i>forward</i>)</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>Returns the item in the focus chain which is next to this item. If <i translate="no">forward</i> is <code translate="no">true</code>, or not supplied, it is the next item in the forwards direction. If <i translate="no">forward</i> is <code translate="no">false</code>, it is the next item in the backwards direction.</p>
+</div></div><!-- @@@nextItemInFocusChain -->
+<br/>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<div class="footer">
+ <p>
+ <acronym title="Copyright">&copy;</acronym> 2024 <span translate="no">The Qt Company Ltd.</span>
+ Documentation contributions included herein are the copyrights of
+ their respective owners.<br/> The documentation provided herein is licensed under the terms of the <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation License version 1.3</a> as published by the <span translate="no">Free Software Foundation</span>.<br/> <span translate="no">Qt</span> and respective logos are <a href="https://doc.qt.io/qt/trademarks.html"> trademarks</a> of <span translate="no">The Qt Company Ltd.</span> in Finland and/or other countries
+ worldwide. All other trademarks are property of their respective owners. </p>
+</div>
+</body>
+</html>
diff --git a/tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtquick-mousearea.html b/tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtquick-mousearea.html
new file mode 100644
index 0000000000..bbdd6345e8
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/qdochtmlparser/qml-qtquick-mousearea.html
@@ -0,0 +1,676 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+<!-- qquickmousearea.cpp -->
+ <title>MouseArea QML Type | Qt Quick 5.15.16</title>
+ <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
+ <script type="text/javascript">
+ document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
+ // loading style sheet breaks anchors that were jumped to before
+ // so force jumping to anchor again
+ setTimeout(function() {
+ var anchor = location.hash;
+ // need to jump to different anchor first (e.g. none)
+ location.hash = "#";
+ setTimeout(function() {
+ location.hash = anchor;
+ }, 0);
+ }, 0);
+ </script>
+</head>
+<body>
+<div class="header" id="qtdocheader">
+ <div class="main">
+ <div class="main-rounded">
+ <div class="navigationbar">
+ <ul>
+<li><a href="../qtdoc/index.html" translate="no">Qt 5.15</a></li>
+<li><a href="qtquick-index.html" translate="no">Qt Quick</a></li>
+<li><a href="qtquick-qmlmodule.html" translate="no">QML Types</a></li>
+<li>MouseArea QML Type</li>
+<li id="buildversion"><a href="qtquick-index.html" translate="no">Qt 5.15.16 Reference Documentation</a></li>
+ </ul>
+ </div>
+</div>
+<div class="content">
+<div class="line">
+<div class="content mainContent">
+<div class="sidebar">
+<div class="toc">
+<h3><a name="toc">Contents</a></h3>
+<ul>
+<li class="level1"><a href="#properties">Properties</a></li>
+<li class="level1"><a href="#signals">Signals</a></li>
+<li class="level1"><a href="#details">Detailed Description</a></li>
+<li class="level2"><a href="#example-usage">Example Usage</a></li>
+</ul>
+</div>
+<div class="sidebar-content" id="sidebar-content"></div></div>
+<h1 class="title" translate="no">MouseArea QML Type</h1>
+<span class="subtitle" translate="no"></span>
+<!-- $$$MouseArea-brief -->
+<p>Enables simple mouse handling. <a href="#details">More...</a></p>
+<!-- @@@MouseArea -->
+<div class="table"><table class="alignedsummary" translate="no">
+<tr><td class="memItemLeft rightAlign topAlign"> Import Statement:</td><td class="memItemRight bottomAlign"> import QtQuick 2.15</td></tr><tr><td class="memItemLeft rightAlign topAlign"> Inherits:</td><td class="memItemRight bottomAlign"> <p><a href="qml-qtquick-item.html" translate="no">Item</a></p>
+</td></tr></table></div><ul>
+<li><a href="qml-qtquick-mousearea-members.html">List of all members, including inherited members</a></li>
+</ul>
+<a name="properties"></a>
+<h2 id="properties">Properties</h2>
+<ul>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#acceptedButtons-prop" translate="no">acceptedButtons</a></b></b> : Qt::MouseButtons</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#containsMouse-prop" translate="no">containsMouse</a></b></b> : bool</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#containsPress-prop" translate="no">containsPress</a></b></b> : bool</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#cursorShape-prop" translate="no">cursorShape</a></b></b> : Qt::CursorShape</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#drag-prop" translate="no">drag</a></b></b><ul>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#drag.active-prop" translate="no">drag.active</a></b></b> : bool</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#drag.axis-prop" translate="no">drag.axis</a></b></b> : enumeration</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#drag.filterChildren-prop" translate="no">drag.filterChildren</a></b></b> : bool</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#drag.maximumX-prop" translate="no">drag.maximumX</a></b></b> : real</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#drag.maximumY-prop" translate="no">drag.maximumY</a></b></b> : real</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#drag.minimumX-prop" translate="no">drag.minimumX</a></b></b> : real</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#drag.minimumY-prop" translate="no">drag.minimumY</a></b></b> : real</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#drag.smoothed-prop" translate="no">drag.smoothed</a></b></b> : bool</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#drag.target-prop" translate="no">drag.target</a></b></b> : Item</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#drag.threshold-prop" translate="no">drag.threshold</a></b></b> : real</li>
+</ul>
+</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#enabled-prop" translate="no">enabled</a></b></b> : bool</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#hoverEnabled-prop" translate="no">hoverEnabled</a></b></b> : bool</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#mouseX-prop" translate="no">mouseX</a></b></b> : real</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#mouseY-prop" translate="no">mouseY</a></b></b> : real</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#pressAndHoldInterval-prop" translate="no">pressAndHoldInterval</a></b></b> : int</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#pressed-prop" translate="no">pressed</a></b></b> : bool</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#pressedButtons-prop" translate="no">pressedButtons</a></b></b> : MouseButtons</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#preventStealing-prop" translate="no">preventStealing</a></b></b> : bool</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#propagateComposedEvents-prop" translate="no">propagateComposedEvents</a></b></b> : bool</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#scrollGestureEnabled-prop" translate="no">scrollGestureEnabled</a></b></b> : bool</li>
+</ul>
+<a name="signals"></a>
+<h2 id="signals">Signals</h2>
+<ul>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#canceled-signal" translate="no">canceled</a></b></b>()</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#clicked-signal" translate="no">clicked</a></b></b>(MouseEvent <i>mouse</i>)</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#doubleClicked-signal" translate="no">doubleClicked</a></b></b>(MouseEvent <i>mouse</i>)</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#entered-signal" translate="no">entered</a></b></b>()</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#exited-signal" translate="no">exited</a></b></b>()</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#positionChanged-signal" translate="no">positionChanged</a></b></b>(MouseEvent <i>mouse</i>)</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#pressAndHold-signal" translate="no">pressAndHold</a></b></b>(MouseEvent <i>mouse</i>)</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#pressed-signal" translate="no">pressed</a></b></b>(MouseEvent <i>mouse</i>)</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#released-signal" translate="no">released</a></b></b>(MouseEvent <i>mouse</i>)</li>
+<li class="fn" translate="no"><b><b><a href="qml-qtquick-mousearea.html#wheel-signal" translate="no">wheel</a></b></b>(WheelEvent <i>wheel</i>)</li>
+</ul>
+<!-- $$$MouseArea-description -->
+<a name="details"></a>
+<h2 id="details">Detailed Description</h2>
+<p>A MouseArea is an invisible item that is typically used in conjunction with a visible item in order to provide mouse handling for that item. By effectively acting as a proxy, the logic for mouse handling can be contained within a MouseArea item.</p>
+<p>The <a href="qml-qtquick-mousearea.html#enabled-prop" translate="no">enabled</a> property is used to enable and disable mouse handling for the proxied item. When disabled, the mouse area becomes transparent to mouse events.</p>
+<p>MouseArea is an invisible Item, but it has a visible property. When set to false, the mouse area becomes transparent to mouse events.</p>
+<p>The <a href="qml-qtquick-mousearea.html#pressed-signal" translate="no">pressed</a> read-only property indicates whether or not the user is holding down a mouse button over the mouse area. This property is often used in bindings between properties in a user interface. The <a href="qml-qtquick-mousearea.html#containsMouse-prop" translate="no">containsMouse</a> read-only property indicates the presence of the mouse cursor over the mouse area but, by default, only when a mouse button is held down; see the <a href="qml-qtquick-mousearea.html#containsMouse-prop" translate="no">containsMouse</a> documentation for details.</p>
+<p>Information about the mouse position and button clicks are provided via signals for which event handler properties are defined. The most commonly used involved handling mouse presses and clicks: onClicked, onDoubleClicked, onPressed, onReleased and onPressAndHold. It's also possible to handle mouse wheel events via the onWheel signal.</p>
+<p>If a MouseArea overlaps with the area of other MouseArea items, you can choose to propagate <code translate="no">clicked</code>, <code translate="no">doubleClicked</code> and <code translate="no">pressAndHold</code> events to these other items by setting <a href="qml-qtquick-mousearea.html#propagateComposedEvents-prop" translate="no">propagateComposedEvents</a> to true and rejecting events that should be propagated. See the <a href="qml-qtquick-mousearea.html#propagateComposedEvents-prop" translate="no">propagateComposedEvents</a> documentation for details.</p>
+<p>By default, MouseArea items only report mouse clicks and not changes to the position of the mouse cursor. Setting the <a href="qml-qtquick-mousearea.html#hoverEnabled-prop" translate="no">hoverEnabled</a> property ensures that handlers defined for onPositionChanged, onEntered and onExited are used and that the <a href="qml-qtquick-mousearea.html#containsMouse-prop" translate="no">containsMouse</a> property is updated even when no mouse buttons are pressed.</p>
+<a name="example-usage"></a>
+<h2 id="example-usage">Example Usage</h2>
+<div class="float-right"><p><img src="images/qml-mousearea-snippet.png" alt="" /></p>
+</div><p>The following example uses a MouseArea in a <a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a> that changes the <a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a> color to red when clicked:</p>
+<pre class="qml" translate="no">
+ import QtQuick 2.0
+
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ <span class="name">color</span>: <span class="string">&quot;green&quot;</span>
+
+ <span class="type"><a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a></span> {
+ <span class="name">anchors</span>.fill: <span class="name">parent</span>
+ <span class="name">onClicked</span>: { <span class="name">parent</span>.<span class="name">color</span> <span class="operator">=</span> <span class="string">'red'</span> }
+ }
+ }
+</pre>
+<br style="clear: both" /><p>Many MouseArea signals pass a <a href="qml-qtquick-mouseevent.html" translate="no">mouse</a> parameter that contains additional information about the mouse event, such as the position, button, and any key modifiers.</p>
+<p>Here is an extension of the previous example that produces a different color when the area is right clicked:</p>
+<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ <span class="name">color</span>: <span class="string">&quot;green&quot;</span>
+
+ <span class="type"><a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a></span> {
+ <span class="name">anchors</span>.fill: <span class="name">parent</span>
+ <span class="name">acceptedButtons</span>: <span class="name">Qt</span>.<span class="name">LeftButton</span> <span class="operator">|</span> <span class="name">Qt</span>.<span class="name">RightButton</span>
+ <span class="name">onClicked</span>: {
+ <span class="keyword">if</span> (<span class="name">mouse</span>.<span class="name">button</span> <span class="operator">==</span> <span class="name">Qt</span>.<span class="name">RightButton</span>)
+ <span class="name">parent</span>.<span class="name">color</span> <span class="operator">=</span> <span class="string">'blue'</span>;
+ <span class="keyword">else</span>
+ <span class="name">parent</span>.<span class="name">color</span> <span class="operator">=</span> <span class="string">'red'</span>;
+ }
+ }
+ }
+</pre>
+<p><b>See also </b><a href="qml-qtquick-mouseevent.html" translate="no">MouseEvent</a>, <a href="qtquick-mousearea-example.html" translate="no">MouseArea example</a>, and <a href="qtquick-input-topic.html" translate="no">Important Concepts In Qt Quick - User Input</a>.</p>
+<!-- @@@MouseArea -->
+<h2>Property Documentation</h2>
+<!-- $$$ -->
+<div class="qmlitem"><div class="fngroup">
+<div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="mouseX-prop">
+<td class="tblQmlPropNode"><p>
+<a name="mouseX-prop"></a><span class="name">mouseX</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="mouseY-prop">
+<td class="tblQmlPropNode"><p>
+<a name="mouseY-prop"></a><span class="name">mouseY</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+</table></div></div>
+</div><div class="qmldoc"><p>These properties hold the coordinates of the mouse cursor.</p>
+<p>If the <a href="qml-qtquick-mousearea.html#hoverEnabled-prop" translate="no">hoverEnabled</a> property is false then these properties will only be valid while a button is pressed, and will remain valid as long as the button is held down even if the mouse is moved outside the area.</p>
+<p>By default, this property is false.</p>
+<p>If <a href="qml-qtquick-mousearea.html#hoverEnabled-prop" translate="no">hoverEnabled</a> is true then these properties will be valid when:</p>
+<ul>
+<li>no button is pressed, but the mouse is within the <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> (<a href="qml-qtquick-mousearea.html#containsMouse-prop" translate="no">containsMouse</a> is true).</li>
+<li>a button is pressed and held, even if it has since moved out of the area.</li>
+</ul>
+<p>The coordinates are relative to the <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a>.</p>
+</div></div><!-- @@@ -->
+<br/>
+<!-- $$$acceptedButtons -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="acceptedButtons-prop">
+<td class="tblQmlPropNode"><p>
+<a name="acceptedButtons-prop"></a><span class="name">acceptedButtons</span> : <span class="type">Qt::MouseButtons</span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the mouse buttons that the mouse area reacts to.</p>
+<p>To specify that the <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> will react to multiple buttons, <a href="../qtcore/qt.html#MouseButton-enum" translate="no">Qt::MouseButtons</a> flag values are combined using the &quot;|&quot; (or) operator:</p>
+<pre class="cpp" translate="no">
+ MouseArea { acceptedButtons: <span class="type"><a href="../qtqml/qml-qtqml-qt.html" translate="no">Qt</a></span><span class="operator">.</span>LeftButton <span class="operator">|</span> <span class="type"><a href="../qtqml/qml-qtqml-qt.html" translate="no">Qt</a></span><span class="operator">.</span>RightButton }
+</pre>
+<p>To indicate that all possible mouse buttons are to be accepted, the special value 'Qt.AllButtons' may be used:</p>
+<pre class="cpp" translate="no">
+ MouseArea { acceptedButtons: <span class="type"><a href="../qtqml/qml-qtqml-qt.html" translate="no">Qt</a></span><span class="operator">.</span>AllButtons }
+</pre>
+<p>The default value is <code translate="no">Qt.LeftButton</code>.</p>
+</div></div><!-- @@@acceptedButtons -->
+<br/>
+<!-- $$$containsMouse -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="containsMouse-prop">
+<td class="tblQmlPropNode"><p>
+<a name="containsMouse-prop"></a><span class="name">containsMouse</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds whether the mouse is currently inside the mouse area.</p>
+<div class="admonition warning">
+<p><b>Warning: </b>If <a href="qml-qtquick-mousearea.html#hoverEnabled-prop" translate="no">hoverEnabled</a> is false, containsMouse will only be valid when the mouse is pressed while the mouse cursor is inside the <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a>.</p>
+</div>
+</div></div><!-- @@@containsMouse -->
+<br/>
+<!-- $$$containsPress -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="containsPress-prop">
+<td class="tblQmlPropNode"><p>
+<a name="containsPress-prop"></a><span class="name">containsPress</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This is a convenience property equivalent to <code translate="no">pressed &amp;&amp; containsMouse</code>, i.e&#x2e; it holds whether any of the <a href="qml-qtquick-mousearea.html#acceptedButtons-prop" translate="no">acceptedButtons</a> are currently pressed and the mouse is currently within the <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a>.</p>
+<p>This property is particularly useful for highlighting an item while the mouse is pressed within its bounds.</p>
+<p>This property was introduced in Qt 5.4.</p>
+<p><b>See also </b><a href="qml-qtquick-mousearea.html#pressed-signal" translate="no">pressed</a> and <a href="qml-qtquick-mousearea.html#containsMouse-prop" translate="no">containsMouse</a>.</p>
+</div></div><!-- @@@containsPress -->
+<br/>
+<!-- $$$cursorShape -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="cursorShape-prop">
+<td class="tblQmlPropNode"><p>
+<a name="cursorShape-prop"></a><span class="name">cursorShape</span> : <span class="type">Qt::CursorShape</span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the cursor shape for this mouse area. Note that on platforms that do not display a mouse cursor this may have no effect.</p>
+<p>The available cursor shapes are:</p>
+<ul>
+<li>Qt.ArrowCursor</li>
+<li>Qt.UpArrowCursor</li>
+<li>Qt.CrossCursor</li>
+<li>Qt.WaitCursor</li>
+<li>Qt.IBeamCursor</li>
+<li>Qt.SizeVerCursor</li>
+<li>Qt.SizeHorCursor</li>
+<li>Qt.SizeBDiagCursor</li>
+<li>Qt.SizeFDiagCursor</li>
+<li>Qt.SizeAllCursor</li>
+<li>Qt.BlankCursor</li>
+<li>Qt.SplitVCursor</li>
+<li>Qt.SplitHCursor</li>
+<li>Qt.PointingHandCursor</li>
+<li>Qt.ForbiddenCursor</li>
+<li>Qt.WhatsThisCursor</li>
+<li>Qt.BusyCursor</li>
+<li>Qt.OpenHandCursor</li>
+<li>Qt.ClosedHandCursor</li>
+<li>Qt.DragCopyCursor</li>
+<li>Qt.DragMoveCursor</li>
+<li>Qt.DragLinkCursor</li>
+</ul>
+<p>In order to only set a mouse cursor shape for a region without reacting to mouse events set the <a href="qml-qtquick-mousearea.html#acceptedButtons-prop" translate="no">acceptedButtons</a> to none:</p>
+<pre class="cpp" translate="no">
+ MouseArea { cursorShape: <span class="type"><a href="../qtqml/qml-qtqml-qt.html" translate="no">Qt</a></span><span class="operator">.</span>IBeamCursor; acceptedButtons: <span class="type"><a href="../qtqml/qml-qtqml-qt.html" translate="no">Qt</a></span><span class="operator">.</span>NoButton }
+</pre>
+<p>The default value is <code translate="no">Qt.ArrowCursor</code>.</p>
+<p><b>See also </b><a href="../qtcore/qt.html#CursorShape-enum" translate="no">Qt::CursorShape</a>.</p>
+</div></div><!-- @@@cursorShape -->
+<br/>
+<!-- $$$drag -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="even" id="drag-prop"><th class="centerAlign"><p><a name="drag-prop"></a><b>drag group</b></p></th></tr>
+<tr valign="top" class="odd" id="drag.active-prop">
+<td class="tblQmlPropNode"><p>
+<a name="drag.active-prop"></a><span class="name">drag.active</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+<tr valign="top" class="odd" id="drag.axis-prop">
+<td class="tblQmlPropNode"><p>
+<a name="drag.axis-prop"></a><span class="name">drag.axis</span> : <span class="type"><a href="../qtqml/qml-enumeration.html" translate="no">enumeration</a></span></p></td></tr>
+<tr valign="top" class="odd" id="drag.filterChildren-prop">
+<td class="tblQmlPropNode"><p>
+<a name="drag.filterChildren-prop"></a><span class="name">drag.filterChildren</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+<tr valign="top" class="odd" id="drag.maximumX-prop">
+<td class="tblQmlPropNode"><p>
+<a name="drag.maximumX-prop"></a><span class="name">drag.maximumX</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="drag.maximumY-prop">
+<td class="tblQmlPropNode"><p>
+<a name="drag.maximumY-prop"></a><span class="name">drag.maximumY</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="drag.minimumX-prop">
+<td class="tblQmlPropNode"><p>
+<a name="drag.minimumX-prop"></a><span class="name">drag.minimumX</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="drag.minimumY-prop">
+<td class="tblQmlPropNode"><p>
+<a name="drag.minimumY-prop"></a><span class="name">drag.minimumY</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+<tr valign="top" class="odd" id="drag.smoothed-prop">
+<td class="tblQmlPropNode"><p>
+<a name="drag.smoothed-prop"></a><span class="name">drag.smoothed</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+<tr valign="top" class="odd" id="drag.target-prop">
+<td class="tblQmlPropNode"><p>
+<a name="drag.target-prop"></a><span class="name">drag.target</span> : <span class="type"><a href="qml-qtquick-item.html" translate="no">Item</a></span></p></td></tr>
+<tr valign="top" class="odd" id="drag.threshold-prop">
+<td class="tblQmlPropNode"><p>
+<a name="drag.threshold-prop"></a><span class="name">drag.threshold</span> : <span class="type"><a href="../qtqml/qml-real.html" translate="no">real</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p><code translate="no">drag</code> provides a convenient way to make an item draggable.</p>
+<ul>
+<li><code translate="no">drag.target</code> specifies the id of the item to drag.</li>
+<li><code translate="no">drag.active</code> specifies if the target item is currently being dragged.</li>
+<li><code translate="no">drag.axis</code> specifies whether dragging can be done horizontally (<code translate="no">Drag.XAxis</code>), vertically (<code translate="no">Drag.YAxis</code>), or both (<code translate="no">Drag.XAndYAxis</code>)</li>
+<li><code translate="no">drag.minimum</code> and <code translate="no">drag.maximum</code> limit how far the target can be dragged along the corresponding axes.</li>
+</ul>
+<p>The following example displays a <a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a> that can be dragged along the X-axis. The opacity of the rectangle is reduced when it is dragged to the right.</p>
+<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">id</span>: <span class="name">container</span>
+ <span class="name">width</span>: <span class="number">600</span>; <span class="name">height</span>: <span class="number">200</span>
+
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">id</span>: <span class="name">rect</span>
+ <span class="name">width</span>: <span class="number">50</span>; <span class="name">height</span>: <span class="number">50</span>
+ <span class="name">color</span>: <span class="string">&quot;red&quot;</span>
+ <span class="name">opacity</span>: (<span class="number">600.0</span> <span class="operator">-</span> <span class="name">rect</span>.<span class="name">x</span>) <span class="operator">/</span> <span class="number">600</span>
+
+ <span class="type"><a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a></span> {
+ <span class="name">anchors</span>.fill: <span class="name">parent</span>
+ <span class="name">drag</span>.target: <span class="name">rect</span>
+ <span class="name">drag</span>.axis: <span class="name">Drag</span>.<span class="name">XAxis</span>
+ <span class="name">drag</span>.minimumX: <span class="number">0</span>
+ <span class="name">drag</span>.maximumX: <span class="name">container</span>.<span class="name">width</span> <span class="operator">-</span> <span class="name">rect</span>.<span class="name">width</span>
+ }
+ }
+ }
+</pre>
+<div class="admonition note">
+<p><b>Note: </b>Items cannot be dragged if they are anchored for the requested <code translate="no">drag.axis</code>. For example, if <code translate="no">anchors.left</code> or <code translate="no">anchors.right</code> was set for <code translate="no">rect</code> in the above example, it cannot be dragged along the X-axis. This can be avoided by settng the anchor value to <code translate="no">undefined</code> in an <a href="qml-qtquick-mousearea.html#pressed-signal" translate="no">onPressed</a> handler.</p>
+</div>
+<p>If <code translate="no">drag.filterChildren</code> is set to true, a drag can override descendant MouseAreas. This enables a parent <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> to handle drags, for example, while descendants handle clicks:</p>
+<p><code translate="no">drag.threshold</code> determines the threshold in pixels of when the drag operation should start. By default this is bound to a platform dependent value. This property was added in Qt Quick 2.2&#x2e;</p>
+<p>If <code translate="no">drag.smoothed</code> is <code translate="no">true</code>, the target will be moved only after the drag operation has started. If set to <code translate="no">false</code>, the target will be moved straight to the current mouse position. By default, this property is <code translate="no">true</code>. This property was added in Qt Quick 2.4</p>
+<p>See the <a href="qml-qtquick-drag.html" translate="no">Drag</a> attached property and <a href="qml-qtquick-droparea.html" translate="no">DropArea</a> if you want to make a drop.</p>
+<pre class="qml" translate="no">
+ import QtQuick 2.0
+
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">width</span>: <span class="number">480</span>
+ <span class="name">height</span>: <span class="number">320</span>
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">x</span>: <span class="number">30</span>; <span class="name">y</span>: <span class="number">30</span>
+ <span class="name">width</span>: <span class="number">300</span>; <span class="name">height</span>: <span class="number">240</span>
+ <span class="name">color</span>: <span class="string">&quot;lightsteelblue&quot;</span>
+
+ <span class="type"><a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a></span> {
+ <span class="name">anchors</span>.fill: <span class="name">parent</span>
+ <span class="name">drag</span>.target: <span class="name">parent</span>;
+ <span class="name">drag</span>.axis: <span class="string">&quot;XAxis&quot;</span>
+ <span class="name">drag</span>.minimumX: <span class="number">30</span>
+ <span class="name">drag</span>.maximumX: <span class="number">150</span>
+ <span class="name">drag</span>.filterChildren: <span class="number">true</span>
+
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;yellow&quot;</span>
+ <span class="name">x</span>: <span class="number">50</span>; <span class="name">y</span> : <span class="number">50</span>
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ <span class="type"><a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a></span> {
+ <span class="name">anchors</span>.fill: <span class="name">parent</span>
+ <span class="name">onClicked</span>: <span class="name">console</span>.<span class="name">log</span>(<span class="string">&quot;Clicked&quot;</span>)
+ }
+ }
+ }
+ }
+ }
+</pre>
+</div></div><!-- @@@drag -->
+<br/>
+<!-- $$$enabled -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="enabled-prop">
+<td class="tblQmlPropNode"><p>
+<a name="enabled-prop"></a><span class="name">enabled</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds whether the item accepts mouse events.</p>
+<div class="admonition note">
+<p><b>Note: </b>Due to historical reasons, this property is not equivalent to Item.enabled. It only affects mouse events, and its effect does not propagate to child items.</p>
+</div>
+<p>By default, this property is true.</p>
+</div></div><!-- @@@enabled -->
+<br/>
+<!-- $$$hoverEnabled -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="hoverEnabled-prop">
+<td class="tblQmlPropNode"><p>
+<a name="hoverEnabled-prop"></a><span class="name">hoverEnabled</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds whether hover events are handled.</p>
+<p>By default, mouse events are only handled in response to a button event, or when a button is pressed. Hover enables handling of all mouse events even when no mouse button is pressed.</p>
+<p>This property affects the <a href="qml-qtquick-mousearea.html#containsMouse-prop" translate="no">containsMouse</a> property and the onEntered, onExited and onPositionChanged signals.</p>
+</div></div><!-- @@@hoverEnabled -->
+<br/>
+<!-- $$$pressAndHoldInterval -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="pressAndHoldInterval-prop">
+<td class="tblQmlPropNode"><p>
+<a name="pressAndHoldInterval-prop"></a><span class="name">pressAndHoldInterval</span> : <span class="type"><a href="../qtqml/qml-int.html" translate="no">int</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property overrides the elapsed time in milliseconds before <code translate="no">pressAndHold</code> is emitted.</p>
+<p>If not explicitly set -- or after reset -- the value follows <code translate="no">QStyleHints::mousePressAndHoldInterval</code>.</p>
+<p>Typically it's sufficient to set this property globally using the application style hint. This property should be used when varying intervals are needed for certain MouseAreas.</p>
+<p>This property was introduced in Qt 5.9.</p>
+<p><b>See also </b><a href="qml-qtquick-mousearea.html#pressAndHold-signal" translate="no">pressAndHold</a>.</p>
+</div></div><!-- @@@pressAndHoldInterval -->
+<br/>
+<!-- $$$pressed -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="pressed-prop">
+<td class="tblQmlPropNode"><p>
+<a name="pressed-prop"></a><span class="name">pressed</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds whether any of the <a href="qml-qtquick-mousearea.html#acceptedButtons-prop" translate="no">acceptedButtons</a> are currently pressed.</p>
+</div></div><!-- @@@pressed -->
+<br/>
+<!-- $$$pressedButtons -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="pressedButtons-prop">
+<td class="tblQmlPropNode"><p>
+<a name="pressedButtons-prop"></a><span class="name">pressedButtons</span> : <span class="type">MouseButtons</span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds the mouse buttons currently pressed.</p>
+<p>It contains a bitwise combination of:</p>
+<ul>
+<li>Qt.LeftButton</li>
+<li>Qt.RightButton</li>
+<li>Qt.MiddleButton</li>
+</ul>
+<p>The code below displays &quot;right&quot; when the right mouse buttons is pressed:</p>
+<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-text.html" translate="no">Text</a></span> {
+ <span class="name">text</span>: <span class="name">mouseArea</span>.<span class="name">pressedButtons</span> <span class="operator">&amp;</span> <span class="name">Qt</span>.<span class="name">RightButton</span> ? <span class="string">&quot;right&quot;</span> : <span class="string">&quot;&quot;</span>
+ <span class="name">horizontalAlignment</span>: <span class="name">Text</span>.<span class="name">AlignHCenter</span>
+ <span class="name">verticalAlignment</span>: <span class="name">Text</span>.<span class="name">AlignVCenter</span>
+
+ <span class="type"><a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a></span> {
+ <span class="name">id</span>: <span class="name">mouseArea</span>
+ <span class="name">anchors</span>.fill: <span class="name">parent</span>
+ <span class="name">acceptedButtons</span>: <span class="name">Qt</span>.<span class="name">LeftButton</span> <span class="operator">|</span> <span class="name">Qt</span>.<span class="name">RightButton</span>
+ }
+ }
+</pre>
+<div class="admonition note">
+<p><b>Note: </b>this property only handles buttons specified in <a href="qml-qtquick-mousearea.html#acceptedButtons-prop" translate="no">acceptedButtons</a>.</p>
+</div>
+<p><b>See also </b><a href="qml-qtquick-mousearea.html#acceptedButtons-prop" translate="no">acceptedButtons</a>.</p>
+</div></div><!-- @@@pressedButtons -->
+<br/>
+<!-- $$$preventStealing -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="preventStealing-prop">
+<td class="tblQmlPropNode"><p>
+<a name="preventStealing-prop"></a><span class="name">preventStealing</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds whether the mouse events may be stolen from this <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a>.</p>
+<p>If a <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> is placed within an item that filters child mouse events, such as Flickable, the mouse events may be stolen from the <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> if a gesture is recognized by the parent item, e.g&#x2e; a flick gesture. If preventStealing is set to true, no item will steal the mouse events.</p>
+<p>Note that setting preventStealing to true once an item has started stealing events will have no effect until the next press event.</p>
+<p>By default this property is false.</p>
+</div></div><!-- @@@preventStealing -->
+<br/>
+<!-- $$$propagateComposedEvents -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="propagateComposedEvents-prop">
+<td class="tblQmlPropNode"><p>
+<a name="propagateComposedEvents-prop"></a><span class="name">propagateComposedEvents</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property holds whether composed mouse events will automatically propagate to other MouseAreas that overlap with this <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> but are lower in the visual stacking order. By default, this property is false.</p>
+<p><a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> contains several composed events: <code translate="no">clicked</code>, <code translate="no">doubleClicked</code> and <code translate="no">pressAndHold</code>. These are composed of basic mouse events, like <code translate="no">pressed</code>, and can be propagated differently in comparison to basic events.</p>
+<p>If propagateComposedEvents is set to true, then composed events will be automatically propagated to other MouseAreas in the same location in the scene. Each event is propagated to the next <a href="qml-qtquick-mousearea.html#enabled-prop" translate="no">enabled</a> <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> beneath it in the stacking order, propagating down this visual hierarchy until a <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> accepts the event. Unlike <code translate="no">pressed</code> events, composed events will not be automatically accepted if no handler is present.</p>
+<p>For example, below is a yellow <a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a> that contains a blue <a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a>. The blue rectangle is the top-most item in the hierarchy of the visual stacking order; it will visually rendered above the yellow rectangle. Since the blue rectangle sets propagateComposedEvents to true, and also sets <a href="qml-qtquick-mouseevent.html#accepted-prop" translate="no">MouseEvent::accepted</a> to false for all received <code translate="no">clicked</code> events, any <code translate="no">clicked</code> events it receives are propagated to the <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> of the yellow rectangle beneath it.</p>
+<pre class="qml" translate="no">
+ import QtQuick 2.0
+
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;yellow&quot;</span>
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+
+ <span class="type"><a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a></span> {
+ <span class="name">anchors</span>.fill: <span class="name">parent</span>
+ <span class="name">onClicked</span>: <span class="name">console</span>.<span class="name">log</span>(<span class="string">&quot;clicked yellow&quot;</span>)
+ }
+
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">color</span>: <span class="string">&quot;blue&quot;</span>
+ <span class="name">width</span>: <span class="number">50</span>; <span class="name">height</span>: <span class="number">50</span>
+
+ <span class="type"><a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a></span> {
+ <span class="name">anchors</span>.fill: <span class="name">parent</span>
+ <span class="name">propagateComposedEvents</span>: <span class="number">true</span>
+ <span class="name">onClicked</span>: {
+ <span class="name">console</span>.<span class="name">log</span>(<span class="string">&quot;clicked blue&quot;</span>)
+ <span class="name">mouse</span>.<span class="name">accepted</span> <span class="operator">=</span> <span class="number">false</span>
+ }
+ }
+ }
+ }
+</pre>
+<p>Clicking on the blue rectangle will cause the <code translate="no">onClicked</code> handler of its child <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> to be invoked; the event will then be propagated to the <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> of the yellow rectangle, causing its own <code translate="no">onClicked</code> handler to be invoked.</p>
+<p>This property greatly simplifies the usecase of when you want to have overlapping MouseAreas handling the composed events together. For example: if you want one <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> to handle <code translate="no">clicked</code> signals and the other to handle <code translate="no">pressAndHold</code>, or if you want one <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> to handle <code translate="no">clicked</code> most of the time, but pass it through when certain conditions are met.</p>
+</div></div><!-- @@@propagateComposedEvents -->
+<br/>
+<!-- $$$scrollGestureEnabled -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="scrollGestureEnabled-prop">
+<td class="tblQmlPropNode"><p>
+<a name="scrollGestureEnabled-prop"></a><span class="name">scrollGestureEnabled</span> : <span class="type"><a href="../qtqml/qml-bool.html" translate="no">bool</a></span></p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This property controls whether this <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> responds to scroll gestures from non-mouse devices, such as the 2-finger flick gesture on a trackpad. If set to false, the <a href="qml-qtquick-mousearea.html#wheel-signal" translate="no">wheel</a> signal be emitted only when the wheel event comes from an actual mouse with a wheel, while scroll gesture events will pass through to any other Item that will handle them. For example, the user might perform a flick gesture while the cursor is over an item containing a <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a>, intending to interact with a Flickable which is underneath. Setting this property to false will allow the <a href="qml-qtquick-pincharea.html" translate="no">PinchArea</a> to handle the mouse wheel or the pinch gesture, while the Flickable handles the flick gesture.</p>
+<p>By default, this property is true.</p>
+<p>This property was introduced in Qt 5.5.</p>
+</div></div><!-- @@@scrollGestureEnabled -->
+<br/>
+<h2>Signal Documentation</h2>
+<!-- $$$canceled[overload1]$$$canceled -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="canceled-signal">
+<td class="tblQmlFuncNode"><p>
+<a name="canceled-signal"></a><span class="name">canceled</span>()</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This signal is emitted when mouse events have been canceled, because another item stole the mouse event handling.</p>
+<p>This signal is for advanced use: it is useful when there is more than one <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> that is handling input, or when there is a <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> inside a <a href="qml-qtquick-flickable.html" translate="no">Flickable</a>. In the latter case, if you execute some logic in the <code translate="no">onPressed</code> signal handler and then start dragging, the <a href="qml-qtquick-flickable.html" translate="no">Flickable</a> will steal the mouse handling from the <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a>. In these cases, to reset the logic when the <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> has lost the mouse handling to the <a href="qml-qtquick-flickable.html" translate="no">Flickable</a>, <code translate="no">canceled</code> should be handled in addition to <a href="qml-qtquick-mousearea.html#released-signal" translate="no">released</a>.</p>
+<p><b>Note: </b>The corresponding handler is <code translate="no">onCanceled</code>.</p>
+</div></div><!-- @@@canceled -->
+<br/>
+<!-- $$$clicked[overload1]$$$clickedMouseEvent -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="clicked-signal">
+<td class="tblQmlFuncNode"><p>
+<a name="clicked-signal"></a><span class="name">clicked</span>(<span class="type"><a href="qml-qtquick-mouseevent.html" translate="no">MouseEvent</a></span> <i>mouse</i>)</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This signal is emitted when there is a click. A click is defined as a press followed by a release, both inside the <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> (pressing, moving outside the <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a>, and then moving back inside and releasing is also considered a click).</p>
+<p>The <a href="qml-qtquick-mouseevent.html" translate="no">mouse</a> parameter provides information about the click, including the x and y position of the release of the click, and whether the click was held.</p>
+<p>When handling this signal, changing the <a href="qml-qtquick-mouseevent.html#accepted-prop" translate="no">accepted</a> property of the <i translate="no">mouse</i> parameter has no effect, unless the <a href="qml-qtquick-mousearea.html#propagateComposedEvents-prop" translate="no">propagateComposedEvents</a> property is <code translate="no">true</code>.</p>
+<p><b>Note: </b>The corresponding handler is <code translate="no">onClicked</code>.</p>
+</div></div><!-- @@@clicked -->
+<br/>
+<!-- $$$doubleClicked[overload1]$$$doubleClickedMouseEvent -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="doubleClicked-signal">
+<td class="tblQmlFuncNode"><p>
+<a name="doubleClicked-signal"></a><span class="name">doubleClicked</span>(<span class="type"><a href="qml-qtquick-mouseevent.html" translate="no">MouseEvent</a></span> <i>mouse</i>)</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This signal is emitted when there is a double-click (a press followed by a release followed by a press). The <a href="qml-qtquick-mouseevent.html" translate="no">mouse</a> parameter provides information about the click, including the x and y position of the release of the click, and whether the click was held.</p>
+<p>When handling this signal, if the <a href="qml-qtquick-mouseevent.html#accepted-prop" translate="no">accepted</a> property of the <i translate="no">mouse</i> parameter is set to false, the pressed/released/clicked signals will be emitted for the second click; otherwise they are suppressed. The <code translate="no">accepted</code> property defaults to true.</p>
+<p><b>Note: </b>The corresponding handler is <code translate="no">onDoubleClicked</code>.</p>
+</div></div><!-- @@@doubleClicked -->
+<br/>
+<!-- $$$entered[overload1]$$$entered -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="entered-signal">
+<td class="tblQmlFuncNode"><p>
+<a name="entered-signal"></a><span class="name">entered</span>()</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This signal is emitted when the mouse enters the mouse area.</p>
+<p>By default this signal is only emitted if a button is currently pressed. Set <a href="qml-qtquick-mousearea.html#hoverEnabled-prop" translate="no">hoverEnabled</a> to true to emit this signal even when no mouse button is pressed.</p>
+<p><b>Note: </b>The corresponding handler is <code translate="no">onEntered</code>.</p>
+<p><b>See also </b><a href="qml-qtquick-mousearea.html#hoverEnabled-prop" translate="no">hoverEnabled</a>.</p>
+</div></div><!-- @@@entered -->
+<br/>
+<!-- $$$exited[overload1]$$$exited -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="exited-signal">
+<td class="tblQmlFuncNode"><p>
+<a name="exited-signal"></a><span class="name">exited</span>()</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This signal is emitted when the mouse exits the mouse area.</p>
+<p>By default this signal is only emitted if a button is currently pressed. Set <a href="qml-qtquick-mousearea.html#hoverEnabled-prop" translate="no">hoverEnabled</a> to true to emit this signal even when no mouse button is pressed.</p>
+<p>The example below shows a fairly typical relationship between two MouseAreas, with <code translate="no">mouseArea2</code> on top of <code translate="no">mouseArea1</code>. Moving the mouse into <code translate="no">mouseArea2</code> from <code translate="no">mouseArea1</code> will cause <code translate="no">mouseArea1</code> to emit the <code translate="no">exited</code> signal.</p>
+<pre class="qml" translate="no">
+ <span class="type"><a href="qml-qtquick-rectangle.html" translate="no">Rectangle</a></span> {
+ <span class="name">width</span>: <span class="number">400</span>; <span class="name">height</span>: <span class="number">400</span>
+ <span class="type"><a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a></span> {
+ <span class="name">id</span>: <span class="name">mouseArea1</span>
+ <span class="name">anchors</span>.fill: <span class="name">parent</span>
+ <span class="name">hoverEnabled</span>: <span class="number">true</span>
+ }
+ <span class="type"><a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a></span> {
+ <span class="name">id</span>: <span class="name">mouseArea2</span>
+ <span class="name">width</span>: <span class="number">100</span>; <span class="name">height</span>: <span class="number">100</span>
+ <span class="name">anchors</span>.centerIn: <span class="name">parent</span>
+ <span class="name">hoverEnabled</span>: <span class="number">true</span>
+ }
+ }
+</pre>
+<p>If instead you give the two MouseAreas a parent-child relationship, moving the mouse into <code translate="no">mouseArea2</code> from <code translate="no">mouseArea1</code> will <b>not</b> cause <code translate="no">mouseArea1</code> to emit <code translate="no">exited</code>. Instead, they will both be considered to be simultaneously hovered.</p>
+<p><b>Note: </b>The corresponding handler is <code translate="no">onExited</code>.</p>
+<p><b>See also </b><a href="qml-qtquick-mousearea.html#hoverEnabled-prop" translate="no">hoverEnabled</a>.</p>
+</div></div><!-- @@@exited -->
+<br/>
+<!-- $$$positionChanged[overload1]$$$positionChangedMouseEvent -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="positionChanged-signal">
+<td class="tblQmlFuncNode"><p>
+<a name="positionChanged-signal"></a><span class="name">positionChanged</span>(<span class="type"><a href="qml-qtquick-mouseevent.html" translate="no">MouseEvent</a></span> <i>mouse</i>)</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This signal is emitted when the mouse position changes.</p>
+<p>The <a href="qml-qtquick-mouseevent.html" translate="no">mouse</a> parameter provides information about the mouse, including the x and y position, and any buttons currently pressed.</p>
+<p>By default this signal is only emitted if a button is currently pressed. Set <a href="qml-qtquick-mousearea.html#hoverEnabled-prop" translate="no">hoverEnabled</a> to true to emit this signal even when no mouse button is pressed.</p>
+<p>When handling this signal, changing the <a href="qml-qtquick-mouseevent.html#accepted-prop" translate="no">accepted</a> property of the <i translate="no">mouse</i> parameter has no effect.</p>
+<p><b>Note: </b>The corresponding handler is <code translate="no">onPositionChanged</code>.</p>
+</div></div><!-- @@@positionChanged -->
+<br/>
+<!-- $$$pressAndHold[overload1]$$$pressAndHoldMouseEvent -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="pressAndHold-signal">
+<td class="tblQmlFuncNode"><p>
+<a name="pressAndHold-signal"></a><span class="name">pressAndHold</span>(<span class="type"><a href="qml-qtquick-mouseevent.html" translate="no">MouseEvent</a></span> <i>mouse</i>)</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This signal is emitted when there is a long press (currently 800ms). The <a href="qml-qtquick-mouseevent.html" translate="no">mouse</a> parameter provides information about the press, including the x and y position of the press, and which button is pressed.</p>
+<p>When handling this signal, changing the <a href="qml-qtquick-mouseevent.html#accepted-prop" translate="no">accepted</a> property of the <i translate="no">mouse</i> parameter has no effect, unless the <a href="qml-qtquick-mousearea.html#propagateComposedEvents-prop" translate="no">propagateComposedEvents</a> property is <code translate="no">true</code>.</p>
+<p><b>Note: </b>The corresponding handler is <code translate="no">onPressAndHold</code>.</p>
+</div></div><!-- @@@pressAndHold -->
+<br/>
+<!-- $$$pressed[overload1]$$$pressedMouseEvent -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="pressed-signal">
+<td class="tblQmlFuncNode"><p>
+<a name="pressed-signal"></a><span class="name">pressed</span>(<span class="type"><a href="qml-qtquick-mouseevent.html" translate="no">MouseEvent</a></span> <i>mouse</i>)</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This signal is emitted when there is a press. The <a href="qml-qtquick-mouseevent.html" translate="no">mouse</a> parameter provides information about the press, including the x and y position and which button was pressed.</p>
+<p>When handling this signal, use the <a href="qml-qtquick-mouseevent.html#accepted-prop" translate="no">accepted</a> property of the <i translate="no">mouse</i> parameter to control whether this <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> handles the press and all future mouse events until release. The default is to accept the event and not allow other MouseAreas beneath this one to handle the event. If <i>accepted</i> is set to false, no further events will be sent to this <a href="qml-qtquick-mousearea.html" translate="no">MouseArea</a> until the button is next pressed.</p>
+<p><b>Note: </b>The corresponding handler is <code translate="no">onPressed</code>.</p>
+</div></div><!-- @@@pressed -->
+<br/>
+<!-- $$$released[overload1]$$$releasedMouseEvent -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="released-signal">
+<td class="tblQmlFuncNode"><p>
+<a name="released-signal"></a><span class="name">released</span>(<span class="type"><a href="qml-qtquick-mouseevent.html" translate="no">MouseEvent</a></span> <i>mouse</i>)</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This signal is emitted when there is a release. The <a href="qml-qtquick-mouseevent.html" translate="no">mouse</a> parameter provides information about the click, including the x and y position of the release of the click, and whether the click was held.</p>
+<p>When handling this signal, changing the <a href="qml-qtquick-mouseevent.html#accepted-prop" translate="no">accepted</a> property of the <i translate="no">mouse</i> parameter has no effect.</p>
+<p><b>Note: </b>The corresponding handler is <code translate="no">onReleased</code>.</p>
+<p><b>See also </b><a href="qml-qtquick-mousearea.html#canceled-signal" translate="no">canceled</a>.</p>
+</div></div><!-- @@@released -->
+<br/>
+<!-- $$$wheel[overload1]$$$wheelWheelEvent -->
+<div class="qmlitem"><div class="qmlproto" translate="no">
+<div class="table"><table class="qmlname">
+<tr valign="top" class="odd" id="wheel-signal">
+<td class="tblQmlFuncNode"><p>
+<a name="wheel-signal"></a><span class="name">wheel</span>(<span class="type"><a href="qml-qtquick-wheelevent.html" translate="no">WheelEvent</a></span> <i>wheel</i>)</p></td></tr>
+</table></div></div>
+<div class="qmldoc"><p>This signal is emitted in response to both mouse wheel and trackpad scroll gestures.</p>
+<p>The <i translate="no">wheel</i> parameter provides information about the event, including the x and y position, any buttons currently pressed, and information about the wheel movement, including angleDelta and pixelDelta.</p>
+<p><b>Note: </b>The corresponding handler is <code translate="no">onWheel</code>.</p>
+</div></div><!-- @@@wheel -->
+<br/>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<div class="footer">
+ <p>
+ <acronym title="Copyright">&copy;</acronym> 2023 The Qt Company Ltd.
+ Documentation contributions included herein are the copyrights of
+ their respective owners.<br/> The documentation provided herein is licensed under the terms of the <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation License version 1.3</a> as published by the Free Software Foundation.<br/> Qt and respective logos are <a href="https://doc.qt.io/qt/trademarks.html"> trademarks</a> of The Qt Company Ltd. in Finland and/or other countries
+ worldwide. All other trademarks are property of their respective owners. </p>
+</div>
+</body>
+</html>
diff --git a/tests/auto/qmlls/utils/data/qualifiedModule.qml b/tests/auto/qmlls/utils/data/qualifiedModule.qml
new file mode 100644
index 0000000000..4695f57d3f
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/qualifiedModule.qml
@@ -0,0 +1,7 @@
+import QtQuick as QQ
+
+QQ.Item {
+ property Item helloWorld: QQ.Item {}
+ QQ.
+
+} \ No newline at end of file
diff --git a/tests/auto/qmlls/utils/data/renaming/RenameMe.qml b/tests/auto/qmlls/utils/data/renaming/RenameMe.qml
new file mode 100644
index 0000000000..adc3da9800
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/renaming/RenameMe.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int i42
+} \ No newline at end of file
diff --git a/tests/auto/qmlls/utils/data/renaming/RenameMe2.ui.qml b/tests/auto/qmlls/utils/data/renaming/RenameMe2.ui.qml
new file mode 100644
index 0000000000..35320e03ff
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/renaming/RenameMe2.ui.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property string i42
+} \ No newline at end of file
diff --git a/tests/auto/qmlls/utils/data/renaming/RenamedByQmldir.qml b/tests/auto/qmlls/utils/data/renaming/RenamedByQmldir.qml
new file mode 100644
index 0000000000..f97cbcf115
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/renaming/RenamedByQmldir.qml
@@ -0,0 +1,4 @@
+import QtQuick
+
+Item {
+}
diff --git a/tests/auto/qmlls/utils/data/renaming/UnrelatedFile.qml b/tests/auto/qmlls/utils/data/renaming/UnrelatedFile.qml
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/renaming/UnrelatedFile.qml
diff --git a/tests/auto/qmlls/utils/data/renaming/main.qml b/tests/auto/qmlls/utils/data/renaming/main.qml
new file mode 100644
index 0000000000..10afda9773
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/renaming/main.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ RenameMe {}
+ RenameMe2 {}
+ HelloWorld {}
+}
diff --git a/tests/auto/qmlls/utils/data/renaming/qmldir b/tests/auto/qmlls/utils/data/renaming/qmldir
new file mode 100644
index 0000000000..8cff297e26
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/renaming/qmldir
@@ -0,0 +1,6 @@
+module renaming
+RenameMe 254.0 RenameMe.qml
+RenameMe2 254.0 RenameMe2.ui.qml
+RenameMe3 254.0 subfolder/RenameMe3.qml
+main 254.0 main.qml
+HelloWorld 254.0 RenamedByQmldir.qml \ No newline at end of file
diff --git a/tests/auto/qmlls/utils/data/resolveExpressionType/BaseType.qml b/tests/auto/qmlls/utils/data/resolveExpressionType/BaseType.qml
new file mode 100644
index 0000000000..210f55519d
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/resolveExpressionType/BaseType.qml
@@ -0,0 +1,12 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ function helloMethod() {}
+ property int helloProperty
+ signal helloSignal
+ enum HelloEnum { HelloEnumValue1, HelloEnumValue2, HelloEnumValue3 }
+ property font helloFont
+}
diff --git a/tests/auto/qmlls/utils/data/resolveExpressionType/BindingsOnDeferred.qml b/tests/auto/qmlls/utils/data/resolveExpressionType/BindingsOnDeferred.qml
new file mode 100644
index 0000000000..f0d82f3318
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/resolveExpressionType/BindingsOnDeferred.qml
@@ -0,0 +1,19 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls.Basic
+
+Item {
+ property var c: Control {
+ id: inner
+
+ property var myBinding: Binding {
+ inner.background: Item {}
+
+ inner {
+ background: Item {}
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/auto/qmlls/utils/data/resolveExpressionType/Derived1.qml b/tests/auto/qmlls/utils/data/resolveExpressionType/Derived1.qml
new file mode 100644
index 0000000000..687c190094
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/resolveExpressionType/Derived1.qml
@@ -0,0 +1,6 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+BaseType {
+
+}
diff --git a/tests/auto/qmlls/utils/data/resolveExpressionType/Derived2.qml b/tests/auto/qmlls/utils/data/resolveExpressionType/Derived2.qml
new file mode 100644
index 0000000000..3208d97778
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/resolveExpressionType/Derived2.qml
@@ -0,0 +1,6 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+Derived1 {
+
+}
diff --git a/tests/auto/qmlls/utils/data/resolveExpressionType/DerivedType.qml b/tests/auto/qmlls/utils/data/resolveExpressionType/DerivedType.qml
new file mode 100644
index 0000000000..ab0b542ce8
--- /dev/null
+++ b/tests/auto/qmlls/utils/data/resolveExpressionType/DerivedType.qml
@@ -0,0 +1,32 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Derived2 {
+ id: self
+ function f() {
+ helloMethod()
+ let x = helloProperty;
+ helloSignal()
+ let y = HelloEnum.HelloEnumValue1
+ }
+
+ property var someMethod: helloMethod()
+ property int someProperty: helloProperty
+ property var someEnum: HelloEnum.HelloEnumValue2
+ function someHandler() { helloSignal(); }
+ onHelloSignal: someHandler
+
+ Item {
+ property var someMethod: self.helloMethod()
+ property int someProperty: self.helloProperty
+ function f() {
+ self.helloSignal()
+ }
+ }
+ helloFont.family: "helloFamily"
+ Keys.onBackPressed: someHandler
+
+ helloProperty: 42
+}
diff --git a/tests/auto/qmlls/utils/tst_qmlls_documentationHints.cpp b/tests/auto/qmlls/utils/tst_qmlls_documentationHints.cpp
new file mode 100644
index 0000000000..dcb6f47df9
--- /dev/null
+++ b/tests/auto/qmlls/utils/tst_qmlls_documentationHints.cpp
@@ -0,0 +1,134 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "tst_qmlls_documentationHints.h"
+
+#include <QtQmlLS/private/qdochtmlparser_p.h>
+#include <QtQmlDom/private/qqmldomtop_p.h>
+
+tst_qmlls_documentationHints::tst_qmlls_documentationHints()
+ : QQmlDataTest(QT_QMLLS_DOCUMENTATION_DATADIR) , m_documentationDataDir(QT_QMLLS_DOCUMENTATION_DATADIR + "/documentationHints"_L1)
+{
+}
+
+void tst_qmlls_documentationHints::qdochtmlparser_data()
+{
+ using namespace QQmlJS::Dom;
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<QString>("keyword");
+ QTest::addColumn<DomType>("domType");
+ QTest::addColumn<HtmlExtractor::ExtractionMode>("extractionMode");
+ QTest::addColumn<QString>("expectedDocumentation");
+
+ QTest::addRow("qml-object-type-extended-plaintext")
+ << testFile("qdochtmlparser/qml-qtqml-qtobject.html")
+ << "QtObject"
+ << DomType::QmlObject
+ << HtmlExtractor::ExtractionMode::Extended
+ << R"(The QtObject type is a non-visual element which contains only the objectName property.
+It can be useful to create a QtObject if you need an extremely lightweight type to enclose a set of custom properties:
+
+ import QtQuick
+
+ Item {
+ QtObject {
+ id: attributes
+ property string name
+ property int size
+ property variant attributes
+ }
+
+ Text { text: attributes.name }
+ }
+
+It can also be useful for C++ integration, as it is just a plain QObject. See the QObject documentation for further details.)";
+
+ QTest::addRow("qml-object-type-simplified-plaintext")
+ << testFile("qdochtmlparser/qml-qtqml-qtobject.html")
+ << "QtObject"
+ << DomType::QmlObject
+ << HtmlExtractor::ExtractionMode::Simplified
+ << R"(A basic QML type.)";
+
+ QTest::addRow("qml-property-simplified-plaintext")
+ << testFile("qdochtmlparser/qml-qtqml-qtobject.html")
+ << "objectName"
+ << DomType::PropertyDefinition
+ << HtmlExtractor::ExtractionMode::Simplified
+ << R"(This property holds the QObject::objectName for this specific object instance.)";
+
+ QTest::addRow("qml-property-simplified-plaintext-from-Qt5")
+ << testFile("qdochtmlparser/qml-qtqml-qtobject-qt-5.html")
+ << "objectName"
+ << DomType::PropertyDefinition
+ << HtmlExtractor::ExtractionMode::Simplified
+ << R"(This property holds the QObject::objectName for this specific object instance.)";
+
+ QTest::addRow("qml-property-simplified-plaintext")
+ << testFile("qdochtmlparser/qml-qtquick-item.html")
+ << "width"
+ << DomType::PropertyDefinition
+ << HtmlExtractor::ExtractionMode::Simplified
+ << R"(Defines the item's position and size. The default value is 0.)";
+
+ QTest::addRow("qml-group-property-simplified-plaintext")
+ << testFile("qdochtmlparser/qml-qtquick-item.html")
+ << "anchors.fill"
+ << DomType::PropertyDefinition
+ << HtmlExtractor::ExtractionMode::Simplified
+ << R"(Anchors provide a way to position an item by specifying its relationship with other items.)";
+ QTest::addRow("qml-functions")
+ << testFile("qdochtmlparser/qml-qtquick-item.html")
+ << "mapFromGlobal"
+ << DomType::MethodInfo
+ << HtmlExtractor::ExtractionMode::Simplified
+ << "Maps the point (x, y), which is in the global coordinate system, to the item's coordinate system,"
+ " and returns a point matching the mapped coordinate.";
+
+ QTest::addRow("qml-functions-list")
+ << testFile("qdochtmlparser/qml-qtquick-item.html")
+ << "mapFromItem"
+ << DomType::MethodInfo
+ << HtmlExtractor::ExtractionMode::Simplified
+ << "Maps the point (x, y) or rect (x, y, width, height), which is in item's coordinate system,"
+ " to this item's coordinate system, and returns a point or rect matching the mapped coordinate.";
+ QTest::addRow("qml-signal")
+ << testFile("qdochtmlparser/qml-qtquick-mousearea.html")
+ << "pressAndHold"
+ << DomType::MethodInfo
+ << HtmlExtractor::ExtractionMode::Simplified
+ << "This signal is emitted when there is a long press (currently 800ms). The mouse parameter provides information about the press, "
+ "including the x and y position of the press, and which button is pressed.";
+
+ // Some properties and methods can be shown as in groups in qt-docs, like width and height of Item.
+ QTest::addRow("multiple-entries")
+ << testFile("qdochtmlparser/qml-qtquick-mousearea.html")
+ << "pressAndHold"
+ << DomType::MethodInfo
+ << HtmlExtractor::ExtractionMode::Simplified
+ << "This signal is emitted when there is a long press (currently 800ms). The mouse parameter provides information about the press, "
+ "including the x and y position of the press, and which button is pressed.";
+}
+
+void tst_qmlls_documentationHints::qdochtmlparser()
+{
+ using namespace QQmlJS::Dom;
+ QFETCH(QString, filePath);
+ QFETCH(QString, keyword);
+ QFETCH(DomType, domType);
+ QFETCH(HtmlExtractor::ExtractionMode, extractionMode);
+ QFETCH(QString, expectedDocumentation);
+
+ const auto htmlCode = [](const QString &testFileName) {
+ QFile file(testFileName);
+ if (file.open(QIODeviceBase::ReadOnly | QIODevice::Text))
+ return QString::fromUtf8(file.readAll());
+ return QString{};
+ }(filePath);
+
+ ExtractDocumentation extractor(domType);
+ const auto actual = extractor.execute(htmlCode, keyword, extractionMode);
+ QCOMPARE(actual, expectedDocumentation);
+}
+
+QTEST_MAIN(tst_qmlls_documentationHints)
diff --git a/tests/auto/qmlls/utils/tst_qmlls_documentationHints.h b/tests/auto/qmlls/utils/tst_qmlls_documentationHints.h
new file mode 100644
index 0000000000..f3b0f4ddd1
--- /dev/null
+++ b/tests/auto/qmlls/utils/tst_qmlls_documentationHints.h
@@ -0,0 +1,24 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TST_QMLLS_DOCUMENTATION_H
+#define TST_QMLLS_DOCUMENTATION_H
+
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtCore/qobject.h>
+#include <QtTest/qtest.h>
+
+class tst_qmlls_documentationHints : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_qmlls_documentationHints();
+private slots:
+ void qdochtmlparser_data();
+ void qdochtmlparser();
+
+private:
+ QString m_documentationDataDir;
+};
+
+#endif // TST_QMLLS_DOCUMENTATION_H
diff --git a/tests/auto/qmlls/utils/tst_qmlls_highlighting.cpp b/tests/auto/qmlls/utils/tst_qmlls_highlighting.cpp
new file mode 100644
index 0000000000..f21de11990
--- /dev/null
+++ b/tests/auto/qmlls/utils/tst_qmlls_highlighting.cpp
@@ -0,0 +1,650 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "tst_qmlls_highlighting.h"
+
+#include <QtQml/private/qqmljsengine_p.h>
+#include <QtQml/private/qqmljslexer_p.h>
+#include <QtQml/private/qqmljsparser_p.h>
+#include <QtQmlDom/private/qqmldomitem_p.h>
+#include <QtQmlDom/private/qqmldomtop_p.h>
+#include <QtQmlLS/private/qqmlsemantictokens_p.h>
+#include <QtCore/qlibraryinfo.h>
+#include <QtLanguageServer/private/qlanguageserverspectypes_p.h>
+
+#include <qlist.h>
+
+using namespace QLspSpecification;
+
+tst_qmlls_highlighting::tst_qmlls_highlighting()
+ : QQmlDataTest(QT_QMLLS_HIGHLIGHTS_DATADIR) , m_highlightingDataDir(QT_QMLLS_HIGHLIGHTS_DATADIR + "/highlights"_L1)
+{
+}
+
+// Token encoding as in:
+// https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#textDocument_semanticTokens
+void tst_qmlls_highlighting::encodeSemanticTokens_data()
+{
+ QTest::addColumn<Highlights>("highlights");
+ QTest::addColumn<QList<int>>("expectedMemoryLayout");
+
+ {
+ Highlights c;
+ c.highlights().insert(0, Token());
+ QTest::addRow("empty-token-single") << c << QList {0, 0, 0, 0, 0};
+ }
+ {
+ Highlights c;
+ QQmlJS::SourceLocation loc(0, 1, 1, 1);
+ c.highlights().insert(0, Token(loc, 0, 0));
+ QTest::addRow("single-token") << c << QList {0, 0, 1, 0, 0};
+ }
+ {
+ Highlights c;
+ Token t1(QQmlJS::SourceLocation(0, 1, 1, 1), 0, 0);
+ Token t2(QQmlJS::SourceLocation(1, 1, 3, 3), 0, 0);
+ c.highlights().insert(t1.offset, t1);
+ c.highlights().insert(t2.offset, t2);
+ QTest::addRow("different-lines") << c << QList {0, 0, 1, 0, 0, 2, 2, 1, 0, 0};
+ }
+ {
+ Highlights c;
+ Token t1(QQmlJS::SourceLocation(0, 1, 1, 1), 0, 0);
+ Token t2(QQmlJS::SourceLocation(1, 1, 1, 3), 0, 0);
+ c.highlights().insert(t1.offset, t1);
+ c.highlights().insert(t2.offset, t2);
+ QTest::addRow("same-line-different-column") << c << QList {0, 0, 1, 0, 0, 0, 2, 1, 0, 0};
+ }
+ {
+ Highlights c;
+ Token t1(QQmlJS::SourceLocation(0, 1, 1, 1), 1, 0);
+ c.highlights().insert(t1.offset, t1);
+ QTest::addRow("token-type") << c << QList {0, 0, 1, 1, 0};
+ }
+ {
+ Highlights c;
+ Token t1(QQmlJS::SourceLocation(0, 1, 1, 1), 1, 1);
+ c.highlights().insert(t1.offset, t1);
+ QTest::addRow("token-modifier") << c << QList {0, 0, 1, 1, 1};
+ }
+}
+
+void tst_qmlls_highlighting::encodeSemanticTokens()
+{
+ QFETCH(Highlights, highlights);
+ QFETCH(QList<int>, expectedMemoryLayout);
+ const auto encoded = HighlightingUtils::encodeSemanticTokens(highlights);
+ QCOMPARE(encoded, expectedMemoryLayout);
+}
+
+struct LineLength
+{
+ quint32 startLine;
+ quint32 length;
+};
+
+void tst_qmlls_highlighting::sourceLocationsFromMultiLineToken_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<QList<LineLength>>("expectedLines");
+
+ QTest::addRow("multilineComment1") << R"("line 1
+line 2
+line 3 ")" << QList{ LineLength{ 1, 7 }, LineLength{ 2, 6 }, LineLength{ 3, 8 } };
+
+ QTest::addRow("prePostNewlines") <<
+ R"("
+
+")" << QList{ LineLength{ 1, 1 }, LineLength{ 2, 0 }, LineLength{ 3, 1 } };
+ QTest::addRow("windows-newline")
+ << QString::fromUtf8("\"test\r\nwindows\r\nnewline\"")
+ << QList{ LineLength{ 1, 5 }, LineLength{ 2, 7 }, LineLength{ 3, 8 } };
+}
+
+void tst_qmlls_highlighting::sourceLocationsFromMultiLineToken()
+{
+ QFETCH(QString, source);
+ QFETCH(QList<LineLength>, expectedLines);
+ using namespace QQmlJS::AST;
+
+ QQmlJS::Engine jsEngine;
+ QQmlJS::Lexer lexer(&jsEngine);
+ lexer.setCode(source, 1, true);
+ QQmlJS::Parser parser(&jsEngine);
+ parser.parseExpression();
+ const auto expression = parser.expression();
+
+ auto *literal = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(expression);
+ const auto locs =
+ HighlightingUtils::sourceLocationsFromMultiLineToken(source, literal->literalToken);
+
+ [&]() {
+ QCOMPARE(locs.size(), expectedLines.size());
+
+ for (auto i = 0; i < locs.size(); ++i) {
+ QCOMPARE(locs[i].startLine, expectedLines[i].startLine);
+ QCOMPARE(locs[i].length, expectedLines[i].length);
+ }
+ }();
+
+ if (QTest::currentTestFailed()) {
+
+ qDebug() << "Actual locations";
+ for (auto i = 0; i < locs.size(); ++i) {
+ qDebug() << "Startline :" << locs[i].startLine << "Length " << locs[i].length;
+ }
+
+ qDebug() << "Expected locations";
+ for (auto i = 0; i < expectedLines.size(); ++i) {
+ qDebug() << "Startline :" << expectedLines[i].startLine
+ << "Length :" << expectedLines[i].length;
+ }
+ }
+}
+
+void tst_qmlls_highlighting::highlights_data()
+{
+ using namespace QQmlJS::Dom;
+ QTest::addColumn<DomItem>("fileItem");
+ QTest::addColumn<Token>("expectedHighlightedToken");
+
+ const auto fileObject = [](const QString &filePath){
+ QFile f(filePath);
+ DomItem file;
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
+ return file;
+ QString code = f.readAll();
+ DomCreationOptions options;
+ options.setFlag(DomCreationOption::WithScriptExpressions);
+ options.setFlag(DomCreationOption::WithSemanticAnalysis);
+ options.setFlag(DomCreationOption::WithRecovery);
+
+ QStringList dirs = {QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath)};
+ auto envPtr = DomEnvironment::create(dirs,
+ QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
+ | QQmlJS::Dom::DomEnvironment::Option::NoDependencies, options);
+ envPtr->loadBuiltins();
+ envPtr->loadFile(FileToLoad::fromMemory(envPtr, filePath, code),
+ [&file](Path, const DomItem &, const DomItem &newIt) {
+ file = newIt.fileObject();
+ });
+ envPtr->loadPendingDependencies();
+ return file;
+ };
+
+ { // Comments
+ const auto filePath = m_highlightingDataDir + "/comments.qml";
+ const auto fileItem = fileObject(filePath);
+ // Copyright (C) 2023 The Qt Company Ltd.
+ QTest::addRow("single-line-1")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(0, 41, 1, 1), int(SemanticTokenTypes::Comment), 0);
+
+ /* single line comment */
+ QTest::addRow("single-line-2") << fileItem
+ << Token(QQmlJS::SourceLocation(162, 28, 9, 1),
+ int(SemanticTokenTypes::Comment), 0);
+
+ // Multiline comments are split into multiple locations
+ QTest::addRow("multiline-first-line")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(133, 2, 5, 1), int(SemanticTokenTypes::Comment), 0);
+ QTest::addRow("multiline-second-line") << fileItem
+ << Token(QQmlJS::SourceLocation(136, 21, 6, 1),
+ int(SemanticTokenTypes::Comment), 0);
+ QTest::addRow("multiline-third-line")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(158, 2, 7, 1), int(SemanticTokenTypes::Comment), 0);
+
+ // Comments Inside Js blocks
+ QTest::addRow("inside-js") << fileItem
+ << Token(QQmlJS::SourceLocation(232, 5, 13, 9),
+ int(SemanticTokenTypes::Comment), 0);
+ }
+ { // Imports
+ const auto filePath = m_highlightingDataDir + "/imports.qml";
+ const auto fileItem = fileObject(filePath);
+ QTest::addRow("import-keyword")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(112, 6, 4, 1), int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("module-uri") << fileItem
+ << Token(QQmlJS::SourceLocation(119, 7, 4, 8),
+ int(SemanticTokenTypes::Namespace), 0);
+ QTest::addRow("directory-uri")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(152, 3, 6, 8), int(SemanticTokenTypes::String), 0);
+ QTest::addRow("as-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(156, 2, 6, 12),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("version-number")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(140, 4, 5, 14), int(SemanticTokenTypes::Number), 0);
+ QTest::addRow("qualified-namespace") << fileItem
+ << Token(QQmlJS::SourceLocation(159, 6, 6, 15),
+ int(SemanticTokenTypes::Namespace), 0);
+ }
+ { // Bindings
+ const auto filePath = m_highlightingDataDir + "/bindings.qml";
+ const auto fileItem = fileObject(filePath);
+
+ // normal binding
+ QTest::addRow("normalBinding") << fileItem
+ << Token(QQmlJS::SourceLocation(189, 1, 11, 5),
+ int(SemanticTokenTypes::Property), 0);
+ // on binding
+ QTest::addRow("on-binding") << fileItem
+ << Token(QQmlJS::SourceLocation(175, 5, 9, 17),
+ int(SemanticTokenTypes::Property), 0);
+ QTest::addRow("on-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(172, 2, 9, 14),
+ int(SemanticTokenTypes::Keyword), 0);
+ }
+ { // Pragmas
+ const auto filePath = m_highlightingDataDir + "/pragmas.qml";
+ const auto fileItem = fileObject(filePath);
+ QTest::addRow("pragma-keyword")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(112, 6, 4, 1), int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("pragma-name") << fileItem
+ << Token(QQmlJS::SourceLocation(136, 25, 5, 8),
+ int(SemanticTokenTypes::Variable), 0);
+ QTest::addRow("pragma-value") << fileItem
+ << Token(QQmlJS::SourceLocation(198, 4, 6, 27),
+ int(SemanticTokenTypes::Variable), 0);
+ }
+ { // Enums
+ const auto filePath = m_highlightingDataDir + "/enums.qml";
+ const auto fileItem = fileObject(filePath);
+ QTest::addRow("enum-keyword")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(141, 4, 7, 5), int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("enum-name")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(146, 3, 7, 10), int(SemanticTokenTypes::Enum), 0);
+ QTest::addRow("enum-item") << fileItem
+ << Token(QQmlJS::SourceLocation(160, 3, 8, 9),
+ int(SemanticTokenTypes::EnumMember), 0);
+ QTest::addRow("enum-value")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(179, 1, 9, 15), int(SemanticTokenTypes::Number), 0);
+ }
+ { // objects and inline components
+ const auto filePath = m_highlightingDataDir + "/objectAndComponent.qml";
+ const auto fileItem = fileObject(filePath);
+
+ // object
+ QTest::addRow("object-identifier")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(169, 4, 8, 5), int(SemanticTokenTypes::Type), 0);
+ QTest::addRow("object-id-property") << fileItem
+ << Token(QQmlJS::SourceLocation(184, 2, 9, 9),
+ int(SemanticTokenTypes::Property), 0);
+ QTest::addRow("object-id-name") << fileItem
+ << Token(QQmlJS::SourceLocation(188, 5, 9, 13),
+ int(SemanticTokenTypes::Variable), 0);
+
+ // component
+ QTest::addRow("component-keyword")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(139, 9, 7, 5), int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("component-name")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(149, 6, 7, 15), int(SemanticTokenTypes::Type), 0);
+ }
+ { // property definition
+ const auto filePath = m_highlightingDataDir + "/properties.qml";
+ const auto fileItem = fileObject(filePath);
+
+ int definitionModifier = 1 << int(SemanticTokenModifiers::Definition);
+ QTest::addRow("property-keyword")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(154, 8, 8, 9), int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("property-type")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(163, 3, 8, 18), int(SemanticTokenTypes::Type), 0);
+ QTest::addRow("property-name")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(167, 1, 8, 22), int(SemanticTokenTypes::Property),
+ definitionModifier);
+ int readOnlyModifier = definitionModifier | (1 << int(SemanticTokenModifiers::Readonly));
+ QTest::addRow("readonly-keyword")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(177, 8, 9, 9), int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("readonly-modifier")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(199, 2, 9, 31), int(SemanticTokenTypes::Property),
+ readOnlyModifier);
+ int requiredModifier = definitionModifier | (1 << int(SemanticTokenModifiers::Abstract));
+ QTest::addRow("required-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(210, 8, 10, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("required-modifier")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(232, 3, 10, 31), int(SemanticTokenTypes::Property),
+ requiredModifier);
+ int defaultModifier =
+ definitionModifier | (1 << int(SemanticTokenModifiers::DefaultLibrary));
+ QTest::addRow("default-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(244, 7, 11, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("default-modifier")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(265, 4, 11, 30), int(SemanticTokenTypes::Property),
+ defaultModifier);
+ }
+ {
+ // methods and signals
+ const auto filePath = m_highlightingDataDir + "/methodAndSignal.qml";
+ const auto fileItem = fileObject(filePath);
+
+ QTest::addRow("signal-keyword")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(139, 6, 7, 5), int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("signal-name")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(146, 1, 7, 12), int(SemanticTokenTypes::Method), 0);
+ QTest::addRow("signal-type")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(163, 3, 8, 14), int(SemanticTokenTypes::Type), 0);
+ QTest::addRow("signal-type-2")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(186, 3, 9, 17), int(SemanticTokenTypes::Type), 0);
+ QTest::addRow("function-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(195, 9, 10, 5),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("function-name") << fileItem
+ << Token(QQmlJS::SourceLocation(204, 1, 10, 14),
+ int(SemanticTokenTypes::Method), 0);
+ QTest::addRow("function-prm-type")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(209, 3, 10, 19), int(SemanticTokenTypes::Type), 0);
+ QTest::addRow("function-prm-name") << fileItem
+ << Token(QQmlJS::SourceLocation(206, 1, 10, 16),
+ int(SemanticTokenTypes::Parameter), 0);
+ QTest::addRow("function-rtn-type")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(216, 3, 10, 26), int(SemanticTokenTypes::Type), 0);
+ }
+ { // literals
+ const auto filePath = m_highlightingDataDir + "/literals.qml";
+ const auto fileItem = fileObject(filePath);
+
+ QTest::addRow("number") << fileItem
+ << Token(QQmlJS::SourceLocation(155, 3, 7, 21),
+ int(SemanticTokenTypes::Number), 0);
+ QTest::addRow("singleline-string")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(182, 8, 8, 24), int(SemanticTokenTypes::String), 0);
+ QTest::addRow("multiline-string-first")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(214, 6, 9, 24), int(SemanticTokenTypes::String), 0);
+ QTest::addRow("multiline-string-second") << fileItem
+ << Token(QQmlJS::SourceLocation(221, 16, 10, 1),
+ int(SemanticTokenTypes::String), 0);
+ QTest::addRow("boolean") << fileItem
+ << Token(QQmlJS::SourceLocation(260, 4, 11, 22),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("null") << fileItem
+ << Token(QQmlJS::SourceLocation(285, 4, 12, 21),
+ int(SemanticTokenTypes::Keyword), 0);
+ }
+ { // identifiers
+ const auto filePath = m_highlightingDataDir + "/Identifiers.qml";
+ const auto fileItem = fileObject(filePath);
+ QTest::addRow("js-property") << fileItem
+ << Token(QQmlJS::SourceLocation(222, 3, 10, 13),
+ int(SemanticTokenTypes::Variable), 0);
+ QTest::addRow("property-id")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(302, 4, 12, 19), int(SemanticTokenTypes::Property),
+ (1 << int(SemanticTokenModifiers::Readonly)));
+ QTest::addRow("property-changed") << fileItem
+ << Token(QQmlJS::SourceLocation(451, 11, 18, 9),
+ int(SemanticTokenTypes::Method), 0);
+ QTest::addRow("signal") << fileItem
+ << Token(QQmlJS::SourceLocation(474, 7, 19, 9),
+ int(SemanticTokenTypes::Method), 0);
+
+ QTest::addRow("attached-id")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(512, 4, 23, 5), int(SemanticTokenTypes::Type), 0);
+ QTest::addRow("attached-signalhandler") << fileItem
+ << Token(QQmlJS::SourceLocation(517, 9, 23, 10),
+ int(SemanticTokenTypes::Method), 0);
+ QTest::addRow("propchanged-handler") << fileItem
+ << Token(QQmlJS::SourceLocation(572, 13, 27, 5),
+ int(SemanticTokenTypes::Method), 0);
+ QTest::addRow("method-id")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(597, 1, 28, 9), int(SemanticTokenTypes::Method), 0);
+ QTest::addRow("signal-handler")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(656, 9, 32, 5), int(SemanticTokenTypes::Method), 0);
+ }
+ { // script expressions
+ const auto filePath = m_highlightingDataDir + "/scriptExpressions.qml";
+ const auto fileItem = fileObject(filePath);
+
+ QTest::addRow("var-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(192, 3, 11, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("const-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(217, 5, 12, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ const auto modifier = (1 << int(SemanticTokenModifiers::Readonly));
+ QTest::addRow("const-name") << fileItem
+ << Token(QQmlJS::SourceLocation(223, 10, 12, 15),
+ int(SemanticTokenTypes::Variable), modifier);
+ QTest::addRow("do-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(248, 2, 13, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("if-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(287, 2, 15, 13),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("continue-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(319, 8, 16, 17),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("else-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(341, 4, 17, 13),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("while-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(382, 5, 19, 11),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("switch-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(418, 6, 20, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("case-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(444, 4, 21, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("return-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(464, 6, 22, 13),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("default-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(483, 7, 23, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("break-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(504, 5, 24, 13),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("try-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(529, 3, 26, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("catch-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(560, 5, 28, 11),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("finally-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(601, 7, 30, 11),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("for-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(620, 3, 31, 9),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("throw-keyword") << fileItem
+ << Token(QQmlJS::SourceLocation(661, 5, 32, 13),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("for-declaration") << fileItem
+ << Token(QQmlJS::SourceLocation(625, 5, 31, 14),
+ int(SemanticTokenTypes::Keyword), 0);
+ QTest::addRow("destructuring")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(1511, 2, 73, 16), int(SemanticTokenTypes::Variable),
+ (1 << int(SemanticTokenModifiers::Readonly)));
+ QTest::addRow("obj-destructuring")
+ << fileItem
+ << Token(QQmlJS::SourceLocation(1589, 2, 76, 17), int(SemanticTokenTypes::Variable),
+ (1 << int(SemanticTokenModifiers::Readonly)));
+ }
+}
+
+void tst_qmlls_highlighting::highlights()
+{
+ using namespace QQmlJS::Dom;
+ QFETCH(DomItem, fileItem);
+ QFETCH(Token, expectedHighlightedToken);
+
+ Highlights h;
+ HighlightingVisitor hv(h, std::nullopt);
+
+ fileItem.visitTree(QQmlJS::Dom::Path(), hv, VisitOption::Default, emptyChildrenVisitor,
+ emptyChildrenVisitor);
+
+ const auto highlights = h.highlights();
+ QVERIFY(highlights.contains(expectedHighlightedToken.offset));
+ QCOMPARE(highlights.value(expectedHighlightedToken.offset), expectedHighlightedToken);
+}
+
+void tst_qmlls_highlighting::rangeOverlapsWithSourceLocation_data()
+{
+ QTest::addColumn<QQmlJS::SourceLocation>("sourceLocation");
+ QTest::addColumn<HighlightsRange>("range");
+ QTest::addColumn<bool>("overlaps");
+
+ QTest::addRow("sl-inside-range")
+ << QQmlJS::SourceLocation(5, 1, 1, 1) << HighlightsRange{ 0, 100 } << true;
+ QTest::addRow("sl-exceeds-rightBoundRange")
+ << QQmlJS::SourceLocation(5, 1000, 1, 1) << HighlightsRange{ 0, 100 } << true;
+ QTest::addRow("sl-exceeds-leftRightBoundRange")
+ << QQmlJS::SourceLocation(5, 1000, 1, 1) << HighlightsRange{ 8, 100 } << true;
+ QTest::addRow("sl-exceeds-leftBoundRange")
+ << QQmlJS::SourceLocation(5, 100, 1, 1) << HighlightsRange{ 8, 1000 } << true;
+ QTest::addRow("no-overlaps") << QQmlJS::SourceLocation(5, 100, 1, 1)
+ << HighlightsRange{ 8000, 100000 } << false;
+}
+
+void tst_qmlls_highlighting::rangeOverlapsWithSourceLocation()
+{
+ QFETCH(QQmlJS::SourceLocation, sourceLocation);
+ QFETCH(HighlightsRange, range);
+ QFETCH(bool, overlaps);
+ QVERIFY(overlaps == HighlightingUtils::rangeOverlapsWithSourceLocation(sourceLocation, range));
+}
+
+void tst_qmlls_highlighting::updateResultID_data()
+{
+ QTest::addColumn<QByteArray>("currentId");
+ QTest::addColumn<QByteArray>("expectedNextId");
+
+ QTest::addRow("zero-to-one") << QByteArray("0") << QByteArray("1");
+ QTest::addRow("nine-to-ten") << QByteArray("9") << QByteArray("10");
+ QTest::addRow("nineteen-to-twenty") << QByteArray("19") << QByteArray("20");
+ QTest::addRow("twodigit-to-threedigit") << QByteArray("99") << QByteArray("100");
+}
+
+void tst_qmlls_highlighting::updateResultID()
+{
+ QFETCH(QByteArray, currentId);
+ QFETCH(QByteArray, expectedNextId);
+
+ HighlightingUtils::updateResultID(currentId);
+ QCOMPARE(currentId, expectedNextId);
+}
+
+void tst_qmlls_highlighting::computeDiff_data()
+{
+ QTest::addColumn<QList<int>>("oldData");
+ QTest::addColumn<QList<int>>("newData");
+ QTest::addColumn<QList<SemanticTokensEdit>>("expected");
+
+ {
+ QList<int> oldData { 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0};
+ QList<int> newData { 3,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0};
+ SemanticTokensEdit expected;
+ expected.start = 0;
+ expected.deleteCount = 1;
+ expected.data = QList{3};
+ QTest::addRow("simple") << oldData << newData << QList{expected};
+ }
+ {
+ QList<int> oldData { 0, 0, 5, 5, 0};
+ QList<int> newData { 3, 3, 3, 3, 3, 0, 0, 5, 5, 0};
+ SemanticTokensEdit expected;
+ expected.start = 0;
+ expected.deleteCount = 0;
+ expected.data = QList{3, 3, 3, 3, 3};
+ QTest::addRow("prepend") << oldData << newData << QList{expected};
+ }
+ {
+ QList<int> oldData { 3, 3, 3, 3, 3, 0, 0, 5, 5, 0};
+ QList<int> newData { 0, 0, 5, 5, 0};
+ SemanticTokensEdit expected;
+ expected.start = 0;
+ expected.deleteCount = 5;
+ expected.data = {};
+ QTest::addRow("remove-front") << oldData << newData << QList{expected};
+ }
+ {
+ QList<int> oldData { 0, 0, 5, 5, 0};
+ QList<int> newData { 0, 0, 5, 5, 0, 1, 0, 23, 5, 0};
+ SemanticTokensEdit expected;
+ expected.start = 5;
+ expected.deleteCount = 0;
+ expected.data = QList{1, 0, 23, 5, 0};
+ QTest::addRow("append") << oldData << newData << QList{expected};
+ }
+ {
+ QList<int> oldData { 0, 0, 5, 5, 0, 1, 0, 23, 5, 0};
+ QList<int> newData { 0, 0, 5, 5, 0};
+ SemanticTokensEdit expected;
+ expected.start = 5;
+ expected.deleteCount = 5;
+ expected.data = {};
+ QTest::addRow("remove-back") << oldData << newData << QList{expected};
+ }
+ {
+ QList<int> oldData { 0, 0, 5, 5, 0, 1, 0, 23, 5, 0};
+ QList<int> newData { 0, 0, 5, 5, 0, 3, 3, 3, 3, 3, 1, 0, 23, 5, 0};
+ SemanticTokensEdit expected;
+ expected.start = 5;
+ expected.deleteCount = 0;
+ expected.data = QList{3, 3, 3, 3, 3};
+ QTest::addRow("insert-middle") << oldData << newData << QList{expected};
+ }
+ {
+ QList<int> oldData { 0, 0, 5, 5, 0, 3, 3, 3, 3, 3, 1, 0, 23, 5, 0};
+ QList<int> newData { 0, 0, 5, 5, 0, 1, 0, 23, 5, 0};
+ SemanticTokensEdit expected;
+ expected.start = 5;
+ expected.deleteCount = 5;
+ expected.data = {};
+ QTest::addRow("remove-middle") << oldData << newData << QList{expected};
+ }
+}
+
+void tst_qmlls_highlighting::computeDiff()
+{
+ QFETCH(QList<int>, oldData);
+ QFETCH(QList<int>, newData);
+ QFETCH(QList<SemanticTokensEdit>, expected);
+
+ const auto edits = HighlightingUtils::computeDiff(oldData, newData);
+ QCOMPARE(edits.size(), expected.size());
+
+ qsizetype i = 0;
+ for (const auto &edit : edits) {
+ QCOMPARE(edit.start, expected.at(i).start);
+ QCOMPARE(edit.deleteCount, expected.at(i).deleteCount);
+ QCOMPARE(edit.data, expected.at(i).data);
+ ++i;
+ }
+}
+
+
+QTEST_MAIN(tst_qmlls_highlighting)
diff --git a/tests/auto/qmlls/utils/tst_qmlls_highlighting.h b/tests/auto/qmlls/utils/tst_qmlls_highlighting.h
new file mode 100644
index 0000000000..a1d0e3c9b1
--- /dev/null
+++ b/tests/auto/qmlls/utils/tst_qmlls_highlighting.h
@@ -0,0 +1,37 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TST_QMLLS_HIGHLIGHTING_H
+#define TST_QMLLS_HIGHLIGHTING_H
+
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtCore/qobject.h>
+#include <QtTest/qtest.h>
+
+class tst_qmlls_highlighting : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_qmlls_highlighting();
+private slots:
+ void encodeSemanticTokens_data();
+ void encodeSemanticTokens();
+ void sourceLocationsFromMultiLineToken_data();
+ void sourceLocationsFromMultiLineToken();
+
+ void highlights_data();
+ void highlights();
+
+ void rangeOverlapsWithSourceLocation_data();
+ void rangeOverlapsWithSourceLocation();
+
+ void updateResultID_data();
+ void updateResultID();
+
+ void computeDiff_data();
+ void computeDiff();
+private:
+ QString m_highlightingDataDir;
+};
+
+#endif // TST_QMLLS_HIGHLIGHTING_H
diff --git a/tests/auto/qmlls/utils/tst_qmlls_utils.cpp b/tests/auto/qmlls/utils/tst_qmlls_utils.cpp
new file mode 100644
index 0000000000..332dc13590
--- /dev/null
+++ b/tests/auto/qmlls/utils/tst_qmlls_utils.cpp
@@ -0,0 +1,4156 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "tst_qmlls_utils.h"
+#include <algorithm>
+#include <optional>
+
+#include <QtCore/private/qduplicatetracker_p.h>
+#include <QtQmlLS/private/qdochtmlparser_p.h>
+
+// some helper constants for the tests
+const static int positionAfterOneIndent = 5;
+const static QString noResultExpected;
+// constants for resultIndex
+const static int firstResult = 0;
+const static int secondResult = 1;
+// constants for expectedItemsCount
+const static int outOfOne = 1;
+const static int outOfTwo = 2;
+
+// enable/disable additional debug output
+constexpr static bool enable_debug_output = true;
+
+static QString printSet(const QSet<QString> &s)
+{
+ const QString r = QStringList(s.begin(), s.end()).join(u", "_s);
+ return r;
+}
+
+static QString readFileContent(const QString &testFileName) {
+ QFile file(testFileName);
+ if (file.open(QIODeviceBase::ReadOnly))
+ return QString::fromUtf8(file.readAll());
+ return QString{};
+};
+
+std::tuple<QQmlJS::Dom::DomItem, QQmlJS::Dom::DomItem>
+tst_qmlls_utils::createEnvironmentAndLoadFile(const QString &filePath)
+{
+ CacheKey cacheKey = QDir::cleanPath(filePath + u"/.."_s);
+ if (auto entry = cache.find(cacheKey); entry != cache.end()) {
+ QQmlJS::Dom::DomItem env{ *entry };
+ return { env, env.field(QQmlJS::Dom::Fields::qmlFileWithPath).key(filePath) };
+ };
+
+ QStringList qmltypeDirs =
+ QStringList({ dataDirectory(), QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath) });
+
+ // This should be exactly the same options as qmlls uses in qqmlcodemodel.
+ // Otherwise, this test will not test the codepaths also used by qmlls and will be useless.
+ const QQmlJS::Dom::DomCreationOptions options = QQmlJS::Dom::DomCreationOptions{}
+ | QQmlJS::Dom::DomCreationOption::WithSemanticAnalysis
+ | QQmlJS::Dom::DomCreationOption::WithScriptExpressions
+ | QQmlJS::Dom::DomCreationOption::WithRecovery;
+
+ auto envPtr = QQmlJS::Dom::DomEnvironment::create(
+ qmltypeDirs, QQmlJS::Dom::DomEnvironment::Option::SingleThreaded, options);
+
+ QQmlJS::Dom::DomItem file;
+ QQmlJS::Dom::DomItem env(envPtr);
+ envPtr->loadFile(QQmlJS::Dom::FileToLoad::fromFileSystem(envPtr, filePath),
+ [&file](QQmlJS::Dom::Path, const QQmlJS::Dom::DomItem &,
+ const QQmlJS::Dom::DomItem &newIt) { file = newIt; });
+
+ envPtr->loadPendingDependencies();
+ envPtr->loadBuiltins();
+
+ cache[cacheKey] = envPtr;
+ return std::make_tuple(env, file);
+}
+
+void tst_qmlls_utils::textOffsetRowColumnConversions_data()
+{
+ QTest::addColumn<QString>("code");
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+ QTest::addColumn<qsizetype>("expectedOffset");
+ QTest::addColumn<QChar>("expectedChar");
+ // in case they differ from line and character, e.g. when accessing non-existing line or rows
+ // set to -1 when same as before
+ QTest::addColumn<int>("expectedLine");
+ QTest::addColumn<int>("expectedCharacter");
+
+ QTest::newRow("oneline") << u"Hello World!"_s << 0 << 6 << 6ll << QChar('W') << -1 << -1;
+ QTest::newRow("multi-line") << u"Hello World!\n How are you? \n Bye!\n"_s << 0 << 6 << 6ll
+ << QChar('W') << -1 << -1;
+ QTest::newRow("multi-line2") << u"Hello World!\n How are you? \n Bye!\n"_s << 1 << 5 << 18ll
+ << QChar('a') << -1 << -1;
+ QTest::newRow("multi-line3") << u"Hello World!\n How are you? \n Bye!\n"_s << 2 << 1 << 29ll
+ << QChar('B') << -1 << -1;
+
+ QTest::newRow("newlines") << u"A\nB\r\nC\n\r\nD\r\n\r"_s << 0 << 0 << 0ll << QChar('A') << -1
+ << -1;
+ QTest::newRow("newlines2") << u"A\nB\r\nC\n\r\nD\r\n\r"_s << 1 << 0 << 2ll << QChar('B') << -1
+ << -1;
+
+ // try to access '\r'
+ QTest::newRow("newlines3") << u"A\nB\r\nC\n\r\nD\r\n\r"_s << 1 << 1 << 3ll << QChar('\r') << -1
+ << -1;
+ // try to access '\n', should return the last character of the line (which is '\r' in this case)
+ QTest::newRow("newlines4") << u"A\nB\r\nC\n\r\nD\r\n\r"_s << 1 << 2 << 3ll << QChar('\r') << -1
+ << 1;
+ // try to access after the end of the line, should return the last character of the line (which
+ // is '\r' in this case)
+ QTest::newRow("afterLineEnd") << u"A\nB\r\nC\n\r\nD\r\n\r"_s << 1 << 42 << 3ll << QChar('\r')
+ << -1 << 1;
+
+ // try to access an inexisting column, seems to return the last character of the last line.
+ QTest::newRow("afterColumnEnd")
+ << u"A\nB\r\nC\n\r\nD\r\n\rAX"_s << 42 << 0 << 15ll << QChar('X') << 5 << 2;
+}
+
+void tst_qmlls_utils::textOffsetRowColumnConversions()
+{
+ QFETCH(QString, code);
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(qsizetype, expectedOffset);
+ QFETCH(QChar, expectedChar);
+ QFETCH(int, expectedLine);
+ QFETCH(int, expectedCharacter);
+
+ qsizetype offset = QQmlLSUtils::textOffsetFrom(code, line, character);
+
+ QCOMPARE(offset, expectedOffset);
+ if (offset < code.size())
+ QCOMPARE(code[offset], expectedChar);
+
+ auto [computedRow, computedColumn] = QQmlLSUtils::textRowAndColumnFrom(code, expectedOffset);
+ if (expectedLine == -1)
+ expectedLine = line;
+ if (expectedCharacter == -1)
+ expectedCharacter = character;
+
+ QCOMPARE(computedRow, expectedLine);
+ QCOMPARE(computedColumn, expectedCharacter);
+}
+
+void tst_qmlls_utils::findItemFromLocation_data()
+{
+ QTest::addColumn<QString>("filePath");
+ // keep in mind that line and character are starting at 1!
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+ // in case there are multiple items to be found (e.g. for a location between two objects), the
+ // item to be checked against
+ QTest::addColumn<int>("resultIndex");
+ QTest::addColumn<int>("expectedItemsCount");
+ QTest::addColumn<QQmlJS::Dom::DomType>("expectedType");
+ // set to -1 when unchanged from above line and character, starts at 1
+ QTest::addColumn<int>("expectedLine");
+ QTest::addColumn<int>("expectedCharacter");
+
+ const QString file1Qml = testFile(u"file1.qml"_s);
+
+ QTest::addRow("findIntProperty") << file1Qml << 9 << 18 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::PropertyDefinition
+ // start of the "property"-token of the "a" property
+ << -1 << positionAfterOneIndent;
+ QTest::addRow("findIntProperty2") << file1Qml << 9 << 10 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::PropertyDefinition
+ // start of the "property"-token of the "a" property
+ << -1 << positionAfterOneIndent;
+ QTest::addRow("findIntBinding")
+ << file1Qml << 30 << positionAfterOneIndent << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::ScriptIdentifierExpression
+ // start of the a identifier of the "a" binding
+ << -1 << positionAfterOneIndent;
+ QTest::addRow("findIntBinding2") << file1Qml << 30 << 8 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::ScriptLiteral
+ << -1 << 8;
+
+ QTest::addRow("colorBinding") << file1Qml << 39 << 13 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::ScriptIdentifierExpression << -1
+ << 2 * positionAfterOneIndent - 1;
+
+ QTest::addRow("findVarProperty") << file1Qml << 12 << 12 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::PropertyDefinition
+ // start of the "property"-token of the "d" property
+ << -1 << positionAfterOneIndent;
+ QTest::addRow("findVarBinding") << file1Qml << 31 << 8 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::ScriptLiteral << -1 << 8;
+ QTest::addRow("beforeEProperty")
+ << file1Qml << 13 << positionAfterOneIndent << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::PropertyDefinition
+ // start of the "property"-token of the "e" property
+ << -1 << -1;
+ QTest::addRow("onEProperty") << file1Qml << 13 << 24 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::PropertyDefinition
+ // start of the "property"-token of the "e" property
+ << -1 << positionAfterOneIndent;
+ QTest::addRow("afterEProperty") << file1Qml << 13 << 25 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::PropertyDefinition
+ // start of the "property"-token of the "e" property
+ << -1 << positionAfterOneIndent;
+
+ QTest::addRow("property-in-ic") << file1Qml << 28 << 38 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::PropertyDefinition << -1 << 26;
+
+ QTest::addRow("onCChild") << file1Qml << 16 << positionAfterOneIndent << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::ScriptIdentifierExpression << -1
+ << positionAfterOneIndent;
+
+ // check for off-by-one/overlapping items
+ QTest::addRow("closingBraceOfC")
+ << file1Qml << 16 << 19 << firstResult << outOfOne << QQmlJS::Dom::DomType::QmlObject
+ << -1 << positionAfterOneIndent;
+ QTest::addRow("beforeClosingBraceOfC")
+ << file1Qml << 16 << 18 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::ScriptIdentifierExpression << -1 << 12;
+ QTest::addRow("firstBetweenCandD")
+ << file1Qml << 16 << 20 << secondResult << outOfTwo << QQmlJS::Dom::DomType::QmlObject
+ << -1 << positionAfterOneIndent;
+ QTest::addRow("secondBetweenCandD")
+ << file1Qml << 16 << 20 << firstResult << outOfTwo
+ << QQmlJS::Dom::DomType::ScriptIdentifierExpression << -1 << -1;
+
+ QTest::addRow("afterD") << file1Qml << 16 << 21 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::ScriptIdentifierExpression << -1 << 20;
+
+ // check what happens between items (it should not crash)
+
+ QTest::addRow("onWhitespaceBeforeC")
+ << file1Qml << 16 << 1 << firstResult << outOfOne << QQmlJS::Dom::DomType::Map << 9
+ << positionAfterOneIndent;
+
+ QTest::addRow("onWhitespaceAfterC")
+ << file1Qml << 17 << 8 << firstResult << outOfOne << QQmlJS::Dom::DomType::QmlObject
+ << -1 << positionAfterOneIndent;
+
+ QTest::addRow("onWhitespaceBetweenCAndD") << file1Qml << 17 << 23 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::Map << 16 << 8;
+ QTest::addRow("onWhitespaceBetweenCAndD2") << file1Qml << 17 << 24 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::Map << 16 << 8;
+
+ QTest::addRow("ic") << file1Qml << 15 << 5 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::QmlComponent << -1 << 5;
+ QTest::addRow("ic2") << file1Qml << 15 << 20 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::ScriptIdentifierExpression << -1 << 18;
+ QTest::addRow("ic3") << file1Qml << 15 << 33 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::ScriptIdentifierExpression << -1 << 29;
+
+ QTest::addRow("function") << file1Qml << 33 << 5 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::MethodInfo << -1 << positionAfterOneIndent;
+ QTest::addRow("function-parameter")
+ << file1Qml << 33 << 20 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::ScriptIdentifierExpression << -1 << 19;
+ // The return type of a function has no own DomItem. Instead, the return type of a function
+ // is saved into the MethodInfo.
+ QTest::addRow("function-return")
+ << file1Qml << 33 << 41 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::ScriptIdentifierExpression << -1 << 41;
+ QTest::addRow("function2") << file1Qml << 36 << 17 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::MethodInfo << -1
+ << positionAfterOneIndent;
+
+ // check rectangle property
+ QTest::addRow("rectangle-property")
+ << file1Qml << 44 << 31 << firstResult << outOfOne
+ << QQmlJS::Dom::DomType::ScriptIdentifierExpression << -1 << 29;
+}
+
+void tst_qmlls_utils::findItemFromLocation()
+{
+ QFETCH(QString, filePath);
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(int, resultIndex);
+ QFETCH(int, expectedItemsCount);
+ QFETCH(QQmlJS::Dom::DomType, expectedType);
+ QFETCH(int, expectedLine);
+ QFETCH(int, expectedCharacter);
+
+ if (expectedLine == -1)
+ expectedLine = line;
+ if (expectedCharacter == -1)
+ expectedCharacter = character;
+
+ // they all start at 1.
+ Q_ASSERT(line > 0);
+ Q_ASSERT(character > 0);
+ Q_ASSERT(expectedLine > 0);
+ Q_ASSERT(expectedCharacter > 0);
+
+ auto [env, file] = createEnvironmentAndLoadFile(filePath);
+
+ auto locations = QQmlLSUtils::itemsFromTextLocation(
+ file.field(QQmlJS::Dom::Fields::currentItem), line - 1, character - 1);
+
+ QVERIFY(resultIndex < locations.size());
+ QCOMPARE(locations.size(), expectedItemsCount);
+
+ QQmlJS::Dom::DomItem itemToTest = locations[resultIndex].domItem;
+ // ask for the type in the args
+ if constexpr (enable_debug_output) {
+ if (itemToTest.internalKind() != expectedType) {
+ qDebug() << itemToTest.internalKindStr() << " has not the expected kind "
+ << expectedType << " for item " << itemToTest.toString();
+ }
+ }
+ QCOMPARE(itemToTest.internalKind(), expectedType);
+
+ QQmlJS::Dom::FileLocations::Tree locationToTest = locations[resultIndex].fileLocation;
+ QCOMPARE(locationToTest->info().fullRegion.startLine, quint32(expectedLine));
+ QCOMPARE(locationToTest->info().fullRegion.startColumn, quint32(expectedCharacter));
+}
+
+void tst_qmlls_utils::findTypeDefinitionFromLocation_data()
+{
+ QTest::addColumn<QString>("filePath");
+ // keep in mind that line and character are starting at 1!
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+ // in case there are multiple items to be found (e.g. for a location between two objects), the
+ // item to be checked against
+ QTest::addColumn<int>("resultIndex");
+ QTest::addColumn<int>("expectedItemsCount");
+ QTest::addColumn<QString>("expectedFilePath");
+ // set to -1 when unchanged from above line and character. 0-based.
+ QTest::addColumn<int>("expectedLine");
+ QTest::addColumn<int>("expectedCharacter");
+
+ const QString file1Qml = testFile(u"file1.qml"_s);
+ const QString TypeQml = testFile(u"Type.qml"_s);
+ // pass this as file when no result is expected, e.g. for type definition of "var".
+
+ QTest::addRow("onCProperty") << file1Qml << 11 << 16 << firstResult << outOfOne << file1Qml << 7
+ << positionAfterOneIndent;
+
+ QTest::addRow("onCProperty2") << file1Qml << 28 << 37 << firstResult << outOfOne << file1Qml
+ << 7 << positionAfterOneIndent;
+
+ QTest::addRow("onCProperty3") << file1Qml << 28 << 35 << firstResult << outOfOne << file1Qml
+ << 7 << positionAfterOneIndent;
+
+ QTest::addRow("onCBinding") << file1Qml << 46 << 8 << firstResult << outOfOne << file1Qml << 7
+ << positionAfterOneIndent;
+
+ QTest::addRow("onDefaultBinding") << file1Qml << 16 << positionAfterOneIndent << firstResult
+ << outOfOne << file1Qml << 7 << positionAfterOneIndent;
+
+ QTest::addRow("onDefaultBindingId")
+ << file1Qml << 16 << 28 << firstResult << outOfOne << file1Qml << 16 << 20;
+
+ QTest::addRow("findIntProperty") << file1Qml << 9 << 18 << firstResult << outOfOne << file1Qml
+ << -1 << positionAfterOneIndent;
+ QTest::addRow("colorBinding") << file1Qml << 39 << 8 << firstResult << outOfOne << file1Qml
+ << -1 << positionAfterOneIndent;
+
+ // check what happens between items (it should not crash)
+
+ QTest::addRow("onWhitespaceBeforeC")
+ << file1Qml << 16 << 1 << firstResult << outOfOne << noResultExpected << -1 << -1;
+
+ QTest::addRow("onWhitespaceAfterC")
+ << file1Qml << 17 << 23 << firstResult << outOfOne << noResultExpected << -1 << -1;
+
+ QTest::addRow("onWhitespaceBetweenCAndD")
+ << file1Qml << 17 << 24 << firstResult << outOfOne << noResultExpected << -1 << -1;
+
+ QTest::addRow("ic") << file1Qml << 15 << 15 << firstResult << outOfOne << file1Qml << 15 << 15;
+ QTest::addRow("icBase") << file1Qml << 15 << 20 << firstResult << outOfOne
+ << u"TODO: file location for C++ defined types?"_s << -1 << -1;
+ QTest::addRow("ic3") << file1Qml << 15 << 33 << firstResult << outOfOne << file1Qml << -1 << 18;
+
+ // TODO: type definition of function = type definition of return type?
+ // if not, this might need fixing:
+ // currently, asking the type definition of the "function" keyword returns
+ // the type definitin of the return type (when available).
+ QTest::addRow("function-keyword") << file1Qml << 33 << 5 << firstResult << outOfOne << file1Qml
+ << 7 << positionAfterOneIndent;
+ QTest::addRow("function-parameter-builtin")
+ << file1Qml << 33 << 20 << firstResult << outOfOne << file1Qml << -1 << -1;
+ QTest::addRow("function-parameter-item") << file1Qml << 33 << 36 << firstResult << outOfOne
+ << file1Qml << 7 << positionAfterOneIndent;
+
+ QTest::addRow("function-return") << file1Qml << 33 << 41 << firstResult << outOfOne << file1Qml
+ << 7 << positionAfterOneIndent;
+
+ QTest::addRow("void-function")
+ << file1Qml << 36 << 17 << firstResult << outOfOne << noResultExpected << -1 << -1;
+
+ QTest::addRow("rectangle-property") << file1Qml << 44 << 31 << firstResult << outOfOne
+ << "TODO: c++ type location" << -1 << -1;
+
+ QTest::addRow("functionParameterICUsage")
+ << file1Qml << 34 << 16 << firstResult << outOfOne << file1Qml << 7 << 15;
+
+ QTest::addRow("ICBindingUsage")
+ << file1Qml << 47 << 21 << firstResult << outOfOne << file1Qml << 7 << 15;
+ QTest::addRow("ICBindingUsage2")
+ << file1Qml << 49 << 11 << firstResult << outOfOne << file1Qml << 7 << 15;
+ QTest::addRow("ICBindingUsage3")
+ << file1Qml << 52 << 17 << firstResult << outOfOne << file1Qml << 7 << 15;
+}
+
+void tst_qmlls_utils::findTypeDefinitionFromLocation()
+{
+ QFETCH(QString, filePath);
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(int, resultIndex);
+ QFETCH(int, expectedItemsCount);
+ QFETCH(QString, expectedFilePath);
+ QFETCH(int, expectedLine);
+ QFETCH(int, expectedCharacter);
+
+ if (expectedLine == -1)
+ expectedLine = line;
+ if (expectedCharacter == -1)
+ expectedCharacter = character;
+
+ // they all start at 1.
+ Q_ASSERT(line > 0);
+ Q_ASSERT(character > 0);
+ Q_ASSERT(expectedLine > 0);
+ Q_ASSERT(expectedCharacter > 0);
+
+ auto [env, file] = createEnvironmentAndLoadFile(filePath);
+
+ auto locations = QQmlLSUtils::itemsFromTextLocation(
+ file.field(QQmlJS::Dom::Fields::currentItem), line - 1, character - 1);
+
+ QCOMPARE(locations.size(), expectedItemsCount);
+
+ auto base = QQmlLSUtils::findTypeDefinitionOf(locations[resultIndex].domItem);
+
+ // if expectedFilePath is empty, we probably just want to make sure that it does
+ // not crash
+ if (expectedFilePath == noResultExpected) {
+ QVERIFY(!base);
+ return;
+ }
+
+ QEXPECT_FAIL("findIntProperty", "Builtins not supported yet", Abort);
+ QEXPECT_FAIL("function-parameter-builtin", "Base types defined in C++ are not supported yet",
+ Abort);
+ QEXPECT_FAIL("colorBinding", "Types from C++ bases not supported yet", Abort);
+ QEXPECT_FAIL("rectangle-property", "Types from C++ bases not supported yet", Abort);
+ QEXPECT_FAIL("icBase", "Base types defined in C++ are not supported yet", Abort);
+ QVERIFY(base);
+
+ auto fileObject =
+ locations[resultIndex].domItem.goToFile(base->filename).as<QQmlJS::Dom::QmlFile>();
+
+ // print some debug message when failing, instead of using QVERIFY2
+ // (printing the type every time takes a lot of time).
+ if constexpr (enable_debug_output) {
+ if (!fileObject)
+ qDebug() << "Could not find the file" << base->filename << "in the Dom.";
+ }
+
+ QVERIFY(fileObject);
+ QCOMPARE(base->filename, expectedFilePath);
+ QCOMPARE(fileObject->canonicalFilePath(), expectedFilePath);
+
+ QCOMPARE(base->sourceLocation.startLine, quint32(expectedLine));
+ QCOMPARE(base->sourceLocation.startColumn, quint32(expectedCharacter));
+}
+
+void tst_qmlls_utils::findLocationOfItem_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+ QTest::addColumn<int>("expectedLine");
+ QTest::addColumn<int>("expectedCharacter");
+
+ const QString file1Qml = testFile(u"file1.qml"_s);
+
+ QTest::addRow("root-element") << file1Qml << 6 << 2 << -1 << 1;
+
+ QTest::addRow("property-a") << file1Qml << 9 << 18 << -1 << positionAfterOneIndent;
+ QTest::addRow("property-a2") << file1Qml << 9 << 10 << -1 << positionAfterOneIndent;
+ QTest::addRow("nested-C") << file1Qml << 20 << 9 << -1 << -1;
+ QTest::addRow("nested-C2") << file1Qml << 23 << 13 << -1 << -1;
+ QTest::addRow("D") << file1Qml << 17 << 33 << -1 << 32;
+ QTest::addRow("property-d-var-type") << file1Qml << 12 << 15 << -1 << 14;
+
+ QTest::addRow("import") << file1Qml << 4 << 6 << -1 << 1;
+}
+
+void tst_qmlls_utils::findLocationOfItem()
+{
+ QFETCH(QString, filePath);
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(int, expectedLine);
+ QFETCH(int, expectedCharacter);
+
+ if (expectedLine == -1)
+ expectedLine = line;
+ if (expectedCharacter == -1)
+ expectedCharacter = character;
+
+ // they all start at 1.
+ Q_ASSERT(line > 0);
+ Q_ASSERT(character > 0);
+ Q_ASSERT(expectedLine > 0);
+ Q_ASSERT(expectedCharacter > 0);
+
+ auto [env, file] = createEnvironmentAndLoadFile(filePath);
+
+ // grab item using already tested QQmlLSUtils::findLastItemsContaining
+ auto locations = QQmlLSUtils::itemsFromTextLocation(
+ file.field(QQmlJS::Dom::Fields::currentItem), line - 1, character - 1);
+ QCOMPARE(locations.size(), 1);
+
+ // once the item is grabbed, make sure its line/character position can be obtained back
+ auto t = QQmlJS::Dom::FileLocations::treeOf(locations.front().domItem);
+
+ QCOMPARE(t->info().fullRegion.startLine, quint32(expectedLine));
+ QCOMPARE(t->info().fullRegion.startColumn, quint32(expectedCharacter));
+}
+
+void tst_qmlls_utils::findBaseObject_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+ // to avoid mixing up the types (because they are all called Item or QQuickItem eitherway)
+ // mark them with properties and detect right types by their marker property,
+ // usually called (in<Filename>DotQml or in<Inline component Name>)
+ QTest::addColumn<QSet<QString>>("expectedPropertyName");
+ // because types inherit properties, make sure that derived type properties are not in the base
+ // type, to correctly detect mixups between types and their base types
+ QTest::addColumn<QSet<QString>>("unExpectedPropertyName");
+
+ // (non) Expected Properties Names = ePN (nEPN)
+ // marker properties for the root object in BaseType.qml
+ QSet<QString> ePNBaseType;
+ ePNBaseType << u"inBaseTypeDotQml"_s;
+ QSet<QString> nEPNBaseType;
+ nEPNBaseType << u"inTypeDotQml"_s;
+
+ // marker properties for the root object in Type.qml
+ QSet<QString> ePNType;
+ ePNType << u"inBaseTypeDotQml"_s << u"inTypeDotQml"_s;
+ QSet<QString> nEPNType;
+
+ // marker properties for QQuickItem (e.g. the base of "Item")
+ QSet<QString> ePNQQuickItem;
+ QSet<QString> nEPNQQuickItem;
+ nEPNQQuickItem << u"inBaseTypeDotQml"_s << u"inTypeDotQml"_s;
+
+ // marker properties for MyInlineComponent
+ QSet<QString> ePNMyInlineComponent;
+ QSet<QString> nEPNMyInlineComponent;
+ ePNMyInlineComponent << u"inBaseTypeDotQml"_s << u"inTypeDotQml"_s << u"inMyInlineComponent"_s;
+
+ // marker properties for MyNestedInlineComponent
+ const QSet<QString> ePNMyNestedInlineComponent{ u"inMyNestedInlineComponent"_s };
+ const QSet<QString> nEPNMyNestedInlineComponent{ u"inBaseTypeDotQml"_s, u"inTypeDotQml"_s,
+ u"inMyInlineComponent"_s };
+
+ // marker properties for MyBaseInlineComponent
+ const QSet<QString> ePNMyBaseInlineComponent{ u"inBaseTypeDotQml"_s };
+ const QSet<QString> nEPNMyBaseInlineComponent{ u"inTypeDotQml"_s, u"inMyInlineComponent"_s };
+
+ const int rootElementDefLine = 6;
+ QTest::addRow("root-element") << testFile(u"Type.qml"_s) << rootElementDefLine << 5
+ << ePNQQuickItem << nEPNQQuickItem;
+ QTest::addRow("root-element-from-id") << testFile(u"Type.qml"_s) << rootElementDefLine + 1 << 12
+ << ePNBaseType << nEPNBaseType;
+
+ const int myInlineComponentDefLine = 10;
+ // on the component name: go to BaseType
+ QTest::addRow("ic-name") << testFile(u"Type.qml"_s) << myInlineComponentDefLine << 26
+ << ePNBaseType << nEPNBaseType;
+ // on the "BaseType" type: go to QQuickitem (base type of BaseType).
+ QTest::addRow("ic-basetypename") << testFile(u"Type.qml"_s) << myInlineComponentDefLine << 37
+ << ePNQQuickItem << nEPNQQuickItem;
+ QTest::addRow("ic-from-id") << testFile(u"Type.qml"_s) << myInlineComponentDefLine + 1 << 19
+ << ePNBaseType << nEPNBaseType;
+
+ const int inlineTypeDefLine = 15;
+ QTest::addRow("inline") << testFile(u"Type.qml"_s) << inlineTypeDefLine << 23 << ePNQQuickItem
+ << nEPNQQuickItem;
+ QTest::addRow("inline2") << testFile(u"Type.qml"_s) << inlineTypeDefLine << 38 << ePNQQuickItem
+ << nEPNQQuickItem;
+ QTest::addRow("inline3") << testFile(u"Type.qml"_s) << inlineTypeDefLine << 15 << ePNQQuickItem
+ << nEPNQQuickItem;
+ QTest::addRow("inline-from-id") << testFile(u"Type.qml"_s) << inlineTypeDefLine + 1 << 24
+ << ePNBaseType << nEPNBaseType;
+
+ const int inlineIcDefLine = 23;
+ QTest::addRow("inline-ic") << testFile(u"Type.qml"_s) << inlineIcDefLine << 38
+ << ePNMyBaseInlineComponent << nEPNMyBaseInlineComponent;
+ QTest::addRow("inline-ic-from-id") << testFile(u"Type.qml"_s) << inlineIcDefLine + 1 << 28
+ << ePNMyBaseInlineComponent << nEPNMyBaseInlineComponent;
+
+ const int inlineNestedIcDefLine = 27;
+ QTest::addRow("inline-ic2") << testFile(u"Type.qml"_s) << inlineNestedIcDefLine << 46
+ << ePNMyNestedInlineComponent << nEPNMyNestedInlineComponent;
+ QTest::addRow("inline-ic2-from-id")
+ << testFile(u"Type.qml"_s) << inlineNestedIcDefLine + 1 << 23
+ << ePNMyNestedInlineComponent << nEPNMyNestedInlineComponent;
+}
+
+void tst_qmlls_utils::findBaseObject()
+{
+ const QByteArray failOnInlineComponentsMessage =
+ "The Dom cannot resolve inline components from the basetype yet.";
+
+ QFETCH(QString, filePath);
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(QSet<QString>, expectedPropertyName);
+ QFETCH(QSet<QString>, unExpectedPropertyName);
+
+ // they all start at 1.
+ Q_ASSERT(line > 0);
+ Q_ASSERT(character > 0);
+
+ auto [env, file] = createEnvironmentAndLoadFile(filePath);
+
+ // grab item using already tested QQmlLSUtils::findLastItemsContaining
+ auto locations = QQmlLSUtils::itemsFromTextLocation(
+ file.field(QQmlJS::Dom::Fields::currentItem), line - 1, character - 1);
+ if constexpr (enable_debug_output) {
+ if (locations.size() > 1) {
+ for (auto &x : locations)
+ qDebug() << x.domItem.toString();
+ }
+ }
+ QCOMPARE(locations.size(), 1);
+
+ auto typeLocation = QQmlLSUtils::findTypeDefinitionOf(locations.front().domItem);
+ QEXPECT_FAIL("inline-ic", failOnInlineComponentsMessage, Abort);
+ QEXPECT_FAIL("inline-ic2", failOnInlineComponentsMessage, Abort);
+ QVERIFY(typeLocation);
+ QQmlJS::Dom::DomItem type = QQmlLSUtils::sourceLocationToDomItem(
+ locations.front().domItem.goToFile(typeLocation->filename),
+ typeLocation->sourceLocation);
+ auto base = QQmlLSUtils::baseObject(type);
+
+ if constexpr (enable_debug_output) {
+ if (!base)
+ qDebug() << u"Could not find the base of type "_s << type << u" from item:\n"_s
+ << locations.front().domItem.toString();
+ }
+
+ QEXPECT_FAIL("inline-ic-from-id", failOnInlineComponentsMessage, Abort);
+ QEXPECT_FAIL("inline-ic2-from-id", failOnInlineComponentsMessage, Abort);
+ QVERIFY(base);
+
+ const QSet<QString> propertyDefs = base.field(QQmlJS::Dom::Fields::propertyDefs).keys();
+ expectedPropertyName.subtract(propertyDefs);
+ QVERIFY2(expectedPropertyName.empty(),
+ u"Incorrect baseType found: it is missing following marker properties: "_s
+ .append(printSet(expectedPropertyName))
+ .toLatin1());
+ unExpectedPropertyName.intersect(propertyDefs);
+ QVERIFY2(unExpectedPropertyName.empty(),
+ u"Incorrect baseType found: it has an unexpected marker properties: "_s
+ .append(printSet(unExpectedPropertyName))
+ .toLatin1());
+}
+
+/*! \internal
+ \brief Wrapper for findUsages data.
+*/
+struct UsageData
+{
+ QString testFileName;
+ QQmlLSUtils::Usages expectedUsages;
+};
+
+void tst_qmlls_utils::findUsages_data()
+{
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+ QTest::addColumn<UsageData>("data");
+
+ const auto readFileContent = [](const QString &testFileName) {
+ QFile file(testFileName);
+ if (file.open(QIODeviceBase::ReadOnly))
+ return QString::fromUtf8(file.readAll());
+ return QString{};
+ };
+
+ const auto makeUsages = [](const QString &fileName, QList<QQmlLSUtils::Location> &locations) {
+ UsageData data;
+ std::sort(locations.begin(), locations.end());
+ data.expectedUsages = { locations, {} };
+ data.testFileName = fileName;
+ return data;
+ };
+
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ const auto testFileName = testFile("findUsages/jsIdentifier/jsIdentifier.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ {
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 13,
+ strlen("sum"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 13,
+ strlen("sum"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 19,
+ strlen("sum"));
+ const auto sumUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findSumFromDeclaration") << 8 << 13 << sumUsages;
+ QTest::addRow("findSumFromUsage") << 10 << 20 << sumUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 17,
+ strlen("i"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 24,
+ strlen("i"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 32,
+ strlen("i"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 36,
+ strlen("i"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 25,
+ strlen("i"));
+ const auto iUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findIFromDeclaration") << 9 << 17 << iUsages;
+ QTest::addRow("findIFromUsage") << 9 << 24 << iUsages;
+ QTest::addRow("findIFromUsage2") << 10 << 25 << iUsages;
+ }
+ }
+ {
+ const auto testFileName = testFile("findUsages/property/property.qml");
+ const auto otherFile = testFile("findUsages/property/PropertyFromAnotherFile.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ const auto otherFileContent = readFileContent(otherFile);
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 18,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 13, 13,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 13, 29,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 20, 9,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 21, 9,
+ strlen("helloPropertyChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 5,
+ strlen("onHelloPropertyChanged"));
+ const auto helloPropertyUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findPropertyFromDeclaration") << 8 << 18 << helloPropertyUsages;
+ QTest::addRow("findPropertyFromUsage") << 13 << 13 << helloPropertyUsages;
+ QTest::addRow("findPropertyFromUsage2") << 13 << 29 << helloPropertyUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 36, 20,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 38, 25,
+ strlen("helloProperty"));
+ const auto subItemHelloPropertyUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findPropertyFromDeclarationInSubItem") << 38 << 25 << subItemHelloPropertyUsages;
+ QTest::addRow("findPropertyFromUsageInSubItem") << 36 << 20 << subItemHelloPropertyUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 27, 22,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 29, 20,
+ strlen("helloProperty"));
+ const auto ICHelloPropertyUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findPropertyFromDeclarationInIC") << 27 << 22 << ICHelloPropertyUsages;
+ QTest::addRow("findPropertyFromUsageInIC") << 29 << 20 << ICHelloPropertyUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(otherFile, otherFileContent, 4, 18,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 42, 9,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 44, 20,
+ strlen("helloProperty"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 46, 9,
+ strlen("OnHelloPropertyChanged"));
+ const auto helloPropertyUsages = makeUsages(testFileName, expectedUsages);
+
+ QTest::addRow("findPropertyFromOtherFile") << 42 << 13 << helloPropertyUsages;
+ }
+ }
+ {
+ const auto testFileName = testFile("findUsages/propertyInNested/propertyInNested.qml");
+ const auto testFileContent = readFileContent(testFileName);
+
+ const auto componentFileName =
+ testFile("findUsages/propertyInNested/NestedComponentInFile.qml");
+ const auto componentFileContent = readFileContent(componentFileName);
+
+ const auto componentFileName3 =
+ testFile("findUsages/propertyInNested/NestedComponentInFile3.qml");
+ const auto componentFileContent3 = readFileContent(componentFileName);
+
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 7, 18,
+ strlen("p2"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 33, 31,
+ strlen("p2"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 34, 37,
+ strlen("p2"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 35, 43,
+ strlen("p2"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 36, 49,
+ strlen("p2"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 42, 26,
+ strlen("p2"));
+ const auto p2Usages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findPropertyFromDeclaration2") << 7 << 18 << p2Usages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 29, 13,
+ strlen("myNested"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 32, 17,
+ strlen("myNested"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 33, 17,
+ strlen("myNested"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 34, 17,
+ strlen("myNested"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 35, 17,
+ strlen("myNested"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 36, 17,
+ strlen("myNested"));
+ const auto nestedUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findIdFromUsage") << 36 << 20 << nestedUsages;
+ QTest::addRow("findIdFromDefinition") << 29 << 17 << nestedUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 14, 35,
+ strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 32, 32,
+ strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 35, 32,
+ strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 36, 32,
+ strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 16, 9,
+ strlen("inner"));
+ const auto nestedComponent3Usages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findPropertyFromUsageInFieldMemberExpression")
+ << 36 << 34 << nestedComponent3Usages;
+
+ QTest::addRow("findFieldMemberExpressionUsageFromPropertyDefinition")
+ << 14 << 38 << nestedComponent3Usages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(componentFileName, componentFileContent,
+ 4, 37, strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 50, 32,
+ strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 52, 32,
+ strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 53, 32,
+ strlen("inner"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 54, 32,
+ strlen("inner"));
+ const auto nestedComponent3Usages = makeUsages(testFileName, expectedUsages);
+ const auto nestedComponent3UsagesFromOtherFile =
+ makeUsages(componentFileName, expectedUsages);
+ QTest::addRow("findPropertyFromUsageInFieldMemberExpressionFromOtherFile")
+ << 50 << 33 << nestedComponent3Usages;
+
+ QTest::addRow("findFieldMemberExpressionUsageFromPropertyDefinitionFromOtherFile")
+ << 4 << 38 << nestedComponent3UsagesFromOtherFile;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 35, 38,
+ strlen("p2"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 20, 22,
+ strlen("p2"));
+ const auto nestedComponent3P2Usages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findProperty2FromUsageInFieldMemberExpression")
+ << 35 << 39 << nestedComponent3P2Usages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(componentFileName3, componentFileContent3,
+ 5, 18, strlen("p2"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 53, 44,
+ strlen("p2"));
+ const auto nestedComponent3P2Usages = makeUsages(testFileName, expectedUsages);
+ const auto nestedComponent3P2UsagesFromOtherFile = makeUsages(componentFileName3, expectedUsages);
+ QTest::addRow("findProperty2FromUsageInFieldMemberExpressionInOtherFile")
+ << 53 << 44 << nestedComponent3P2Usages;
+ QTest::addRow("findProperty2FromUsageInDefinitionInOtherFile")
+ << 5 << 19 << nestedComponent3P2UsagesFromOtherFile;
+ }
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ const auto testFileName = testFile("findUsages/idUsages/idUsages.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 7, 9,
+ strlen("rootId"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 11, 17,
+ strlen("rootId"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 12, 20,
+ strlen("rootId"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 17, 9,
+ strlen("rootId"));
+ const auto rootIdUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findIdFromUsageInChild") << 12 << 20 << rootIdUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ const auto testFileName = testFile("findUsages/recursive/recursive.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 14,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 24,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 34,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 51,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 68,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 12, 20,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 15, 34,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 19, 27,
+ strlen("recursive"));
+ const auto recursiveUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findFunctionUsage") << 10 << 30 << recursiveUsages;
+ QTest::addRow("findFunctionUsage2") << 12 << 24 << recursiveUsages;
+ QTest::addRow("findQualifiedFunctionUsage") << 19 << 31 << recursiveUsages;
+ QTest::addRow("findFunctionUsageFromDefinition") << 8 << 17 << recursiveUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ const auto testFileName = testFile("findUsages/recursive/recursive.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ const auto otherFileName = testFile("findUsages/recursive/RecursiveInOtherFile.qml");
+ const auto otherFileContent = readFileContent(otherFileName);
+
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 27, 61,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 4, 14,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 6, 24,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 6, 34,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 6, 51,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 6, 68,
+ strlen("recursive"));
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 8, 20,
+ strlen("recursive"));
+
+ const auto recursiveUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findFunctionUsageFromOtherFile") << 27 << 64 << recursiveUsages;
+ const auto recursiveUsagesFromOtherFile = makeUsages(otherFileName, expectedUsages);
+ QTest::addRow("findFunctionUsageFromSameFile") << 6 << 39 << recursiveUsagesFromOtherFile;
+ QTest::addRow("findFunctionUsageFromDefinitionInOtherFile")
+ << 4 << 14 << recursiveUsagesFromOtherFile;
+ }
+ {
+ const auto testFileName = testFile("findUsages/signalsAndHandlers/signalsAndHandlers.qml");
+ const auto testFileContent = readFileContent(testFileName);
+
+ const auto otherFileName = testFile("findUsages/signalsAndHandlers/widthChangedInAnotherFile.qml");
+ const auto otherFileContent = readFileContent(otherFileName);
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 12,
+ strlen("helloSignal"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 11, 9,
+ strlen("helloSignal"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 13, 13,
+ strlen("helloSignal"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 17, 17,
+ strlen("helloSignal"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 21, 9,
+ strlen("helloSignal"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 39, 5,
+ strlen("onHelloSignal"));
+ const auto helloSignalUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findQmlSignalUsageFromDefinition") << 8 << 17 << helloSignalUsages;
+ QTest::addRow("findQmlSignalUsageFromUsage") << 13 << 17 << helloSignalUsages;
+ QTest::addRow("findQmlSignalUsageFromHandler") << 39 << 11 << helloSignalUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 5, 5,
+ strlen("onWidthChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 13,
+ strlen("widthChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 27, 17,
+ strlen("widthChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 28, 20,
+ strlen("widthChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 34, 20,
+ strlen("widthChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 33, 13,
+ strlen("widthChanged"));
+ const auto widthChangedUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findCppSignalUsageFromUsage") << 27 << 23 << widthChangedUsages;
+ QTest::addRow("findCppSignalUsageFromQualifiedUsage") << 28 << 23 << widthChangedUsages;
+ QTest::addRow("findCppSignalUsageFromQualifiedUsage2") << 34 << 24 << widthChangedUsages;
+ }
+ }
+ {
+ const auto testFileName = testFile("findUsages/binding/binding.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 18,
+ strlen("helloPropertyBinding"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 5,
+ strlen("helloPropertyBinding"));
+ const auto helloPropertyBindingUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findBindingUsagesFromDefinition") << 9 << 21 << helloPropertyBindingUsages;
+ QTest::addRow("findBindingUsagesFromBinding") << 10 << 19 << helloPropertyBindingUsages;
+ }
+ {
+ const auto testFileName = testFile("findUsages/signalsAndHandlers/signalAndHandlers2.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 7, 14,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 20,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 14, 29,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 15, 24,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 17,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 24, 24,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 25, 21,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 33, 19,
+ strlen("myHelloHandler"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 42, 29,
+ strlen("myHelloHandler"));
+ const auto myHelloHandlerUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findJSMethodFromUsageInBinding") << 8 << 27 << myHelloHandlerUsages;
+ QTest::addRow("findJSMethodFromDefinition") << 7 << 22 << myHelloHandlerUsages;
+ QTest::addRow("findJSMethodFromDefinition2") << 7 << 9 << myHelloHandlerUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 13, 18,
+ strlen("checkHandlers"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 14, 5,
+ strlen("onCheckHandlersChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 17, 9,
+ strlen("checkHandlersChanged"));
+ const auto checkHandlersUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findQmlPropertyHandlerFromDefinition") << 13 << 18 << checkHandlersUsages;
+ QTest::addRow("findQmlPropertyHandlerFromHandler") << 14 << 5 << checkHandlersUsages;
+ QTest::addRow("findQmlPropertyHandlerFromSignalCall") << 17 << 9 << checkHandlersUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 15, 5,
+ strlen("onChildrenChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 18, 9,
+ strlen("childrenChanged"));
+ const auto checkCppHandlersUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findCppPropertyHandlerFromHandler") << 15 << 5 << checkCppHandlersUsages;
+ QTest::addRow("findCppPropertyHandlerFromSignalCall") << 18 << 9 << checkCppHandlersUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 20, 18,
+ strlen("_"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 5,
+ strlen("on_Changed"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 27, 9,
+ strlen("_Changed"));
+ const auto checkHandlersUsages2 = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findQmlPropertyHandler2FromDefinition") << 20 << 18 << checkHandlersUsages2;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 21, 18,
+ strlen("______42"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 24, 5,
+ strlen("on______42Changed"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 28, 9,
+ strlen("______42Changed"));
+ const auto checkHandlersUsages3 = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findQmlPropertyHandler3FromDefinition") << 21 << 18 << checkHandlersUsages3;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 22, 18,
+ strlen("_123a"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 25, 5,
+ strlen("on_123AChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 29, 9,
+ strlen("_123aChanged"));
+ const auto checkHandlersUsages4 = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findQmlPropertyHandler4FromDefinition") << 22 << 18 << checkHandlersUsages4;
+ }
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ const auto testFileName = testFile("findUsages/connections/connections.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 9,
+ strlen("onClicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 17, 23,
+ strlen("clicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 33, 15,
+ strlen("clicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 16, 22,
+ strlen("onClicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 34, 15,
+ strlen("clicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 18, 23,
+ strlen("clicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 28, 9,
+ strlen("onClicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 35, 15,
+ strlen("clicked"));
+ const auto signalInConnection = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findSignalsInConnectionFromSignal") << 33 << 15 << signalInConnection;
+ QTest::addRow("findSignalsInConnectionFromHandler") << 9 << 9 << signalInConnection;
+ QTest::addRow("findSignalsInConnectionFromFunction") << 16 << 22 << signalInConnection;
+ }
+ {
+ const auto testFileName =
+ testFile("findUsages/parametersAndDeconstruction/parametersAndDeconstruction.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 30,
+ strlen("a"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 16,
+ strlen("a"));
+ const auto aParamUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findMethodParameterA") << 9 << 16 << aParamUsages;
+ QTest::addRow("findMethodParameterAFromUsage") << 8 << 30 << aParamUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 50,
+ strlen("x"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 28,
+ strlen("x"));
+ const auto xParamUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findMethodParameterXDeconstructed") << 8 << 50 << xParamUsages;
+ QTest::addRow("findMethodParameterXDeconstructedFromUsage") << 9 << 28 << xParamUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 53,
+ strlen("y"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 32,
+ strlen("y"));
+ const auto yParamUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findMethodParameterYDeconstructed") << 8 << 53 << yParamUsages;
+ QTest::addRow("findMethodParameterYDeconstructedFromUsage") << 9 << 32 << yParamUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 59,
+ strlen("z"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 36,
+ strlen("z"));
+ const auto zParamUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findMethodParameterZDeconstructed") << 8 << 59 << zParamUsages;
+ QTest::addRow("findMethodParameterZDeconstructedFromUsage") << 9 << 36 << zParamUsages;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 13, 14,
+ strlen("a"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 14, 17,
+ strlen("a"));
+ const auto deconstructedAUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("deconstructed") << 14 << 17 << deconstructedAUsages;
+ QTest::addRow("deconstructedFromDefinition") << 13 << 14 << deconstructedAUsages;
+ }
+ }
+ {
+ const auto testFileName = testFile("findUsages/groupPropertyUsage/groupPropertyUsage.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ const auto otherFileName = testFile("findUsages/groupPropertyUsage/fontFamilyUsage.qml");
+ const auto otherFileContent = readFileContent(otherFileName);
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 5, 34,
+ strlen("family"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 14, 17,
+ strlen("family"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 35,
+ strlen("family"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 10,
+ strlen("family"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 33, 48,
+ strlen("family"));
+ const auto groupPropertyUsages1 = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("groupPropertyUsages1") << 14 << 17 << groupPropertyUsages1;
+ const auto groupPropertyUsages1FromOtherFile =
+ makeUsages(otherFileName, expectedUsages);
+ QTest::addRow("groupPropertyUsages1FromOtherFile")
+ << 5 << 37 << groupPropertyUsages1FromOtherFile;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 5,
+ strlen("font"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 24, 5,
+ strlen("font"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 12, 13,
+ strlen("font"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 30,
+ strlen("font"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 32, 41,
+ strlen("font"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 33, 43,
+ strlen("font"));
+ const auto groupPropertyUsages2 = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("groupPropertyUsages2") << 23 << 5 << groupPropertyUsages2;
+ }
+ }
+ {
+ const auto testFileName =
+ testFile("findUsages/attachedPropertyUsage/attachedPropertyUsage.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 5,
+ strlen("Keys"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 12, 25,
+ strlen("Keys"));
+ const auto attachedPropertyUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("attachedPropertyUsages") << 12 << 25 << attachedPropertyUsages;
+ }
+ {
+ const auto testFileName = testFile("findUsages/inlineComponents/inlineComponents.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 22,
+ strlen("foo"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 10, 44,
+ strlen("foo"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 14, 27,
+ strlen("foo"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 20, 20,
+ strlen("foo"));
+ const auto inlineUsages = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("inlineUsagesFromProperty") << 9 << 22 << inlineUsages;
+ QTest::addRow("inlineUsagesFromUsageOfBaseProperty") << 14 << 27 << inlineUsages;
+ QTest::addRow("inlineUsagesFromJsScope") << 20 << 20 << inlineUsages;
+ }
+ {
+ const auto testFileName = testFile("findUsages/propertyChanges/propertyChanges.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 9,
+ strlen("onClicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 16, 21,
+ strlen("onClicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 19, 25,
+ strlen("onClicked"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 25, 17,
+ strlen("onClicked"));
+ const auto propertyChanges = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("propertyChanges1") << 16 << 21 << propertyChanges;
+ }
+ {
+ const auto testFileName = testFile("findUsages/bindings/bindings.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 11, 23,
+ strlen("patronChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 14, 27,
+ strlen("patronChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 21, 27,
+ strlen("patronChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 27, 19,
+ strlen("patronChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 27, 41,
+ strlen("patronChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 34, 17,
+ strlen("patronChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 13, 20,
+ strlen("patronChanged"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 20, 23,
+ strlen("\"patronChanged\""));
+ const auto bindings = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("propertyInBindingsFromDecl") << 11 << 23 << bindings;
+ QTest::addRow("generalizedGroupPropertyBindings") << 27 << 19 << bindings;
+ }
+ {
+ const auto testFileName = testFile("findUsages/enums/Enums.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ const auto otherFileName = testFile("findUsages/enums/EnumsFromAnotherFile.qml");
+ const auto otherFileContent = readFileContent(otherFileName);
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 9, 9,
+ strlen("Patron"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 22, 35,
+ strlen("Patron"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 23, 34,
+ strlen("Patron"));
+ const auto enums = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("enumValuesFromDeclaration") << 9 << 9 << enums;
+ QTest::addRow("enumValuesFromUsage") << 22 << 35 << enums;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 8, 10,
+ strlen("Cats"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 22, 30,
+ strlen("Cats"));
+ const auto enums = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("enumNameFromDeclaration") << 8 << 10 << enums;
+ QTest::addRow("enumNameFromUsage") << 22 << 30 << enums;
+ }
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 26, 46,
+ strlen("FromAnotherUniverse"));
+ expectedUsages << QQmlLSUtils::Location::from(otherFileName, otherFileContent, 4, 68,
+ strlen("FromAnotherUniverse"));
+ const auto enums = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("enumNameFromDeclarationInOtherFile") << 26 << 50 << enums;
+ const auto enumsFromOtherFile = makeUsages(otherFileName, expectedUsages);
+ QTest::addRow("enumNameFromUsageFromOtherFile") << 4 << 81 << enumsFromOtherFile;
+ }
+ }
+ {
+ const auto testFileName = testFile("findUsages/inlineComponents/inlineComponents2.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 4, 15,
+ strlen("MyIC"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 5, 5,
+ strlen("MyIC"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 5, 12,
+ strlen("MyIC"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 5, 19,
+ strlen("MyIC"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 6, 19,
+ strlen("MyIC"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 6, 26,
+ strlen("MyIC"));
+ const auto inlineComponents = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findICUsagesFromDefinition") << 4 << 16 << inlineComponents;
+ QTest::addRow("findICUsagesFromDefinition2") << 4 << 9 << inlineComponents;
+ QTest::addRow("findICUsagesFromUsage") << 5 << 19 << inlineComponents;
+ QTest::addRow("findICUsagesFromTypeUsage") << 6 << 19 << inlineComponents;
+ }
+ }
+ {
+ const auto testFileName = testFile("findUsages/inlineComponents/inlineComponents.qml");
+ const auto testFileContent = readFileContent(testFileName);
+ const auto providerFileName =
+ testFile("findUsages/inlineComponents/InlineComponentProvider.qml");
+ const auto providerFileContent = readFileContent(providerFileName);
+ {
+ QList<QQmlLSUtils::Location> expectedUsages;
+ expectedUsages << QQmlLSUtils::Location::from(providerFileName, providerFileContent, 4,
+ 15, strlen("IC1"));
+ expectedUsages << QQmlLSUtils::Location::from(providerFileName, providerFileContent, 5,
+ 36, strlen("IC1"));
+ expectedUsages << QQmlLSUtils::Location::from(providerFileName, providerFileContent, 7,
+ 5, strlen("IC1"));
+ expectedUsages << QQmlLSUtils::Location::from(providerFileName, providerFileContent, 17,
+ 13, strlen("IC1"));
+
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 25, 38,
+ strlen("IC1"));
+ expectedUsages << QQmlLSUtils::Location::from(testFileName, testFileContent, 25, 84,
+ strlen("IC1"));
+
+ {
+ const auto usagesForTestFile = makeUsages(testFileName, expectedUsages);
+ QTest::addRow("findICUsagesFromTypeAnnotationInOtherFiles")
+ << 25 << 39 << usagesForTestFile;
+ QTest::addRow("findICUsagesFromInstantiationInOtherFiles")
+ << 25 << 84 << usagesForTestFile;
+ }
+
+ {
+ const auto usagesInProviderFile = makeUsages(providerFileName, expectedUsages);
+
+ QTest::addRow("findICUsagesFromDefinitionInOtherFiles")
+ << 4 << 16 << usagesInProviderFile;
+ QTest::addRow("findICUsagesFromInstantiationInOtherFiles2")
+ << 17 << 14 << usagesInProviderFile;
+ }
+ }
+ }
+}
+
+void tst_qmlls_utils::findUsages()
+{
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(UsageData, data);
+
+ {
+ auto usagesInFilename = data.expectedUsages.usagesInFilename();
+ QVERIFY(std::is_sorted(usagesInFilename.begin(), usagesInFilename.end()));
+ auto usagesInFile = data.expectedUsages.usagesInFile();
+ QVERIFY(std::is_sorted(usagesInFile.begin(), usagesInFile.end()));
+ }
+
+ auto [env, file] = createEnvironmentAndLoadFile(data.testFileName);
+
+ auto locations = QQmlLSUtils::itemsFromTextLocation(
+ file.field(QQmlJS::Dom::Fields::currentItem), line - 1, character - 1);
+
+ if constexpr (enable_debug_output) {
+ if (locations.size() > 1) {
+ for (auto &x : locations)
+ qDebug() << x.domItem.toString();
+ }
+ }
+ QCOMPARE(locations.size(), 1);
+
+ auto usages = QQmlLSUtils::findUsagesOf(locations.front().domItem);
+
+ if constexpr (enable_debug_output) {
+ if (usages != data.expectedUsages) {
+ qDebug() << "Got:\n";
+ for (auto &x : usages.usagesInFile()) {
+ qDebug() << x.filename << "(" << x.sourceLocation.startLine << ", "
+ << x.sourceLocation.startColumn << "), " << x.sourceLocation.offset << "+"
+ << x.sourceLocation.length;
+ }
+ qDebug() << "with usages in filenames:" << usages.usagesInFilename();
+ qDebug() << "But expected: \n";
+ for (auto &x : data.expectedUsages.usagesInFile()) {
+ qDebug() << x.filename << "(" << x.sourceLocation.startLine << ", "
+ << x.sourceLocation.startColumn << "), " << x.sourceLocation.offset << "+"
+ << x.sourceLocation.length;
+ }
+ qDebug() << "with usages in filenames:" << data.expectedUsages.usagesInFilename();
+ }
+ }
+
+ QCOMPARE(usages, data.expectedUsages);
+}
+
+
+void tst_qmlls_utils::renameUsages_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+ QTest::addColumn<QString>("newName");
+ QTest::addColumn<QQmlLSUtils::RenameUsages>("expectedRenames");
+ QTest::addColumn<QString>("expectedError");
+
+ const QString testFileName = testFile(u"JSUsages.qml"_s);
+ const QString testFileNameFromAnotherFile = testFile(u"JSUsagesFromAnotherFile.qml"_s);
+ const QString testFileContent = readFileContent(testFileName);
+ const QString testFileFromAnotherFileContent = readFileContent(testFileNameFromAnotherFile);
+
+ const QString noError;
+ const QQmlLSUtils::RenameUsages noRenames;
+
+ QQmlLSUtils::RenameUsages methodFRename{
+ {
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 72, 14, strlen("recursive"),
+ u"newNameNewMe"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 74, 24, strlen("recursive"),
+ u"newNameNewMe"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 74, 34, strlen("recursive"),
+ u"newNameNewMe"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 74, 51, strlen("recursive"),
+ u"newNameNewMe"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 74, 68, strlen("recursive"),
+ u"newNameNewMe"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 76, 20, strlen("recursive"),
+ u"newNameNewMe"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 79, 34, strlen("recursive"),
+ u"newNameNewMe"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 84, 27, strlen("recursive"),
+ u"newNameNewMe"_s),
+ },
+ {}
+ };
+
+ QQmlLSUtils::RenameUsages JSIdentifierSumRename{
+ {
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 8, 13, strlen("sum"),
+ u"sumsumsum123"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 10, 13, strlen("sum"),
+ u"sumsumsum123"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 10, 19, strlen("sum"),
+ u"sumsumsum123"_s),
+ },
+ {}
+ };
+
+ QQmlLSUtils::RenameUsages qmlSignalRename{
+ {
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 88, 12,
+ strlen("helloSignal"), u"finalSignal"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 91, 9, strlen("helloSignal"),
+ u"finalSignal"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 93, 13,
+ strlen("helloSignal"), u"finalSignal"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 97, 17,
+ strlen("helloSignal"), u"finalSignal"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 101, 9,
+ strlen("helloSignal"), u"finalSignal"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 119, 5,
+ strlen("onHelloSignal"), u"onFinalSignal"_s),
+ },
+ {}
+ };
+
+ QQmlLSUtils::RenameUsages helloPropertyRename{
+ {
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 17, 18,
+ strlen("helloProperty"), u"freshPropertyName"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 24, 13,
+ strlen("helloProperty"), u"freshPropertyName"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 24, 29,
+ strlen("helloProperty"), u"freshPropertyName"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 65, 60,
+ strlen("helloProperty"), u"freshPropertyName"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 151, 9,
+ strlen("helloPropertyChanged"),
+ u"freshPropertyNameChanged"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 153, 5,
+ strlen("onHelloPropertyChanged"),
+ u"onFreshPropertyNameChanged"_s),
+ QQmlLSUtils::Edit::from(testFileNameFromAnotherFile, testFileFromAnotherFileContent,
+ 12, 16, strlen("helloProperty"), u"freshPropertyName"_s),
+ },
+ {}
+ };
+
+ QQmlLSUtils::RenameUsages nestedComponentRename{
+ {
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 42, 15,
+ strlen("NestedComponent"), u"SuperInlineComponent"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 61, 5,
+ strlen("NestedComponent"), u"SuperInlineComponent"_s),
+ },
+ {}
+ };
+
+ QQmlLSUtils::RenameUsages myNestedIdRename{
+ {
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 62, 13, strlen("myNested"),
+ u"freshNewIdForMyNested"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 65, 17, strlen("myNested"),
+ u"freshNewIdForMyNested"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 66, 17, strlen("myNested"),
+ u"freshNewIdForMyNested"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 67, 17, strlen("myNested"),
+ u"freshNewIdForMyNested"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 68, 17, strlen("myNested"),
+ u"freshNewIdForMyNested"_s),
+ QQmlLSUtils::Edit::from(testFileName, testFileContent, 69, 17, strlen("myNested"),
+ u"freshNewIdForMyNested"_s),
+ },
+ {}
+ };
+
+ const QString renameFileQml = testFile("renaming/main.qml");
+ const QString renameFileQmlContent = readFileContent(renameFileQml);
+ const QQmlLSUtils::RenameUsages renameComponent1{
+ {
+ QQmlLSUtils::Edit::from(renameFileQml, renameFileQmlContent, 4, 5,
+ strlen("RenameMe"), u"FreshNewComponentName"_s),
+ },
+ {
+ { testFile("renaming/RenameMe.qml"),
+ testFile(u"renaming/FreshNewComponentName.qml"_s) },
+ }
+ };
+ const QQmlLSUtils::RenameUsages renameComponent2{
+ {
+ QQmlLSUtils::Edit::from(renameFileQml, renameFileQmlContent, 5, 5,
+ strlen("RenameMe2"), u"AnotherOneThankYou"_s),
+ },
+ {
+ { testFile("renaming/RenameMe2.ui.qml"),
+ testFile(u"renaming/AnotherOneThankYou.ui.qml"_s) },
+ }
+ };
+ const QQmlLSUtils::RenameUsages renameComponentNamedByQmldir{
+ {
+ QQmlLSUtils::Edit::from(renameFileQml, renameFileQmlContent, 6, 5,
+ strlen("HelloWorld"), u"AnotherOneThankYou"_s),
+ },
+ // make sure that the file itself does not get renamed
+ {}
+ };
+
+ const QString parserError = u"Invalid EcmaScript identifier!"_s;
+
+ QTest::addRow("renameMethod") << testFileName << 72 << 19 << u"newNameNewMe"_s << methodFRename
+ << noError;
+ QTest::addRow("renameJSIdentifier")
+ << testFileName << 10 << 19 << u"sumsumsum123"_s << JSIdentifierSumRename << noError;
+ QTest::addRow("renameQmlSignal")
+ << testFileName << 93 << 19 << u"finalSignal"_s << qmlSignalRename << noError;
+ QTest::addRow("renameQmlSignalHandler")
+ << testFileName << 119 << 10 << u"onFinalSignal"_s << qmlSignalRename << noError;
+
+ QTest::addRow("renameQmlProperty")
+ << testFileName << 17 << 20 << u"freshPropertyName"_s << helloPropertyRename << noError;
+ QTest::addRow("renameQmlPropertyChanged")
+ << testFileName << 151 << 18 << u"freshPropertyNameChanged"_s << helloPropertyRename
+ << noError;
+ QTest::addRow("renameQmlPropertyChangedHandler")
+ << testFileName << 153 << 22 << u"onFreshPropertyNameChanged"_s << helloPropertyRename
+ << noError;
+
+ QTest::addRow("renameQmlObjectId") << testFileName << 65 << 21 << u"freshNewIdForMyNested"_s
+ << myNestedIdRename << noError;
+
+ // rename forbidden stuff
+ QTest::addRow("renameCPPDefinedItem") << testFileName << 144 << 13 << u"onHelloWorld"_s
+ << noRenames << u"defined in non-QML files."_s;
+ QTest::addRow("renameFunctionKeyword") << testFileName << 8 << 10 << u"HelloWorld"_s
+ << noRenames << "Requested item cannot be renamed";
+ QTest::addRow("invalidCharactersInIdentifier")
+ << testFileName << 12 << 22 << u"\""_s << noRenames << parserError;
+ QTest::addRow("invalidCharactersInIdentifier2")
+ << testFileName << 12 << 22 << u"hello world"_s << noRenames << parserError;
+ QTest::addRow("invalidCharactersInIdentifier3")
+ << testFileName << 12 << 22 << u"sum.sum.sum"_s << noRenames << parserError;
+ QTest::addRow("emptyIdentifier")
+ << testFileName << 12 << 22 << QString() << noRenames << parserError;
+ QTest::addRow("usingKeywordAsIdentifier")
+ << testFileName << 12 << 22 << u"function"_s << noRenames << parserError;
+
+ QTest::addRow("changedSignalHandlerMissingOnChanged")
+ << testFileName << 134 << 9 << u"___"_s << noRenames
+ << u"Invalid name for a property changed handler identifier"_s;
+ QTest::addRow("changedSignalHandlerMissingChanged")
+ << testFileName << 134 << 9 << u"on___"_s << noRenames
+ << u"Invalid name for a property changed handler identifier"_s;
+ QTest::addRow("changedSignalHandlerMissingOn")
+ << testFileName << 134 << 9 << u"___Changed"_s << noRenames
+ << u"Invalid name for a property changed handler identifier"_s;
+ QTest::addRow("changedSignalHandlerTypoInChanged")
+ << testFileName << 134 << 9 << u"on___Chänged"_s << noRenames
+ << u"Invalid name for a property changed handler identifier"_s;
+
+ QTest::addRow("signalHandlerMissingOn")
+ << testFileName << 119 << 10 << u"helloSuperSignal"_s << noRenames
+ << u"Invalid name for a signal handler identifier"_s;
+ QTest::addRow("signalHandlerMissingCapitalization")
+ << testFileName << 119 << 10 << u"onhelloSuperSignal"_s << noRenames
+ << u"Invalid name for a signal handler identifier"_s;
+
+ QTest::addRow("JSIdentifierStartsWithNumber")
+ << testFileName << 67 << 13 << u"123"_s << noRenames << parserError;
+
+ QTest::addRow("renameQmlFile") << testFile(u"renaming/main.qml"_s) << 4 << 9
+ << u"FreshNewComponentName"_s << renameComponent1 << noError;
+
+ QTest::addRow("renameUiQmlFile") << testFile(u"renaming/main.qml"_s) << 5 << 9
+ << u"AnotherOneThankYou"_s << renameComponent2 << noError;
+
+ QTest::addRow("renameQmlFileRenamedByQmldir")
+ << testFile(u"renaming/main.qml"_s) << 6 << 8 << u"AnotherOneThankYou"_s
+ << renameComponentNamedByQmldir << noError;
+}
+
+void tst_qmlls_utils::renameUsages()
+{
+ // findAndRenameUsages() already tests if all usages will be renamed
+ // now test that the new name is correctly passed
+ QFETCH(QString, filePath);
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(QString, newName);
+ QFETCH(QQmlLSUtils::RenameUsages, expectedRenames);
+ QFETCH(QString, expectedError);
+
+ {
+ const auto renameInFile = expectedRenames.renameInFile();
+ QVERIFY(std::is_sorted(renameInFile.constBegin(), renameInFile.constEnd()));
+ const auto renameInFilename = expectedRenames.renameInFilename();
+ QVERIFY(std::is_sorted(renameInFilename.begin(), renameInFilename.end()));
+ }
+
+ auto [env, file] = createEnvironmentAndLoadFile(filePath);
+
+ auto locations = QQmlLSUtils::itemsFromTextLocation(
+ file.field(QQmlJS::Dom::Fields::currentItem), line - 1, character - 1);
+
+ if constexpr (enable_debug_output) {
+ if (locations.size() > 1) {
+ for (auto &x : locations)
+ qDebug() << x.domItem.toString();
+ }
+ }
+ QCOMPARE(locations.size(), 1);
+
+ if (auto errors = QQmlLSUtils::checkNameForRename(locations.front().domItem, newName)) {
+ if constexpr (enable_debug_output) {
+ if (expectedError.isEmpty())
+ qDebug() << "Expected no error but got" << errors->message;
+ if (!errors->message.contains(expectedError))
+ qDebug() << "Cannot find" << expectedError << "in" << errors->message;
+ }
+ QVERIFY(!expectedError.isEmpty());
+ QVERIFY(errors->message.contains(expectedError));
+ return;
+ }
+ auto edits = QQmlLSUtils::renameUsagesOf(locations.front().domItem, newName);
+
+ if constexpr (enable_debug_output) {
+ if (edits != expectedRenames) {
+ qDebug() << "Got:\n";
+ for (auto &x : edits.renameInFile()) {
+ qDebug() << x.replacement << x.location.filename << "("
+ << x.location.sourceLocation.startLine << ", "
+ << x.location.sourceLocation.startColumn << "), "
+ << x.location.sourceLocation.offset << "+"
+ << x.location.sourceLocation.length;
+ }
+ qDebug() << "with renames in filenames:";
+ for (auto &x : edits.renameInFilename()) {
+ qDebug() << x.oldFilename << "->" << x.newFilename;
+ }
+ qDebug() << "But expected: \n";
+ for (auto &x : expectedRenames.renameInFile()) {
+ qDebug() << x.replacement << x.location.filename << "("
+ << x.location.sourceLocation.startLine << ", "
+ << x.location.sourceLocation.startColumn << "), "
+ << x.location.sourceLocation.offset << "+"
+ << x.location.sourceLocation.length;
+ }
+ qDebug() << "with renames in filenames:";
+ for (auto &x : expectedRenames.renameInFilename()) {
+ qDebug() << x.oldFilename << "->" << x.newFilename;
+ }
+ }
+ }
+ QCOMPARE(edits, expectedRenames);
+}
+
+void tst_qmlls_utils::findDefinitionFromLocation_data()
+{
+ QTest::addColumn<QString>("filePath");
+ // keep in mind that line and character are starting at 1!
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+
+ QTest::addColumn<QString>("expectedFilePath");
+ // set to -1 when unchanged from above line and character. 0-based.
+ QTest::addColumn<int>("expectedLine");
+ QTest::addColumn<int>("expectedCharacter");
+ QTest::addColumn<size_t>("expectedLength");
+
+ const QString JSDefinitionsQml = testFile(u"JSDefinitions.qml"_s);
+ const QString BaseTypeQml = testFile(u"BaseType.qml"_s);
+
+ QTest::addRow("JSIdentifierX")
+ << JSDefinitionsQml << 14 << 11 << JSDefinitionsQml << 13 << 13 << strlen("x");
+ QTest::addRow("JSIdentifierX2")
+ << JSDefinitionsQml << 15 << 11 << JSDefinitionsQml << 13 << 13 << strlen("x");
+ QTest::addRow("propertyI") << JSDefinitionsQml << 14 << 14 << JSDefinitionsQml << 9 << 18
+ << strlen("i");
+ QTest::addRow("qualifiedPropertyI")
+ << JSDefinitionsQml << 15 << 21 << JSDefinitionsQml << 9 << 18 << strlen("i");
+ QTest::addRow("inlineComponentProperty")
+ << JSDefinitionsQml << 62 << 21 << JSDefinitionsQml << 54 << 22 << strlen("data");
+
+ QTest::addRow("parameterA") << JSDefinitionsQml << 10 << 16 << JSDefinitionsQml << 10 << 16
+ << strlen("a");
+ QTest::addRow("parameterAUsage")
+ << JSDefinitionsQml << 10 << 39 << JSDefinitionsQml << -1 << 16 << strlen("a");
+
+ QTest::addRow("parameterB") << JSDefinitionsQml << 10 << 28 << JSDefinitionsQml << 10 << 28
+ << strlen("b");
+ QTest::addRow("parameterBUsage")
+ << JSDefinitionsQml << 10 << 86 << JSDefinitionsQml << -1 << 28 << strlen("b");
+
+ QTest::addRow("comment") << JSDefinitionsQml << 10 << 21 << noResultExpected << -1 << -1
+ << size_t{};
+
+ QTest::addRow("scopedX") << JSDefinitionsQml << 22 << 18 << JSDefinitionsQml << 21 << 17
+ << strlen("scoped");
+ QTest::addRow("scopedX2") << JSDefinitionsQml << 25 << 22 << JSDefinitionsQml << 21 << 17
+ << strlen("scoped");
+ QTest::addRow("scopedX3") << JSDefinitionsQml << 28 << 14 << JSDefinitionsQml << 19 << 13
+ << strlen("scoped");
+
+ QTest::addRow("normalI") << JSDefinitionsQml << 22 << 23 << JSDefinitionsQml << 9 << 18
+ << strlen("i");
+ QTest::addRow("scopedI") << JSDefinitionsQml << 25 << 27 << JSDefinitionsQml << 24 << 32
+ << strlen("i");
+
+ QTest::addRow("shadowingProperty")
+ << JSDefinitionsQml << 37 << 21 << JSDefinitionsQml << 34 << 22 << strlen("i");
+ QTest::addRow("shadowingQualifiedProperty")
+ << JSDefinitionsQml << 37 << 35 << JSDefinitionsQml << 34 << 22 << strlen("i");
+ QTest::addRow("shadowedProperty")
+ << JSDefinitionsQml << 37 << 49 << JSDefinitionsQml << 9 << 18 << strlen("i");
+
+ QTest::addRow("propertyInBinding")
+ << JSDefinitionsQml << 64 << 37 << JSDefinitionsQml << 9 << 18 << strlen("i");
+ QTest::addRow("propertyInBinding2")
+ << JSDefinitionsQml << 65 << 38 << JSDefinitionsQml << 9 << 18 << strlen("i");
+ QTest::addRow("propertyInBinding3")
+ << JSDefinitionsQml << 66 << 51 << JSDefinitionsQml << 9 << 18 << strlen("i");
+
+ QTest::addRow("propertyFromDifferentFile")
+ << JSDefinitionsQml << 72 << 20 << BaseTypeQml << 24 << 18 << strlen("helloProperty");
+
+ QTest::addRow("id") << JSDefinitionsQml << 15 << 17 << JSDefinitionsQml << 7 << 9
+ << strlen("rootId");
+ QTest::addRow("onId") << JSDefinitionsQml << 32 << 16 << JSDefinitionsQml << 32 << 13
+ << strlen("nested");
+ QTest::addRow("parentId") << JSDefinitionsQml << 37 << 44 << JSDefinitionsQml << 7 << 9
+ << strlen("rootId");
+ QTest::addRow("currentId") << JSDefinitionsQml << 37 << 30 << JSDefinitionsQml << 32 << 13
+ << strlen("nested");
+ QTest::addRow("inlineComponentId")
+ << JSDefinitionsQml << 56 << 35 << JSDefinitionsQml << 52 << 13 << strlen("helloIC");
+
+ QTest::addRow("recursiveFunction")
+ << JSDefinitionsQml << 39 << 28 << JSDefinitionsQml << 36 << 18 << strlen("f");
+ QTest::addRow("recursiveFunction2")
+ << JSDefinitionsQml << 39 << 39 << JSDefinitionsQml << 36 << 18 << strlen("f");
+ QTest::addRow("functionFromFunction")
+ << JSDefinitionsQml << 44 << 20 << JSDefinitionsQml << 36 << 18 << strlen("f");
+ QTest::addRow("qualifiedFunctionName")
+ << JSDefinitionsQml << 48 << 23 << JSDefinitionsQml << 36 << 18 << strlen("f");
+
+ QTest::addRow("functionInParent")
+ << JSDefinitionsQml << 44 << 37 << JSDefinitionsQml << 18 << 14 << strlen("ffff");
+ QTest::addRow("functionFromDifferentFile")
+ << JSDefinitionsQml << 72 << 47 << BaseTypeQml << 25 << 14 << strlen("helloFunction");
+ QTest::addRow("componentFromFile")
+ << JSDefinitionsQml << 68 << 28 << BaseTypeQml << 6 << 1 << strlen("Item");
+ QTest::addRow("inlineComponentFromDifferentFile")
+ << JSDefinitionsQml << 75 << 27 << BaseTypeQml << 9 << 38 << strlen("Item");
+}
+
+void tst_qmlls_utils::findDefinitionFromLocation()
+{
+ QFETCH(QString, filePath);
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(QString, expectedFilePath);
+ QFETCH(int, expectedLine);
+ QFETCH(int, expectedCharacter);
+ QFETCH(size_t, expectedLength);
+
+ if (expectedLine == -1)
+ expectedLine = line;
+ if (expectedCharacter == -1)
+ expectedCharacter = character;
+
+ // they all start at 1.
+ Q_ASSERT(line > 0);
+ Q_ASSERT(character > 0);
+ Q_ASSERT(expectedLine > 0);
+ Q_ASSERT(expectedCharacter > 0);
+
+ auto [env, file] = createEnvironmentAndLoadFile(filePath);
+
+ auto locations = QQmlLSUtils::itemsFromTextLocation(
+ file.field(QQmlJS::Dom::Fields::currentItem), line - 1, character - 1);
+
+ QCOMPARE(locations.size(), 1);
+
+ auto definition = QQmlLSUtils::findDefinitionOf(locations.front().domItem);
+
+ // if expectedFilePath is empty, we probably just want to make sure that it does
+ // not crash
+ if (expectedFilePath == noResultExpected) {
+ QVERIFY(!definition);
+ return;
+ }
+
+ QVERIFY(definition);
+
+ QCOMPARE(definition->filename, expectedFilePath);
+
+ QCOMPARE(definition->sourceLocation.startLine, quint32(expectedLine));
+ QCOMPARE(definition->sourceLocation.startColumn, quint32(expectedCharacter));
+ QCOMPARE(definition->sourceLocation.length, quint32(expectedLength));
+}
+
+void tst_qmlls_utils::resolveExpressionType_data()
+{
+ QTest::addColumn<QString>("filePath");
+ // keep in mind that line and character are starting at 1!
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+ QTest::addColumn<QQmlLSUtils::ResolveOptions>("resolveOption");
+ QTest::addColumn<QString>("expectedFile");
+ // startline of the owners definition
+ QTest::addColumn<int>("expectedLine");
+ QTest::addColumn<QQmlLSUtils::IdentifierType>("expectedType");
+
+ using namespace QQmlLSUtils;
+
+ const int noLine = -1;
+ const QString noFile;
+
+ {
+ const QString JSDefinitionsQml = testFile(u"JSDefinitions.qml"_s);
+ const int parentLine = 6;
+ const int childLine = 31;
+
+ QTest::addRow("id") << JSDefinitionsQml << 15 << 17 << ResolveOwnerType << JSDefinitionsQml
+ << parentLine << QmlObjectIdIdentifier;
+ QTest::addRow("childIddInChild") << JSDefinitionsQml << 37 << 30 << ResolveOwnerType
+ << JSDefinitionsQml << childLine << QmlObjectIdIdentifier;
+ QTest::addRow("parentIdInChild") << JSDefinitionsQml << 37 << 43 << ResolveOwnerType
+ << JSDefinitionsQml << parentLine << QmlObjectIdIdentifier;
+
+ QTest::addRow("propertyI") << JSDefinitionsQml << 14 << 14 << ResolveOwnerType
+ << JSDefinitionsQml << parentLine << PropertyIdentifier;
+ QTest::addRow("qualifiedPropertyI") << JSDefinitionsQml << 15 << 21 << ResolveOwnerType
+ << JSDefinitionsQml << parentLine << PropertyIdentifier;
+ QTest::addRow("propertyIInChild") << JSDefinitionsQml << 37 << 21 << ResolveOwnerType
+ << JSDefinitionsQml << childLine << PropertyIdentifier;
+ QTest::addRow("qualifiedChildPropertyIInChild")
+ << JSDefinitionsQml << 37 << 35 << ResolveOwnerType << JSDefinitionsQml
+ << childLine << PropertyIdentifier;
+ QTest::addRow("qualifiedParentPropertyIInChild")
+ << JSDefinitionsQml << 37 << 49 << ResolveOwnerType << JSDefinitionsQml
+ << parentLine << PropertyIdentifier;
+
+ QTest::addRow("childMethod") << JSDefinitionsQml << 48 << 23 << ResolveOwnerType
+ << JSDefinitionsQml << childLine << MethodIdentifier;
+ QTest::addRow("childMethod2") << JSDefinitionsQml << 44 << 20 << ResolveOwnerType
+ << JSDefinitionsQml << childLine << MethodIdentifier;
+ QTest::addRow("parentMethod") << JSDefinitionsQml << 14 << 9 << ResolveOwnerType
+ << JSDefinitionsQml << parentLine << MethodIdentifier;
+ }
+
+ {
+ const QString bindingsOnDeferredQml =
+ testFile(u"resolveExpressionType/BindingsOnDeferred.qml"_s);
+ const QString qQuickControl = u"private/qquickcontrol_p.h"_s;
+ const QString qQuickKeysAttachedType = u"private/qquickitem_p.h"_s;
+ QTest::addRow("bindingOnId") << bindingsOnDeferredQml << 12 << 14 << ResolveOwnerType
+ << bindingsOnDeferredQml << 8 << QmlObjectIdIdentifier;
+ QTest::addRow("bindingOnQualifiedDeferredProperty")
+ << bindingsOnDeferredQml << 12 << 24 << ResolveOwnerType << qQuickControl << noLine
+ << PropertyIdentifier;
+ QTest::addRow("groupedPropertyBindingOnId")
+ << bindingsOnDeferredQml << 14 << 14 << ResolveOwnerType << bindingsOnDeferredQml
+ << 8 << QmlObjectIdIdentifier;
+ QTest::addRow("someDeferredProperty")
+ << bindingsOnDeferredQml << 15 << 22 << ResolveOwnerType << qQuickControl << noLine
+ << PropertyIdentifier;
+ }
+
+ {
+ const QString JSUsagesQml = testFile(u"JSUsages.qml"_s);
+ const int rootLine = 6;
+ const int nestedComponent2Line = 46;
+ const int nestedComponent3Line = 51;
+ const int nestedComponent4Line = 57;
+ QTest::addRow("propertyAccess:inner.inner") << JSUsagesQml << 68 << 34 << ResolveOwnerType
+ << JSUsagesQml << nestedComponent2Line << PropertyIdentifier;
+ QTest::addRow("propertyAccess:inner.inner2") << JSUsagesQml << 69 << 34 << ResolveOwnerType
+ << JSUsagesQml << nestedComponent2Line << PropertyIdentifier;
+ QTest::addRow("propertyAccess:inner.inner.inner")
+ << JSUsagesQml << 69 << 40 << ResolveOwnerType << JSUsagesQml
+ << nestedComponent3Line << PropertyIdentifier;
+ QTest::addRow("propertyAccess:inner.inner.inner.p2")
+ << JSUsagesQml << 69 << 44 << ResolveOwnerType << JSUsagesQml
+ << nestedComponent4Line << PropertyIdentifier;
+
+ QTest::addRow("propertyAccess:helloProperty")
+ << JSUsagesQml << 65 << 68 << ResolveOwnerType << JSUsagesQml << rootLine << PropertyIdentifier;
+ QTest::addRow("propertyAccess:nestedHelloProperty")
+ << JSUsagesQml << 65 << 46 << ResolveOwnerType << JSUsagesQml
+ << nestedComponent4Line << PropertyIdentifier;
+ }
+
+ {
+ const QString derivedType = testFile(u"resolveExpressionType/DerivedType.qml"_s);
+ const QString derived2Type = testFile(u"resolveExpressionType/Derived2.qml"_s);
+ const QString baseType = testFile(u"resolveExpressionType/BaseType.qml"_s);
+ const QString qQuickValueTypes = u"private/qquickvaluetypes_p.h"_s;
+ const QString qQuickKeysAttachedType = u"private/qquickitem_p.h"_s;
+
+ const int baseTypeLine = 6;
+ const int derivedTypeLine = 6;
+ const int keysLine = 29;
+
+ QTest::addRow("ownerOfMethod")
+ << derivedType << 9 << 13 << ResolveOwnerType << baseType << baseTypeLine << MethodIdentifier;
+ QTest::addRow("ownerOfMethod2")
+ << derivedType << 15 << 33 << ResolveOwnerType << baseType << baseTypeLine << MethodIdentifier;
+ QTest::addRow("ownerOfQualifiedMethod")
+ << derivedType << 22 << 46 << ResolveOwnerType << baseType << baseTypeLine << MethodIdentifier;
+
+ QTest::addRow("ownerOfProperty")
+ << derivedType << 10 << 22 << ResolveOwnerType << baseType << baseTypeLine << PropertyIdentifier;
+ QTest::addRow("ownerOfProperty2")
+ << derivedType << 16 << 37 << ResolveOwnerType << baseType << baseTypeLine << PropertyIdentifier;
+ QTest::addRow("ownerOfQualifiedProperty")
+ << derivedType << 23 << 46 << ResolveOwnerType << baseType << baseTypeLine << PropertyIdentifier;
+
+ QTest::addRow("ownerOfOwnProperty")
+ << derivedType << 16 << 23 << ResolveOwnerType << derivedType << derivedTypeLine << PropertyIdentifier;
+
+ QTest::addRow("ownerOfSignal")
+ << derivedType << 11 << 13 << ResolveOwnerType << baseType << baseTypeLine << SignalIdentifier;
+ QTest::addRow("ownerOfSignal2")
+ << derivedType << 18 << 37 << ResolveOwnerType << baseType << baseTypeLine << SignalIdentifier;
+ QTest::addRow("ownerOfSignalHandler")
+ << derivedType << 19 << 10 << ResolveOwnerType << baseType << baseTypeLine << SignalHandlerIdentifier;
+ QTest::addRow("ownerOfQualifiedSignal")
+ << derivedType << 25 << 22 << ResolveOwnerType << baseType << baseTypeLine << SignalIdentifier;
+
+ QTest::addRow("ownerOfGroupedProperty")
+ << derivedType << 28 << 7 << ResolveOwnerType << baseType << baseTypeLine << GroupedPropertyIdentifier;
+ QTest::addRow("ownerOfGroupedProperty2")
+ << derivedType << 28 << 17 << ResolveOwnerType << qQuickValueTypes << noLine
+ << PropertyIdentifier;
+
+ QTest::addRow("ownerOfAttachedProperty")
+ << derivedType << 29 << 6 << ResolveOwnerType << derivedType << keysLine << AttachedTypeIdentifier;
+ QTest::addRow("ownerOfAttachedProperty2")
+ << derivedType << 29 << 14 << ResolveOwnerType << qQuickKeysAttachedType << noLine
+ << SignalHandlerIdentifier;
+
+ QTest::addRow("actualTypeOfAttachedProperty")
+ << derivedType << 29 << 14 << ResolveActualTypeForFieldMemberExpression << noFile
+ << noLine << SignalHandlerIdentifier;
+
+ QTest::addRow("id")
+ << derivedType << 7 << 10 << ResolveOwnerType << derivedType << 6 << QmlObjectIdIdentifier;
+ QTest::addRow("propertyBinding")
+ << derivedType << 31 << 13 << ResolveOwnerType << baseType << baseTypeLine << PropertyIdentifier;
+
+ QTest::addRow("qmlObject")
+ << derivedType << 6 << 4 << ResolveOwnerType << derived2Type << 4 << QmlComponentIdentifier;
+ }
+}
+
+void tst_qmlls_utils::resolveExpressionType()
+{
+ QFETCH(QString, filePath);
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(QQmlLSUtils::ResolveOptions, resolveOption);
+ QFETCH(QString, expectedFile);
+ QFETCH(int, expectedLine);
+ QFETCH(QQmlLSUtils::IdentifierType, expectedType);
+
+ // they all start at 1.
+ Q_ASSERT(line > 0);
+ Q_ASSERT(character > 0);
+
+
+ auto [env, file] = createEnvironmentAndLoadFile(filePath);
+
+ auto locations = QQmlLSUtils::itemsFromTextLocation(
+ file.field(QQmlJS::Dom::Fields::currentItem), line - 1, character - 1);
+
+ QCOMPARE(locations.size(), 1);
+
+ auto definition = QQmlLSUtils::resolveExpressionType(locations.front().domItem, resolveOption);
+
+ QVERIFY(definition);
+ if (!expectedFile.isEmpty()) {
+ QVERIFY(definition->semanticScope);
+ QCOMPARE(definition->semanticScope->filePath(), expectedFile);
+
+ if (expectedLine != -1) {
+ QQmlJS::SourceLocation location = definition->semanticScope->sourceLocation();
+ QCOMPARE((int)location.startLine, expectedLine);
+ }
+ } else {
+ QVERIFY(!definition->semanticScope);
+ }
+ QCOMPARE(definition->type, expectedType);
+}
+
+void tst_qmlls_utils::isValidEcmaScriptIdentifier_data()
+{
+ QTest::addColumn<QString>("identifier");
+ QTest::addColumn<bool>("isValid");
+
+ QTest::addRow("f") << u"f"_s << true;
+ QTest::addRow("f-unicode") << u"\\u0046"_s << true;
+ QTest::addRow("starts-with-digit") << u"8helloWorld"_s << false;
+ QTest::addRow("starts-with-unicode-digit") << u"\\u0038helloWorld"_s << false; // \u0038 == '8'
+ QTest::addRow("keyword") << u"return"_s << false;
+ QTest::addRow("not-keyword") << u"returny"_s << true;
+}
+
+void tst_qmlls_utils::isValidEcmaScriptIdentifier()
+{
+ QFETCH(QString, identifier);
+ QFETCH(bool, isValid);
+
+ QCOMPARE(QQmlLSUtils::isValidEcmaScriptIdentifier(identifier), isValid);
+}
+
+using namespace QLspSpecification;
+
+enum InsertOption { None, InsertColon };
+
+void tst_qmlls_utils::completions_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("character");
+ QTest::addColumn<ExpectedCompletions>("expected");
+ QTest::addColumn<QStringList>("notExpected");
+
+ const QString file = testFile(u"Yyy.qml"_s);
+ const QString emptyFile = testFile(u"emptyFile.qml"_s);
+ const QString pragmaFile = testFile(u"pragmas.qml"_s);
+
+ const QString singletonName = u"SystemInformation"_s;
+ const QString attachedTypeName = u"Component"_s;
+ const QString attachedTypeName2 = u"Keys"_s;
+ const auto attachedTypes = ExpectedCompletions({
+ { attachedTypeName, CompletionItemKind::Class },
+ { attachedTypeName2, CompletionItemKind::Class },
+ });
+
+ const auto keywords = ExpectedCompletions({
+ { u"function"_s, CompletionItemKind::Keyword },
+ { u"required"_s, CompletionItemKind::Keyword },
+ { u"enum"_s, CompletionItemKind::Keyword },
+ { u"component"_s, CompletionItemKind::Keyword },
+ });
+
+ const auto mixedTypes = ExpectedCompletions({
+ { u"Zzz"_s, CompletionItemKind::Class },
+ { u"Item"_s, CompletionItemKind::Class },
+ { u"int"_s, CompletionItemKind::Class },
+ { u"date"_s, CompletionItemKind::Class },
+ });
+ const auto constructorTypes = ExpectedCompletions({
+ { u"Rectangle"_s, CompletionItemKind::Constructor },
+ { u"MyRectangle"_s, CompletionItemKind::Constructor },
+ { u"Zzz"_s, CompletionItemKind::Constructor },
+ { u"Item"_s, CompletionItemKind::Constructor },
+ { u"QtObject"_s, CompletionItemKind::Constructor },
+ });
+ const auto rectangleTypes = ExpectedCompletions({
+ { u"Rectangle"_s, CompletionItemKind::Constructor },
+ { u"MyRectangle"_s, CompletionItemKind::Constructor },
+ });
+
+ QTest::newRow("objEmptyLine") << file << 9 << 1
+ << ExpectedCompletions({
+ { u"Rectangle"_s, CompletionItemKind::Constructor },
+ { u"width"_s, CompletionItemKind::Property },
+ })
+ << QStringList({ u"QtQuick"_s, u"vector4d"_s });
+
+ const QString propertyCompletion = u"property type name: value;"_s;
+ const QString functionCompletion = u"function name(args...): returnType { statements...}"_s;
+
+ const ExpectedCompletions quickSnippetsWithQualifier{
+ { u"QQ.BorderImage snippet"_s, CompletionItemKind::Snippet,
+ u"QQ.BorderImage {\n"
+ u"\tid: ${1:name}\n"
+ u"\tsource: \"${2:file}\"\n"
+ u"\twidth: ${3:100}; height: ${4:100}\n"
+ u"\tborder.left: ${5: 5}; border.top: ${5}\n"
+ u"\tborder.right: ${5}; border.bottom: ${5}\n"
+ u"}"_s },
+ { u"QQ.ColorAnimation snippet"_s, CompletionItemKind::Snippet,
+ u"QQ.ColorAnimation {\n"
+ u"\tfrom: \"${1:white}\"\n"
+ u"\tto: \"${2:black}\"\n"
+ u"\tduration: ${3:200}\n"
+ u"}"_s },
+ { u"QQ.Image snippet"_s, CompletionItemKind::Snippet,
+ u"QQ.Image {\n"
+ u"\tid: ${1:name}\n"
+ u"\tsource: \"${2:file}\"\n"
+ u"}"_s },
+ { u"QQ.Item snippet"_s, CompletionItemKind::Snippet,
+ u"QQ.Item {\n"
+ u"\tid: ${1:name}\n"
+ u"}"_s },
+ { u"QQ.NumberAnimation snippet"_s, CompletionItemKind::Snippet,
+ u"QQ.NumberAnimation {\n"
+ u"\ttarget: ${1:object}\n"
+ u"\tproperty: \"${2:name}\"\n"
+ u"\tduration: ${3:200}\n"
+ u"\teasing.type: QQ.Easing.${4:InOutQuad}\n"
+ u"}"_s },
+ { u"QQ.NumberAnimation with targets snippet"_s, CompletionItemKind::Snippet,
+ u"QQ.NumberAnimation {\n"
+ u"\ttargets: [${1:object}]\n"
+ u"\tproperties: \"${2:name}\"\n"
+ u"\tduration: ${3:200}\n"
+ u"}"_s },
+ { u"QQ.PauseAnimation snippet"_s, CompletionItemKind::Snippet,
+ u"QQ.PauseAnimation {\n"
+ u"\tduration: ${1:200}\n"
+ u"}"_s },
+ { u"QQ.PropertyAction snippet"_s, CompletionItemKind::Snippet,
+ u"QQ.PropertyAction {\n"
+ u"\ttarget: ${1:object}\n"
+ u"\tproperty: \"${2:name}\"\n"
+ "}"_s },
+ { u"QQ.PropertyAction with targets snippet"_s, CompletionItemKind::Snippet,
+ u"QQ.PropertyAction {\n"
+ u"\ttargets: [${1:object}]\n"
+ u"\tproperties: \"${2:name}\"\n"
+ u"}"_s },
+ { u"QQ.PropertyChanges snippet"_s, CompletionItemKind::Snippet,
+ u"QQ.PropertyChanges {\n"
+ u"\ttarget: ${1:object}\n"
+ u"}"_s },
+ { u"QQ.State snippet"_s, CompletionItemKind::Snippet,
+ u"QQ.State {\n"
+ u"\tname: ${1:name}\n"
+ u"\tQQ.PropertyChanges {\n"
+ u"\t\ttarget: ${2:object}\n"
+ u"\t}\n"
+ u"}"_s },
+ { u"QQ.Text snippet"_s, CompletionItemKind::Snippet,
+ u"QQ.Text {\n"
+ u"\tid: ${1:name}\n"
+ u"\ttext: qsTr(\"${2:text}\")\n"
+ u"}"_s },
+ { u"QQ.Transition snippet"_s, CompletionItemKind::Snippet,
+ u"QQ.Transition {\n"
+ u"\tfrom: \"${1:fromState}\"\n"
+ u"\tto: \"${2:toState}\"\n"
+ u"}"_s },
+ { u"states binding with PropertyChanges in State"_s, CompletionItemKind::Snippet,
+ u"states: [\n"
+ u"\tQQ.State {\n"
+ u"\t\tname: \"${1:name}\"\n"
+ u"\t\tQQ.PropertyChanges {\n"
+ u"\t\t\ttarget: ${2:object}\n"
+ u"\t\t}\n"
+ u"\t}\n"
+ u"]"_s },
+ { u"transitions binding with Transition"_s, CompletionItemKind::Snippet,
+ u"transitions: [\n"
+ u"\tQQ.Transition {\n"
+ u"\t\tfrom: \"${1:fromState}\"\n"
+ u"\t\tto: \"${2:fromState}\"\n"
+ u"\t}\n"
+ u"]"_s }
+ };
+ const ExpectedCompletions quickSnippetsWithoutQualifier{
+ { { u"BorderImage snippet"_s, CompletionItemKind::Snippet,
+ u"BorderImage {\n"
+ u"\tid: ${1:name}\n"
+ u"\tsource: \"${2:file}\"\n"
+ u"\twidth: ${3:100}; height: ${4:100}\n"
+ u"\tborder.left: ${5: 5}; border.top: ${5}\n"
+ u"\tborder.right: ${5}; border.bottom: ${5}\n"
+ u"}"_s },
+ { u"ColorAnimation snippet"_s, CompletionItemKind::Snippet,
+ u"ColorAnimation {\n"
+ u"\tfrom: \"${1:white}\"\n"
+ u"\tto: \"${2:black}\"\n"
+ u"\tduration: ${3:200}\n"
+ u"}"_s },
+ { u"Image snippet"_s, CompletionItemKind::Snippet,
+ u"Image {\n"
+ u"\tid: ${1:name}\n"
+ u"\tsource: \"${2:file}\"\n"
+ u"}"_s },
+ { u"Item snippet"_s, CompletionItemKind::Snippet,
+ u"Item {\n"
+ u"\tid: ${1:name}\n"
+ u"}"_s },
+ { u"NumberAnimation snippet"_s, CompletionItemKind::Snippet,
+ u"NumberAnimation {\n"
+ u"\ttarget: ${1:object}\n"
+ u"\tproperty: \"${2:name}\"\n"
+ u"\tduration: ${3:200}\n"
+ u"\teasing.type: Easing.${4:InOutQuad}\n"
+ u"}"_s },
+ { u"NumberAnimation with targets snippet"_s, CompletionItemKind::Snippet,
+ u"NumberAnimation {\n"
+ u"\ttargets: [${1:object}]\n"
+ u"\tproperties: \"${2:name}\"\n"
+ u"\tduration: ${3:200}\n"
+ u"}"_s },
+ { u"PauseAnimation snippet"_s, CompletionItemKind::Snippet,
+ u"PauseAnimation {\n"
+ u"\tduration: ${1:200}\n"
+ u"}"_s },
+ { u"PropertyAction snippet"_s, CompletionItemKind::Snippet,
+ u"PropertyAction {\n"
+ u"\ttarget: ${1:object}\n"
+ u"\tproperty: \"${2:name}\"\n"
+ "}"_s },
+ { u"PropertyAction with targets snippet"_s, CompletionItemKind::Snippet,
+ u"PropertyAction {\n"
+ u"\ttargets: [${1:object}]\n"
+ u"\tproperties: \"${2:name}\"\n"
+ u"}"_s },
+ { u"PropertyChanges snippet"_s, CompletionItemKind::Snippet,
+ u"PropertyChanges {\n"
+ u"\ttarget: ${1:object}\n"
+ u"}"_s },
+ { u"State snippet"_s, CompletionItemKind::Snippet,
+ u"State {\n"
+ u"\tname: ${1:name}\n"
+ u"\tPropertyChanges {\n"
+ u"\t\ttarget: ${2:object}\n"
+ u"\t}\n"
+ u"}"_s },
+ { u"Text snippet"_s, CompletionItemKind::Snippet,
+ u"Text {\n"
+ u"\tid: ${1:name}\n"
+ u"\ttext: qsTr(\"${2:text}\")\n"
+ u"}"_s },
+ { u"Transition snippet"_s, CompletionItemKind::Snippet,
+ u"Transition {\n"
+ u"\tfrom: \"${1:fromState}\"\n"
+ u"\tto: \"${2:toState}\"\n"
+ u"}"_s } }
+ };
+ const ExpectedCompletions quickSnippetsWithoutQualifierWithBindings = ExpectedCompletions{
+ { { u"states binding with PropertyChanges in State"_s, CompletionItemKind::Snippet,
+ u"states: [\n"
+ u"\tState {\n"
+ u"\t\tname: \"${1:name}\"\n"
+ u"\t\tPropertyChanges {\n"
+ u"\t\t\ttarget: ${2:object}\n"
+ u"\t\t}\n"
+ u"\t}\n"
+ u"]"_s },
+ { u"transitions binding with Transition"_s, CompletionItemKind::Snippet,
+ u"transitions: [\n"
+ u"\tTransition {\n"
+ u"\t\tfrom: \"${1:fromState}\"\n"
+ u"\t\tto: \"${2:fromState}\"\n"
+ u"\t}\n"
+ u"]"_s } }
+ } += quickSnippetsWithoutQualifier;
+ QTest::newRow("objEmptyLineSnippets")
+ << file << 9 << 1
+ << (ExpectedCompletions({
+ { propertyCompletion, CompletionItemKind::Snippet,
+ u"property ${1:type} ${2:name}: ${0:value};"_s },
+ { u"readonly property type name: value;"_s, CompletionItemKind::Snippet,
+ u"readonly property ${1:type} ${2:name}: ${0:value};"_s },
+ { u"default property type name: value;"_s, CompletionItemKind::Snippet,
+ u"default property ${1:type} ${2:name}: ${0:value};"_s },
+ { u"default required property type name: value;"_s,
+ CompletionItemKind::Snippet,
+ u"default required property ${1:type} ${2:name}: ${0:value};"_s },
+ { u"required default property type name: value;"_s,
+ CompletionItemKind::Snippet,
+ u"required default property ${1:type} ${2:name}: ${0:value};"_s },
+ { u"required property type name: value;"_s, CompletionItemKind::Snippet,
+ u"required property ${1:type} ${2:name}: ${0:value};"_s },
+ { u"property type name;"_s, CompletionItemKind::Snippet,
+ u"property ${1:type} ${0:name};"_s },
+ { u"required property type name;"_s, CompletionItemKind::Snippet,
+ u"required property ${1:type} ${0:name};"_s },
+ { u"default property type name;"_s, CompletionItemKind::Snippet,
+ u"default property ${1:type} ${0:name};"_s },
+ { u"default required property type name;"_s, CompletionItemKind::Snippet,
+ u"default required property ${1:type} ${0:name};"_s },
+ { u"required default property type name;"_s, CompletionItemKind::Snippet,
+ u"required default property ${1:type} ${0:name};"_s },
+ { u"signal name(arg1:type1, ...)"_s, CompletionItemKind::Snippet,
+ u"signal ${1:name}($0)"_s },
+ { u"signal name;"_s, CompletionItemKind::Snippet, u"signal ${0:name};"_s },
+ { u"required name;"_s, CompletionItemKind::Snippet,
+ u"required ${0:name};"_s },
+ { functionCompletion, CompletionItemKind::Snippet,
+ u"function ${1:name}($2): ${3:returnType} {\n\t$0\n}"_s },
+ { u"enum name { Values...}"_s, CompletionItemKind::Snippet,
+ u"enum ${1:name} {\n\t${0:values}\n}"_s },
+ { u"component Name: BaseType { ... }"_s, CompletionItemKind::Snippet,
+ u"component ${1:name}: ${2:baseType} {\n\t$0\n}"_s },
+ }) += quickSnippetsWithoutQualifierWithBindings)
+ // not allowed because required properties need an initializer
+ << QStringList({ u"readonly property type name;"_s });
+
+ QTest::newRow("quickSnippetsForQualifiedQuickImport")
+ << testFile("qualifiedModule.qml") << 5 << 1
+ << quickSnippetsWithQualifier
+ // not allowed because required properties need an initializer
+ << QStringList({ u"readonly property type name;"_s });
+
+ QTest::newRow("quickSnippetsForQualifiedQuickImportBeforeDot")
+ << testFile("qualifiedModule.qml") << 5 << 7
+ << quickSnippetsWithQualifier
+ // not allowed because required properties need an initializer
+ << QStringList({ u"readonly property type name;"_s });
+
+ QTest::newRow("quickSnippetsForQualifiedQuickImportAfterDot")
+ << testFile("qualifiedModule.qml") << 5 << 8
+ << quickSnippetsWithoutQualifier
+ // not allowed because required properties need an initializer
+ << QStringList({ u"readonly property type name;"_s,
+ u"states binding with PropertyChanges in State"_s,
+ u"transitions binding with Transition"_s });
+
+ QTest::newRow("quickSnippetsForQualifiedQuickImportBeforeDotInBinding")
+ << testFile("qualifiedModule.qml") << 4 << 33 << quickSnippetsWithQualifier
+ << QStringList();
+
+ QTest::newRow("quickSnippetsForQualifiedQuickImportAfterDotInBinding")
+ << testFile("qualifiedModule.qml") << 4 << 34 << quickSnippetsWithoutQualifier
+ << QStringList({ u"states binding with PropertyChanges in State"_s,
+ u"transitions binding with Transition"_s });
+
+ // forbid transitions and states because QtObject does not inherit from Item
+ QTest::newRow("qtObjectEmptyLineSnippets")
+ << file << 141 << 8
+ << ExpectedCompletions{ { u"Item"_s, CompletionItemKind::Constructor } }
+ << QStringList({ u"transitions binding with Transition"_s,
+ u"states binding with PropertyChanges in State"_s });
+
+ QTest::newRow("handlers") << file << 5 << 1
+ << ExpectedCompletions{ {
+ { u"onHandleMe"_s, CompletionItemKind::Method },
+ { u"onDefaultPropertyChanged"_s,
+ CompletionItemKind::Method },
+ } }
+ << QStringList({ u"QtQuick"_s, u"vector4d"_s });
+
+ QTest::newRow("attachedTypes")
+ << file << 9 << 1 << attachedTypes << QStringList{ u"QtQuick"_s, u"vector4d"_s };
+
+ QTest::newRow("attachedTypesInScript")
+ << file << 6 << 12 << attachedTypes << QStringList{ u"QtQuick"_s, u"vector4d"_s };
+ QTest::newRow("attachedTypesInLongScript")
+ << file << 10 << 16 << attachedTypes << QStringList{ u"QtQuick"_s, u"vector4d"_s };
+
+ QTest::newRow("completionFromRootId") << file << 10 << 21
+ << ExpectedCompletions({
+ { u"width"_s, CompletionItemKind::Property },
+ { u"lala"_s, CompletionItemKind::Method },
+ { u"foo"_s, CompletionItemKind::Property },
+ })
+ << QStringList{ u"QtQuick"_s, u"vector4d"_s };
+
+ QTest::newRow("attachedProperties") << file << 89 << 15
+ << ExpectedCompletions({
+ { u"onCompleted"_s, CompletionItemKind::Method },
+ })
+ << QStringList{ u"QtQuick"_s,
+ u"vector4d"_s,
+ attachedTypeName,
+ u"Rectangle"_s,
+ u"property"_s,
+ u"foo"_s,
+ u"onActiveFocusOnTabChanged"_s };
+
+ QTest::newRow("inBindingLabel") << file << 6 << 10
+ << ExpectedCompletions({
+ { u"Rectangle"_s, CompletionItemKind::Constructor },
+ { u"width"_s, CompletionItemKind::Property },
+ })
+ << QStringList({ u"QtQuick"_s, u"vector4d"_s, u"property"_s });
+
+ QTest::newRow("afterBinding") << file << 6 << 11
+ << (ExpectedCompletions({
+ { u"height"_s, CompletionItemKind::Property },
+ { u"width"_s, CompletionItemKind::Property },
+ { u"Rectangle"_s, CompletionItemKind::Constructor },
+ { singletonName, CompletionItemKind::Class },
+ })
+ + attachedTypes)
+ << QStringList({ u"QtQuick"_s, u"property"_s, u"vector4d"_s });
+
+ QTest::newRow("jsGlobals") << file << 6 << 11
+ << ExpectedCompletions{ {
+ { u"console"_s, CompletionItemKind::Property },
+ { u"Math"_s, CompletionItemKind::Property },
+ } }
+ << QStringList({ u"QtQuick"_s, u"property"_s, u"vector4d"_s });
+
+ QTest::newRow("jsGlobals2") << file << 100 << 32
+ << ExpectedCompletions{ {
+ { u"abs"_s, CompletionItemKind::Method },
+ { u"log"_s, CompletionItemKind::Method },
+ { u"E"_s, CompletionItemKind::Property },
+ } }
+ << QStringList({ u"QtQuick"_s, u"property"_s, u"vector4d"_s,
+ u"foo"_s, u"lala"_s });
+
+ QTest::newRow("afterLongBinding")
+ << file << 10 << 16
+ << ExpectedCompletions({
+ { u"height"_s, CompletionItemKind::Property },
+ { u"width"_s, CompletionItemKind::Property },
+ { u"Rectangle"_s, CompletionItemKind::Constructor },
+ })
+ << QStringList({ u"QtQuick"_s, u"property"_s, u"vector4d"_s });
+
+ QTest::newRow("afterId") << file << 5 << 8 << ExpectedCompletions({})
+ << QStringList({
+ u"QtQuick"_s,
+ u"property"_s,
+ u"Rectangle"_s,
+ u"width"_s,
+ u"vector4d"_s,
+ u"import"_s,
+ });
+
+ QTest::newRow("emptyFile") << emptyFile << 1 << 1
+ << ExpectedCompletions({
+ { u"import"_s, CompletionItemKind::Keyword },
+ { u"pragma"_s, CompletionItemKind::Keyword },
+ })
+ << QStringList({ u"QtQuick"_s, u"vector4d"_s, u"width"_s });
+
+ QTest::newRow("importImport") << file << 1 << 4
+ << ExpectedCompletions({
+ { u"import"_s, CompletionItemKind::Keyword },
+ })
+ << QStringList({ u"QtQuick"_s, u"vector4d"_s, u"width"_s,
+ u"Rectangle"_s });
+
+ QTest::newRow("importModuleStart")
+ << file << 1 << 8
+ << ExpectedCompletions({
+ { u"QtQuick"_s, CompletionItemKind::Module },
+ })
+ << QStringList({ u"vector4d"_s, u"width"_s, u"Rectangle"_s, u"import"_s });
+
+ QTest::newRow("importVersionStart")
+ << file << 1 << 16
+ << ExpectedCompletions({
+ { u"2"_s, CompletionItemKind::Constant },
+ { u"as"_s, CompletionItemKind::Keyword },
+ })
+ << QStringList({ u"Rectangle"_s, u"import"_s, u"vector4d"_s, u"width"_s });
+
+ // QTest::newRow("importVersionMinor")
+ // << uri << 1 << 18
+ // << ExpectedCompletions({
+ // { u"15"_s, CompletionItemKind::Constant },
+ // })
+ // << QStringList({ u"as"_s, u"Rectangle"_s, u"import"_s, u"vector4d"_s, u"width"_s });
+
+ QTest::newRow("expandBase1") << file << 10 << 24
+ << ExpectedCompletions({
+ { u"width"_s, CompletionItemKind::Property },
+ { u"foo"_s, CompletionItemKind::Property },
+ })
+ << QStringList({ u"import"_s, u"Rectangle"_s });
+
+ QTest::newRow("expandBase2") << file << 11 << 30
+ << ExpectedCompletions({
+ { u"width"_s, CompletionItemKind::Property },
+ { u"color"_s, CompletionItemKind::Property },
+ })
+ << QStringList({ u"foo"_s, u"import"_s, u"Rectangle"_s });
+
+ QTest::newRow("qualifiedTypeCompletionBeforeDot")
+ << testFile(u"qualifiedModule.qml"_s) << 4 << 31
+ << ExpectedCompletions({
+ { u"QQ.Rectangle"_s, CompletionItemKind::Constructor },
+ })
+ << QStringList({ u"foo"_s, u"import"_s, u"lala"_s, });
+
+ QTest::newRow("qualifiedTypeCompletionAfterDot")
+ << testFile(u"qualifiedModule.qml"_s) << 4 << 35
+ << ExpectedCompletions({
+ { u"Rectangle"_s, CompletionItemKind::Constructor },
+ })
+ << QStringList({ u"foo"_s, u"import"_s, u"lala"_s, u"width"_s });
+
+ QTest::newRow("qualifiedTypeCompletionBeforeDotInDefaultBinding")
+ << testFile(u"qualifiedModule.qml"_s) << 5 << 5
+ << ExpectedCompletions({
+ { u"QQ.Rectangle"_s, CompletionItemKind::Constructor },
+ })
+ << QStringList({ u"foo"_s, u"import"_s, u"lala"_s });
+
+ QTest::newRow("qualifiedTypeCompletionAfterDotInDefaultBinding")
+ << testFile(u"qualifiedModule.qml"_s) << 5 << 8
+ << ExpectedCompletions({
+ { u"Rectangle"_s, CompletionItemKind::Constructor },
+ })
+ << QStringList({ u"foo"_s, u"import"_s, u"lala"_s, u"width"_s });
+
+ QTest::newRow("parameterCompletion")
+ << file << 36 << 24
+ << ExpectedCompletions({
+ { u"helloWorld"_s, CompletionItemKind::Variable },
+ { u"helloMe"_s, CompletionItemKind::Variable },
+ })
+ << QStringList();
+
+ QTest::newRow("inMethodName") << file << 15 << 14 << ExpectedCompletions({})
+ << QStringList{ u"QtQuick"_s, u"vector4d"_s, u"foo"_s,
+ u"root"_s, u"Item"_s, singletonName };
+
+ QTest::newRow("inMethodReturnType") << file << 17 << 54 << mixedTypes
+ << QStringList{
+ u"QtQuick"_s,
+ u"foo"_s,
+ u"root"_s,
+ };
+
+ QTest::newRow("letStatement") << file << 95 << 13 << ExpectedCompletions({})
+ << QStringList{ u"QtQuick"_s, u"vector4d"_s, u"root"_s };
+
+ QTest::newRow("inParameterCompletion") << file << 35 << 39 << ExpectedCompletions({})
+ << QStringList{
+ u"helloWorld"_s,
+ u"helloMe"_s,
+ };
+
+ QTest::newRow("parameterTypeCompletion") << file << 35 << 55 << mixedTypes
+ << QStringList{
+ u"helloWorld"_s,
+ u"helloMe"_s,
+ };
+
+ QTest::newRow("propertyTypeCompletion") << file << 16 << 14 << mixedTypes
+ << QStringList{
+ u"helloWorld"_s,
+ u"helloMe"_s,
+ };
+ QTest::newRow("propertyTypeCompletion2") << file << 16 << 23 << mixedTypes
+ << QStringList{
+ u"helloWorld"_s,
+ u"helloMe"_s,
+ };
+ QTest::newRow("propertyNameCompletion")
+ << file << 16 << 24 << ExpectedCompletions({})
+ << QStringList{
+ u"helloWorld"_s, u"helloMe"_s, u"Zzz"_s, u"Item"_s, u"int"_s, u"date"_s,
+ };
+ QTest::newRow("propertyNameCompletion2")
+ << file << 16 << 25 << ExpectedCompletions({})
+ << QStringList{
+ u"helloWorld"_s, u"helloMe"_s, u"Zzz"_s, u"Item"_s, u"int"_s, u"date"_s,
+ };
+
+ QTest::newRow("propertyDefinitionBinding")
+ << file << 90 << 27
+ << (ExpectedCompletions({
+ { u"lala"_s, CompletionItemKind::Method },
+ { u"createRectangle"_s, CompletionItemKind::Method },
+ { u"createItem"_s, CompletionItemKind::Method },
+ { u"createAnything"_s, CompletionItemKind::Method },
+ }) += constructorTypes)
+ << QStringList{
+ u"helloWorld"_s,
+ u"helloMe"_s,
+ u"int"_s,
+ u"date"_s,
+ };
+
+ QTest::newRow("ignoreNonRelatedTypesForPropertyDefinitionBinding")
+ << file << 16 << 28
+ << (ExpectedCompletions({
+ { u"createRectangle"_s, CompletionItemKind::Method },
+ { u"createItem"_s, CompletionItemKind::Method },
+ { u"createAnything"_s, CompletionItemKind::Method },
+ }) += rectangleTypes)
+ << QStringList{
+ u"Item"_s, u"Zzz"_s, u"helloWorld"_s, u"helloMe"_s,
+ u"int"_s, u"date"_s, u"Item"_s, u"QtObject"_s,
+ };
+
+ QTest::newRow("inBoundObject")
+ << file << 16 << 40
+ << (ExpectedCompletions({
+ { u"objectName"_s, CompletionItemKind::Property },
+ { u"width"_s, CompletionItemKind::Property },
+ { propertyCompletion, CompletionItemKind::Snippet },
+ { functionCompletion, CompletionItemKind::Snippet },
+ }) += constructorTypes)
+ << QStringList{
+ u"helloWorld"_s, u"helloMe"_s, u"int"_s, u"date"_s, u"QtQuick"_s, u"vector4d"_s,
+ };
+
+ QTest::newRow("qualifiedIdentifierCompletion")
+ << file << 37 << 36
+ << ExpectedCompletions({
+ { u"helloProperty"_s, CompletionItemKind::Property },
+ { u"childAt"_s, CompletionItemKind::Method },
+ })
+ << QStringList{ u"helloVar"_s, u"someItem"_s, u"color"_s, u"helloWorld"_s,
+ u"propertyOfZZZ"_s };
+
+ QTest::newRow("scriptExpressionCompletion")
+ << file << 60 << 16
+ << ExpectedCompletions({
+ // parameters
+ { u"jsParameterInChild"_s, CompletionItemKind::Variable },
+ // own properties
+ { u"jsIdentifierInChild"_s, CompletionItemKind::Variable },
+ { u"functionInChild"_s, CompletionItemKind::Method },
+ { u"propertyInChild"_s, CompletionItemKind::Property },
+ // inherited properties from QML
+ { u"functionInBase"_s, CompletionItemKind::Method },
+ { u"propertyInBase"_s, CompletionItemKind::Property },
+ // inherited properties (transitive) from C++
+ { u"objectName"_s, CompletionItemKind::Property },
+ { u"someItem"_s, CompletionItemKind::Value },
+ { u"true"_s, CompletionItemKind::Value },
+ { u"false"_s, CompletionItemKind::Value },
+ { u"null"_s, CompletionItemKind::Value },
+ })
+ << QStringList{
+ u"helloVar"_s,
+ u"color"_s,
+ u"helloWorld"_s,
+ u"propertyOfZZZ"_s,
+ u"propertyInDerived"_s,
+ u"functionInDerived"_s,
+ u"jsIdentifierInDerived"_s,
+ u"jsIdentifierInBase"_s,
+ u"lala"_s,
+ u"foo"_s,
+ u"jsParameterInBase"_s,
+ u"jsParameterInDerived"_s,
+ };
+
+ QTest::newRow("qualifiedScriptExpressionCompletion")
+ << file << 60 << 34
+ << ExpectedCompletions({
+ // own properties
+ { u"helloProperty"_s, CompletionItemKind::Property },
+ // inherited properties (transitive) from C++
+ { u"width"_s, CompletionItemKind::Property },
+ })
+ << QStringList{
+ u"helloVar"_s,
+ u"color"_s,
+ u"helloWorld"_s,
+ u"propertyOfZZZ"_s,
+ u"propertyInDerived"_s,
+ u"functionInDerived"_s,
+ u"jsIdentifierInDerived"_s,
+ u"jsIdentifierInBase"_s,
+ u"jsIdentifierInChild"_s,
+ u"lala"_s,
+ u"foo"_s,
+ u"jsParameterInBase"_s,
+ u"jsParameterInDerived"_s,
+ u"jsParameterInChild"_s,
+ u"functionInChild"_s,
+ };
+
+ QTest::newRow("pragma") << pragmaFile << 1 << 8
+ << ExpectedCompletions({
+ { u"NativeMethodBehavior"_s, CompletionItemKind::Value },
+ { u"ComponentBehavior"_s, CompletionItemKind::Value },
+ { u"ListPropertyAssignBehavior"_s,
+ CompletionItemKind::Value },
+ { u"Singleton"_s, CompletionItemKind::Value },
+ // note: only complete the Addressible/Inaddressible part of
+ // ValueTypeBehavior!
+ { u"ValueTypeBehavior"_s, CompletionItemKind::Value },
+ })
+ << QStringList{
+ u"int"_s,
+ u"Rectangle"_s,
+ u"FunctionSignatureBehavior"_s,
+ u"Strict"_s,
+ };
+
+ QTest::newRow("pragmaValue") << pragmaFile << 2 << 30
+ << ExpectedCompletions({
+ { u"AcceptThisObject"_s, CompletionItemKind::Value },
+ { u"RejectThisObject"_s, CompletionItemKind::Value },
+ })
+ << QStringList{
+ u"int"_s,
+ u"Rectangle"_s,
+ u"FunctionSignatureBehavior"_s,
+ u"Strict"_s,
+ u"NativeMethodBehavior"_s,
+ u"ComponentBehavior"_s,
+ u"ListPropertyAssignBehavior"_s,
+ u"Singleton"_s,
+ u"ValueTypeBehavior"_s,
+ u"Unbound"_s,
+ };
+
+ QTest::newRow("pragmaMultiValue")
+ << pragmaFile << 3 << 43
+ << ExpectedCompletions({
+ { u"ReplaceIfNotDefault"_s, CompletionItemKind::Value },
+ { u"Append"_s, CompletionItemKind::Value },
+ { u"Replace"_s, CompletionItemKind::Value },
+ })
+ << QStringList{
+ u"int"_s,
+ u"Rectangle"_s,
+ u"FunctionSignatureBehavior"_s,
+ u"Strict"_s,
+ u"NativeMethodBehavior"_s,
+ u"ComponentBehavior"_s,
+ u"ListPropertyAssignBehavior"_s,
+ u"Singleton"_s,
+ u"ValueTypeBehavior"_s,
+ u"Unbound"_s,
+ };
+
+ QTest::newRow("pragmaWithoutValue")
+ << pragmaFile << 1 << 17
+ << ExpectedCompletions({
+ { u"NativeMethodBehavior"_s, CompletionItemKind::Value },
+ { u"ComponentBehavior"_s, CompletionItemKind::Value },
+ { u"ListPropertyAssignBehavior"_s, CompletionItemKind::Value },
+ { u"Singleton"_s, CompletionItemKind::Value },
+ // note: only complete the Addressible/Inaddressible part of
+ // ValueTypeBehavior!
+ { u"ValueTypeBehavior"_s, CompletionItemKind::Value },
+ })
+ << QStringList{
+ u"int"_s,
+ u"Rectangle"_s,
+ u"FunctionSignatureBehavior"_s,
+ u"Strict"_s,
+ };
+
+ QTest::newRow("non-block-scoped-variable")
+ << file << 69 << 21
+ << ExpectedCompletions({
+ { u"helloVarVariable"_s, CompletionItemKind::Variable },
+ })
+ << QStringList{};
+ QTest::newRow("block-scoped-variable")
+ << file << 76 << 21 << ExpectedCompletions{ { u"test2"_s, CompletionItemKind::Method } }
+ << QStringList{ u"helloLetVariable"_s, u"helloVarVariable"_s };
+
+ QTest::newRow("singleton") << file << 78 << 33
+ << ExpectedCompletions({
+ { singletonName, CompletionItemKind::Class },
+ })
+ << QStringList{};
+
+ QTest::newRow("singletonPropertyAndEnums")
+ << file << 78 << 52
+ << ExpectedCompletions({
+ { u"byteOrder"_s, CompletionItemKind::Property },
+ { u"Little"_s, CompletionItemKind::EnumMember },
+ { u"Endian"_s, CompletionItemKind::Enum },
+ })
+ << QStringList{
+ u"int"_s,
+ u"Rectangle"_s,
+ u"foo"_s,
+ };
+
+ QTest::newRow("enumsFromItem") << file << 86 << 33
+ << ExpectedCompletions({
+ { u"World"_s, CompletionItemKind::EnumMember },
+ { u"ValueOne"_s, CompletionItemKind::EnumMember },
+ { u"ValueTwo"_s, CompletionItemKind::EnumMember },
+ { u"Hello"_s, CompletionItemKind::Enum },
+ { u"MyEnum"_s, CompletionItemKind::Enum },
+ })
+ << QStringList{
+ u"int"_s,
+ u"Rectangle"_s,
+ };
+
+ QTest::newRow("enumsFromEnumName")
+ << file << 87 << 40
+ << ExpectedCompletions({
+ { u"World"_s, CompletionItemKind::EnumMember },
+ })
+ << QStringList{
+ u"int"_s, u"Rectangle"_s, u"foo"_s, u"ValueOne"_s,
+ u"ValueTwo"_s, u"Hello"_s, u"MyEnum"_s,
+ };
+
+ QTest::newRow("requiredProperty")
+ << file << 97 << 14
+ << ExpectedCompletions({
+ { u"property"_s, CompletionItemKind::Keyword },
+ { u"default"_s, CompletionItemKind::Keyword },
+ })
+ << QStringList{
+ u"readonly"_s, u"required"_s, u"int"_s, u"Rectangle"_s, u"foo"_s,
+ u"ValueOne"_s, u"ValueTwo"_s, u"Hello"_s, u"MyEnum"_s,
+ };
+
+ QTest::newRow("readonlyProperty")
+ << file << 98 << 13
+ << ExpectedCompletions({
+ { u"property"_s, CompletionItemKind::Keyword },
+ { u"default"_s, CompletionItemKind::Keyword },
+ })
+ << QStringList{
+ u"required"_s, u"readonly"_s, u"int"_s, u"Rectangle"_s, u"foo"_s,
+ u"ValueOne"_s, u"ValueTwo"_s, u"Hello"_s, u"MyEnum"_s,
+ };
+
+ QTest::newRow("defaultProperty")
+ << file << 99 << 12
+ << ExpectedCompletions({
+ { u"property"_s, CompletionItemKind::Keyword },
+ { u"readonly"_s, CompletionItemKind::Keyword },
+ { u"required"_s, CompletionItemKind::Keyword },
+ })
+ << QStringList{
+ u"default"_s, u"int"_s, u"Rectangle"_s, u"foo"_s,
+ u"ValueOne"_s, u"ValueTwo"_s, u"Hello"_s, u"MyEnum"_s,
+ };
+
+ QTest::newRow("defaultProperty2")
+ << file << 99 << 20
+ << ExpectedCompletions({
+ { u"property"_s, CompletionItemKind::Keyword },
+ { u"readonly"_s, CompletionItemKind::Keyword },
+ { u"required"_s, CompletionItemKind::Keyword },
+ })
+ << QStringList{
+ u"default"_s, u"int"_s, u"Rectangle"_s, u"foo"_s,
+ u"ValueOne"_s, u"ValueTwo"_s, u"Hello"_s, u"MyEnum"_s,
+ };
+
+ QTest::newRow("defaultProperty3")
+ << file << 99 << 21 << ExpectedCompletions{ { u"int"_s, CompletionItemKind::Class } }
+ << QStringList{
+ u"property"_s,
+ u"readonly"_s,
+ u"required"_s,
+ };
+
+ const QString forStatementCompletion = u"for (initializer; condition; increment) { statements... }"_s;
+ const QString ifStatementCompletion = u"if (condition) statement"_s;
+ const QString letStatementCompletion = u"let variable = value;"_s;
+ const QString constStatementCompletion = u"const variable = value;"_s;
+ const QString varStatementCompletion = u"var variable = value;"_s;
+
+ // for the for loop
+ const QString letStatementCompletionWithoutSemicolon = letStatementCompletion.chopped(1);
+ const QString constStatementCompletionWithoutSemicolon = constStatementCompletion.chopped(1);
+ const QString varStatementCompletionWithoutSemicolon = varStatementCompletion.chopped(1);
+
+ const QString caseStatementCompletion = u"case value: statements..."_s;
+ const QString caseStatement2Completion = u"case value: { statements... }"_s;
+ const QString defaultStatementCompletion = u"default: statements..."_s;
+ const QString defaultStatement2Completion = u"default: { statements... }"_s;
+
+ // warning: the completion strings in the test below were all tested by hand in VS Code to
+ // make sure they are easy to use. Make sure to check the code snippets by hand before changing
+ // them.
+ QTest::newRow("jsStatements")
+ << file << 104 << 1
+ << ExpectedCompletions{ { letStatementCompletion, CompletionItemKind::Snippet,
+ u"let ${1:variable} = $0;"_s },
+ { u"const variable = value;"_s, CompletionItemKind::Snippet,
+ u"const ${1:variable} = $0;"_s },
+ { u"var variable = value;"_s, CompletionItemKind::Snippet,
+ u"var ${1:variable} = $0;"_s },
+ { u"{ statements... }"_s, CompletionItemKind::Snippet,
+ u"{\n\t$0\n}"_s },
+ { u"if (condition) { statements }"_s,
+ CompletionItemKind::Snippet, u"if ($1) {\n\t$0\n}"_s },
+ { u"do { statements } while (condition);"_s,
+ CompletionItemKind::Snippet, u"do {\n\t$1\n} while ($0);"_s },
+ { u"while (condition) { statements...}"_s,
+ CompletionItemKind::Snippet, u"while ($1) {\n\t$0\n}"_s },
+ { forStatementCompletion,
+ CompletionItemKind::Snippet, u"for ($1;$2;$3) {\n\t$0\n}"_s },
+ { u"try { statements... } catch(error) { statements... }"_s,
+ CompletionItemKind::Snippet, u"try {\n\t$1\n} catch($2) {\n\t$0\n}"_s },
+ { u"try { statements... } finally { statements... }"_s,
+ CompletionItemKind::Snippet, u"try {\n\t$1\n} finally {\n\t$0\n}"_s },
+ { u"try { statements... } catch(error) { statements... } finally { statements... }"_s,
+ CompletionItemKind::Snippet, u"try {\n\t$1\n} catch($2) {\n\t$3\n} finally {\n\t$0\n}"_s },
+ { u"for (property in object) { statements... }"_s,
+ CompletionItemKind::Snippet, u"for ($1 in $2) {\n\t$0\n}"_s },
+ { u"for (element of array) { statements... }"_s,
+ CompletionItemKind::Snippet, u"for ($1 of $2) {\n\t$0\n}"_s },
+ { u"continue"_s, CompletionItemKind::Keyword },
+ { u"break"_s, CompletionItemKind::Keyword },
+ }
+ << QStringList{ caseStatementCompletion,
+ caseStatement2Completion,
+ defaultStatementCompletion,
+ defaultStatement2Completion,
+ };
+
+ QTest::newRow("forStatementLet")
+ << file << 103 << 13
+ << ExpectedCompletions{ { letStatementCompletionWithoutSemicolon,
+ CompletionItemKind::Snippet, u"let ${1:variable} = $0"_s },
+ { constStatementCompletionWithoutSemicolon,
+ CompletionItemKind::Snippet, u"const ${1:variable} = $0"_s },
+ { varStatementCompletionWithoutSemicolon,
+ CompletionItemKind::Snippet, u"var ${1:variable} = $0"_s },
+ { u"helloJSStatements"_s, CompletionItemKind::Method } }
+ << QStringList{ u"property"_s,
+ u"readonly"_s,
+ u"required"_s,
+ forStatementCompletion,
+ ifStatementCompletion,
+ letStatementCompletion,
+ constStatementCompletion,
+ varStatementCompletion };
+
+ QTest::newRow("forStatementCondition")
+ << file << 103 << 25
+ << ExpectedCompletions{
+ { u"helloJSStatements"_s, CompletionItemKind::Method },
+ { u"i"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ u"property"_s, u"readonly"_s, u"required"_s,
+ forStatementCompletion, ifStatementCompletion, varStatementCompletion,
+ letStatementCompletion, constStatementCompletion, }
+ ;
+
+ QTest::newRow("forStatementIncrement")
+ << file << 103 << 30
+ << ExpectedCompletions{
+ { u"helloJSStatements"_s, CompletionItemKind::Method },
+ { u"i"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ u"property"_s, u"readonly"_s, u"required"_s,
+ forStatementCompletion, ifStatementCompletion, varStatementCompletion,
+ letStatementCompletion, constStatementCompletion, }
+ ;
+
+ QTest::newRow("forStatementIncrement2")
+ << file << 103 << 33
+ << ExpectedCompletions{ { u"helloJSStatements"_s, CompletionItemKind::Method } }
+ << QStringList{
+ u"property"_s, u"readonly"_s,
+ u"required"_s, forStatementCompletion,
+ ifStatementCompletion, varStatementCompletion,
+ letStatementCompletion, constStatementCompletion,
+ };
+
+ QTest::newRow("forStatementWithoutBlock")
+ << file << 107 << 12
+ << ExpectedCompletions{ { letStatementCompletion, CompletionItemKind::Snippet },
+ { constStatementCompletion, CompletionItemKind::Snippet },
+ { varStatementCompletion, CompletionItemKind::Snippet },
+ { u"helloJSStatements"_s, CompletionItemKind::Method },
+ { u"j"_s, CompletionItemKind::Variable },
+ { forStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{ propertyCompletion };
+
+ QTest::newRow("blockStatementBeforeBracket")
+ << file << 103 << 36
+ << ExpectedCompletions{ { letStatementCompletion, CompletionItemKind::Snippet },
+ { constStatementCompletion, CompletionItemKind::Snippet },
+ { varStatementCompletion, CompletionItemKind::Snippet },
+ { u"helloJSStatements"_s, CompletionItemKind::Method },
+ { u"i"_s, CompletionItemKind::Variable },
+ { forStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{ propertyCompletion };
+
+ QTest::newRow("blockStatementAfterBracket")
+ << file << 103 << 37
+ << ExpectedCompletions{ { letStatementCompletion, CompletionItemKind::Snippet },
+ { constStatementCompletion, CompletionItemKind::Snippet },
+ { varStatementCompletion, CompletionItemKind::Snippet },
+ { u"helloJSStatements"_s, CompletionItemKind::Method },
+ { forStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{ propertyCompletion };
+
+ QTest::newRow("ifStatementCondition")
+ << file << 110 << 15
+ << ExpectedCompletions{
+ { u"hello"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion, constStatementCompletion }
+ ;
+
+ QTest::newRow("ifStatementConsequence")
+ << file << 111 << 12
+ << ExpectedCompletions{ { letStatementCompletion, CompletionItemKind::Snippet },
+ { constStatementCompletion, CompletionItemKind::Snippet },
+ { varStatementCompletion, CompletionItemKind::Snippet },
+ { u"hello"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion }
+ ;
+
+ QTest::newRow("ifStatementAlternative")
+ << file << 113 << 12
+ << ExpectedCompletions{ { letStatementCompletion, CompletionItemKind::Snippet },
+ { constStatementCompletion, CompletionItemKind::Snippet },
+ { varStatementCompletion, CompletionItemKind::Snippet },
+ { u"hello"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion }
+ ;
+
+ QTest::newRow("binaryExpressionCompletionInsideStatement")
+ << file << 113 << 21
+ << ExpectedCompletions{ { u"hello"_s, CompletionItemKind::Variable }, }
+ << QStringList{ propertyCompletion, forStatementCompletion }
+ ;
+
+ QTest::newRow("elseIfStatement")
+ << file << 121 << 18
+ << ExpectedCompletions{ { u"hello"_s, CompletionItemKind::Variable }, }
+ << QStringList{ propertyCompletion, letStatementCompletion, ifStatementCompletion }
+ ;
+ QTest::newRow("returnStatement")
+ << file << 125 << 16
+ << ExpectedCompletions{ { u"hello"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+ QTest::newRow("returnStatement2")
+ << testFile("completions/returnStatement.qml") << 8 << 15
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable }, }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("whileCondition")
+ << file << 128 << 16
+ << ExpectedCompletions{ { u"hello"_s, CompletionItemKind::Variable }, }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("whileConsequence")
+ << file << 128 << 22
+ << ExpectedCompletions{ { u"hello"_s, CompletionItemKind::Variable },
+ { letStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{ propertyCompletion };
+
+ QTest::newRow("doWhileCondition")
+ << file << 131 << 30
+ << ExpectedCompletions{ { u"hello"_s, CompletionItemKind::Variable }, }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("doWhileConsequence")
+ << file << 131 << 12
+ << ExpectedCompletions{ { u"hello"_s, CompletionItemKind::Variable },
+ { letStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{ propertyCompletion };
+
+ QTest::newRow("forInStatementLet")
+ << file << 134 << 13
+ << ExpectedCompletions{ { letStatementCompletion, CompletionItemKind::Snippet },
+ { constStatementCompletion, CompletionItemKind::Snippet },
+ { varStatementCompletion, CompletionItemKind::Snippet },
+ { u"helloJSStatements"_s, CompletionItemKind::Method } }
+ << QStringList{
+ u"property"_s, u"readonly"_s, u"required"_s,
+ forStatementCompletion, ifStatementCompletion,
+ };
+
+ QTest::newRow("forOfStatementLet")
+ << file << 135 << 13
+ << ExpectedCompletions{ { letStatementCompletion, CompletionItemKind::Snippet },
+ { constStatementCompletion, CompletionItemKind::Snippet },
+ { varStatementCompletion, CompletionItemKind::Snippet },
+ { u"helloJSStatements"_s, CompletionItemKind::Method } }
+ << QStringList{
+ u"property"_s, u"readonly"_s, u"required"_s,
+ forStatementCompletion, ifStatementCompletion,
+ };
+
+ QTest::newRow("forInStatementTarget")
+ << file << 134 << 25
+ << ExpectedCompletions{
+ { u"helloJSStatements"_s, CompletionItemKind::Method },
+ { u"hello"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ u"property"_s, u"readonly"_s, u"required"_s,
+ forStatementCompletion, ifStatementCompletion, varStatementCompletion,
+ letStatementCompletion, constStatementCompletion, }
+ ;
+
+ QTest::newRow("forOfStatementTarget")
+ << file << 135 << 24
+ << ExpectedCompletions{
+ { u"helloJSStatements"_s, CompletionItemKind::Method },
+ { u"hello"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ u"property"_s, u"readonly"_s, u"required"_s,
+ forStatementCompletion, ifStatementCompletion, varStatementCompletion,
+ letStatementCompletion, constStatementCompletion, }
+ ;
+
+ QTest::newRow("forInStatementConsequence")
+ << file << 134 << 31
+ << ExpectedCompletions{ { letStatementCompletion, CompletionItemKind::Snippet },
+ { constStatementCompletion, CompletionItemKind::Snippet },
+ { varStatementCompletion, CompletionItemKind::Snippet },
+ { u"helloJSStatements"_s, CompletionItemKind::Method },
+ { u"hello"_s, CompletionItemKind::Variable },
+ { forStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{ propertyCompletion };
+
+ QTest::newRow("forOfStatementConsequence")
+ << file << 135 << 30
+ << ExpectedCompletions{ { letStatementCompletion, CompletionItemKind::Snippet },
+ { constStatementCompletion, CompletionItemKind::Snippet },
+ { varStatementCompletion, CompletionItemKind::Snippet },
+ { u"helloJSStatements"_s, CompletionItemKind::Method },
+ { u"hello"_s, CompletionItemKind::Variable },
+ { forStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{ propertyCompletion };
+
+ QTest::newRow("binaryExpressionRHS") << file << 138 << 17
+ << ExpectedCompletions{
+ { u"log"_s, CompletionItemKind::Method },
+ { u"error"_s, CompletionItemKind::Method },
+ }
+ << QStringList{ propertyCompletion, u"helloVarVariable"_s,
+ u"test1"_s, u"width"_s,
+ u"height"_s, u"layer"_s,
+ u"left"_s, forStatementCompletion }
+ ;
+ QTest::newRow("binaryExpressionLHS") << file << 138 << 12
+ << ExpectedCompletions{
+ { u"qualifiedScriptIdentifiers"_s, CompletionItemKind::Method },
+ { u"width"_s, CompletionItemKind::Property },
+ { u"layer"_s, CompletionItemKind::Property },
+ }
+ << QStringList{ u"log"_s, u"error"_s, forStatementCompletion}
+ ;
+
+ const QString missingRHSFile = testFile(u"completions/missingRHS.qml"_s);
+ QTest::newRow("binaryExpressionMissingRHS") << missingRHSFile << 12 << 25
+ << ExpectedCompletions{
+ { u"good"_s, CompletionItemKind::Property },
+ }
+ << QStringList{ propertyCompletion, u"bad"_s }
+ ;
+ QTest::newRow("binaryExpressionMissingRHSWithDefaultProperty") << missingRHSFile << 14 << 33
+ << ExpectedCompletions{
+ { u"good"_s, CompletionItemKind::Property },
+ }
+ << QStringList{ propertyCompletion, u"bad"_s, u"helloSubItem"_s }
+ ;
+
+ QTest::newRow("binaryExpressionMissingRHSWithSemicolon")
+ << testFile(u"completions/missingRHS.parserfail.qml"_s)
+ << 5 << 22
+ << ExpectedCompletions{
+ { u"good"_s, CompletionItemKind::Property },
+ }
+ << QStringList{ propertyCompletion, u"bad"_s, u"helloSubItem"_s }
+ ;
+
+ QTest::newRow("binaryExpressionMissingRHSWithStatement") <<
+ testFile(u"completions/missingRHS.parserfail.qml"_s)
+ << 6 << 22
+ << ExpectedCompletions{
+ { u"good"_s, CompletionItemKind::Property },
+ }
+ << QStringList{ propertyCompletion, u"bad"_s, u"helloSubItem"_s }
+ ;
+
+ QTest::newRow("tryStatements")
+ << testFile(u"completions/tryStatements.qml"_s) << 5 << 14
+ << ExpectedCompletions{ { letStatementCompletion, CompletionItemKind::Snippet },
+ { forStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{};
+
+ QTest::newRow("tryStatementsCatchParameter")
+ << testFile(u"completions/tryStatements.qml"_s) << 5 << 23 << ExpectedCompletions{}
+ << QStringList{ letStatementCompletion, forStatementCompletion };
+
+ QTest::newRow("tryStatementsCatchBlock")
+ << testFile(u"completions/tryStatements.qml"_s) << 5 << 27
+ << ExpectedCompletions{ { letStatementCompletion, CompletionItemKind::Snippet },
+ { forStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{};
+
+ QTest::newRow("tryStatementsFinallyBlock")
+ << testFile(u"completions/tryStatements.qml"_s) << 5 << 39
+ << ExpectedCompletions{ { letStatementCompletion, CompletionItemKind::Snippet },
+ { forStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{};
+
+ QTest::newRow("inSwitchExpression")
+ << testFile(u"completions/switchStatements.qml"_s) << 10 << 16
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"myProperty"_s, CompletionItemKind::Property } }
+ << QStringList{
+ letStatementCompletion,
+ propertyCompletion,
+ };
+
+ QTest::newRow("beforeCaseStatement")
+ << testFile(u"completions/switchStatements.qml"_s) << 11 << 1
+ << ExpectedCompletions{ { caseStatementCompletion, CompletionItemKind::Snippet },
+ { caseStatement2Completion, CompletionItemKind::Snippet },
+ { defaultStatementCompletion, CompletionItemKind::Snippet },
+ { defaultStatement2Completion, CompletionItemKind::Snippet } }
+ << QStringList{ letStatementCompletion, propertyCompletion, u"x"_s, u"myProperty"_s };
+ QTest::newRow("inCaseExpression")
+ << testFile(u"completions/switchStatements.qml"_s) << 12 << 14
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { u"myProperty"_s, CompletionItemKind::Property } }
+ << QStringList{ letStatementCompletion, propertyCompletion, caseStatementCompletion };
+ QTest::newRow("inCaseStatementList")
+ << testFile(u"completions/switchStatements.qml"_s) << 13 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { caseStatementCompletion, CompletionItemKind::Snippet },
+ { defaultStatementCompletion, CompletionItemKind::Snippet },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { u"break"_s, CompletionItemKind::Keyword },
+ { u"return"_s, CompletionItemKind::Keyword },
+ { u"myProperty"_s, CompletionItemKind::Property } }
+ << QStringList{ propertyCompletion };
+ QTest::newRow("inDefaultStatementList")
+ << testFile(u"completions/switchStatements.qml"_s) << 24 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { caseStatementCompletion, CompletionItemKind::Snippet },
+ { defaultStatementCompletion, CompletionItemKind::Snippet },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { u"break"_s, CompletionItemKind::Keyword },
+ { u"return"_s, CompletionItemKind::Keyword },
+ { u"myProperty"_s, CompletionItemKind::Property } }
+ << QStringList{ propertyCompletion };
+ QTest::newRow("inMoreCasesStatementList")
+ << testFile(u"completions/switchStatements.qml"_s) << 26 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { caseStatementCompletion, CompletionItemKind::Snippet },
+ { defaultStatementCompletion, CompletionItemKind::Snippet },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { u"break"_s, CompletionItemKind::Keyword },
+ { u"return"_s, CompletionItemKind::Keyword },
+ { u"myProperty"_s, CompletionItemKind::Property } }
+ << QStringList{ propertyCompletion };
+
+ QTest::newRow("inCaseBeforeBlock")
+ << testFile(u"completions/switchStatements.qml"_s) << 14 << 23
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { caseStatementCompletion, CompletionItemKind::Snippet },
+ { defaultStatementCompletion, CompletionItemKind::Snippet },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { u"myProperty"_s, CompletionItemKind::Property } }
+ << QStringList{
+ propertyCompletion,
+ };
+ QTest::newRow("inCaseBeforeBlock2")
+ << testFile(u"completions/switchStatements.qml"_s) << 14 << 24
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { u"myProperty"_s, CompletionItemKind::Property } }
+ << QStringList{
+ propertyCompletion,
+ };
+
+ QTest::newRow("inCaseNestedStatement")
+ << testFile(u"completions/switchStatements.qml"_s) << 16 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { u"myProperty"_s, CompletionItemKind::Property } }
+ << QStringList{ propertyCompletion, caseStatementCompletion,
+ defaultStatementCompletion };
+
+ QTest::newRow("inCaseAfterBlock")
+ << testFile(u"completions/switchStatements.qml"_s) << 22 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { caseStatementCompletion, CompletionItemKind::Snippet },
+ { defaultStatementCompletion, CompletionItemKind::Snippet },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { u"myProperty"_s, CompletionItemKind::Property } }
+ << QStringList{
+ propertyCompletion,
+ };
+
+ QTest::newRow("inCaseBeforeDefault")
+ << testFile(u"completions/switchStatements.qml"_s) << 23 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { caseStatementCompletion, CompletionItemKind::Snippet },
+ { defaultStatementCompletion, CompletionItemKind::Snippet },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { u"myProperty"_s, CompletionItemKind::Property } }
+ << QStringList{
+ propertyCompletion,
+ };
+
+ QTest::newRow("inCaseAfterDefault")
+ << testFile(u"completions/switchStatements.qml"_s) << 25 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { caseStatementCompletion, CompletionItemKind::Snippet },
+ { defaultStatementCompletion, CompletionItemKind::Snippet },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { u"myProperty"_s, CompletionItemKind::Property } }
+ << QStringList{
+ propertyCompletion,
+ };
+
+ QTest::newRow("beforeAnyCase")
+ << testFile(u"completions/switchStatements.qml"_s) << 20 << 1
+ << ExpectedCompletions{ { caseStatementCompletion, CompletionItemKind::Snippet },
+ { defaultStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{ propertyCompletion, letStatementCompletion, u"myProperty"_s, u"x"_s,
+ u"f"_s };
+
+ QTest::newRow("beforeAnyDefault")
+ << testFile(u"completions/switchStatements.qml"_s) << 32 << 1
+ << ExpectedCompletions{ { caseStatementCompletion, CompletionItemKind::Snippet },
+ { defaultStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{ propertyCompletion, letStatementCompletion, u"myProperty"_s, u"x"_s,
+ u"f"_s };
+ QTest::newRow("inDefaultAfterDefault")
+ << testFile(u"completions/switchStatements.qml"_s) << 33 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { caseStatementCompletion, CompletionItemKind::Snippet },
+ { defaultStatementCompletion, CompletionItemKind::Snippet },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { u"myProperty"_s, CompletionItemKind::Property } }
+ << QStringList{
+ propertyCompletion,
+ };
+
+ // variableDeclaration.qml tests for let/const/var statements + destructuring
+
+ QTest::newRow("letStatement") << testFile(u"completions/variableDeclaration.qml"_s) << 7 << 13
+ << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, letStatementCompletion,
+ u"x"_s, u"data"_s };
+
+ QTest::newRow("letStatement2")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 7 << 26
+ << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, letStatementCompletion, u"x"_s, u"data"_s };
+
+ QTest::newRow("letStatementBehindEqual")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 7 << 28
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("letStatementBehindEqual2")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 7 << 33
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("constStatement")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 8 << 19
+ << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, letStatementCompletion, u"x"_s, u"data"_s };
+
+ QTest::newRow("constStatementBehindEqual")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 8 << 32
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("varStatement") << testFile(u"completions/variableDeclaration.qml"_s) << 9 << 17
+ << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, letStatementCompletion,
+ u"x"_s, u"data"_s };
+
+ QTest::newRow("varStatementBehindEqual")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 9 << 28
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("objectDeconstruction")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 13 << 20
+ << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, letStatementCompletion, u"x"_s, u"data"_s };
+
+ QTest::newRow("objectDeconstructionAloneBehindEqual")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 14 << 51
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("objectDeconstructionAloneBehindEqual2")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 14 << 58
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("objectDeconstruction2BehindEqual")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 15 << 83
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("objectDeconstruction2BehindEqual2")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 15 << 90
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("objectDeconstruction3BehindEqual")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 15 << 140
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("objectDeconstructionBehindComma")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 15 << 143
+ << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, letStatementCompletion, u"x"_s, u"data"_s };
+
+ QTest::newRow("objectDeconstructionBetweenObjects")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 15 << 50
+ << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, letStatementCompletion, u"x"_s, u"data"_s };
+
+ QTest::newRow("objectDeconstructionBetweenDeconstructions")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 15 << 97
+ << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, letStatementCompletion, u"x"_s, u"data"_s };
+
+ QTest::newRow("arrayDeconstructionAlone")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 19 << 24
+ << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, letStatementCompletion, u"x"_s, u"data"_s };
+
+ QTest::newRow("arrayDeconstructionAloneBehindEqual")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 19 << 33
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("arrayDeconstruction2")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 21 << 71
+ << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, letStatementCompletion, u"x"_s, u"data"_s };
+
+ QTest::newRow("arrayDeconstruction2BehindEqual")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 21 << 83
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+ QTest::newRow("arrayDeconstruction3")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 21 << 125
+ << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, letStatementCompletion, u"x"_s, u"data"_s };
+
+ QTest::newRow("arrayDeconstruction3BehindEqual")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 21 << 139
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("arrayDeconstructionIn_Wildcard")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 25 << 64
+ << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, letStatementCompletion, u"x"_s, u"data"_s };
+
+ QTest::newRow("arrayDeconstructionBehind+")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 25 << 132
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("objectDeconstructionForNeedle")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 29 << 111
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("arrayInObjectDeconstructionInObjectInitializer")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 33 << 44
+ << ExpectedCompletions{ {u"x"_s, CompletionItemKind::Variable},
+ {u"data"_s, CompletionItemKind::Method},
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion }
+ ;
+
+ QTest::newRow("arrayInObjectDeconstructionInObjectPropertyName")
+ << testFile(u"completions/variableDeclaration.qml"_s) << 33 << 26
+ << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, letStatementCompletion, u"x"_s, u"data"_s };
+
+ QTest::newRow("throwStatement")
+ << testFile(u"completions/throwStatement.qml"_s) << 8 << 15
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method } }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("throwStatement2")
+ << testFile(u"completions/throwStatement.qml"_s) << 9 << 20
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method } }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("labelledStatement")
+ << testFile(u"completions/labelledStatement.qml"_s) << 5 << 16
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { forStatementCompletion, CompletionItemKind::Snippet },
+ }
+ << QStringList{ propertyCompletion, };
+
+ QTest::newRow("nestedLabel")
+ << testFile(u"completions/labelledStatement.qml"_s) << 7 << 22
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { forStatementCompletion, CompletionItemKind::Snippet },
+ }
+ << QStringList{ propertyCompletion, };
+
+ QTest::newRow("nestedLabel2")
+ << testFile(u"completions/labelledStatement.qml"_s) << 8 << 26
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { forStatementCompletion, CompletionItemKind::Snippet },
+ }
+ << QStringList{ propertyCompletion, };
+
+ QTest::newRow("multiLabel")
+ << testFile(u"completions/labelledStatement.qml"_s) << 15 << 21
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { forStatementCompletion, CompletionItemKind::Snippet },
+ }
+ << QStringList{ propertyCompletion, };
+
+ QTest::newRow("multiLabel2")
+ << testFile(u"completions/labelledStatement.qml"_s) << 16 << 21
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"f"_s, CompletionItemKind::Method },
+ { letStatementCompletion, CompletionItemKind::Snippet },
+ { forStatementCompletion, CompletionItemKind::Snippet },
+ }
+ << QStringList{ propertyCompletion, };
+
+ QTest::newRow("continueNested")
+ << testFile(u"completions/continueAndBreakStatement.qml"_s) << 12 << 26
+ << ExpectedCompletions{ { u"nestedLabel1"_s, CompletionItemKind::Value },
+ { u"nestedLabel2"_s, CompletionItemKind::Value }, }
+ << QStringList{ propertyCompletion, u"x"_s, u"f"_s, u"multiLabel1"_s };
+
+ QTest::newRow("breakNested")
+ << testFile(u"completions/continueAndBreakStatement.qml"_s) << 13 << 23
+ << ExpectedCompletions{ { u"nestedLabel1"_s, CompletionItemKind::Value },
+ { u"nestedLabel2"_s, CompletionItemKind::Value }, }
+ << QStringList{ propertyCompletion, u"x"_s, u"f"_s, u"multiLabel1"_s };
+
+ QTest::newRow("continueMulti")
+ << testFile(u"completions/continueAndBreakStatement.qml"_s) << 20 << 22
+ << ExpectedCompletions{ { u"multiLabel1"_s, CompletionItemKind::Value },
+ { u"multiLabel2"_s, CompletionItemKind::Value }, }
+ << QStringList{ propertyCompletion, u"x"_s, u"f"_s, u"nestedLabel1"_s };
+
+ QTest::newRow("breakMulti")
+ << testFile(u"completions/continueAndBreakStatement.qml"_s) << 21 << 19
+ << ExpectedCompletions{ { u"multiLabel1"_s, CompletionItemKind::Value },
+ { u"multiLabel2"_s, CompletionItemKind::Value }, }
+ << QStringList{ propertyCompletion, u"x"_s, u"f"_s, u"nestedLabel1"_s };
+
+ QTest::newRow("continueNoLabel") << testFile(u"completions/continueAndBreakStatement.qml"_s)
+ << 25 << 22 << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, u"x"_s, u"f"_s,
+ u"nestedLabel1"_s, u"multiLabel1"_s };
+
+ QTest::newRow("breakNoLabel") << testFile(u"completions/continueAndBreakStatement.qml"_s) << 26
+ << 19 << ExpectedCompletions{}
+ << QStringList{ propertyCompletion, u"x"_s, u"f"_s,
+ u"nestedLabel1"_s, u"multiLabel1"_s };
+
+ QTest::newRow("insideMethodBody")
+ << testFile(u"completions/functionBody.qml"_s) << 5 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { forStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{ propertyCompletion };
+
+ QTest::newRow("insideMethodBody2")
+ << testFile(u"completions/functionBody.qml"_s) << 11 << 11
+ << ExpectedCompletions{ { u"helloProperty"_s, CompletionItemKind::Property }, }
+ << QStringList{ u"badProperty"_s, forStatementCompletion };
+
+ QTest::newRow("insideMethodBodyStart")
+ << testFile(u"completions/functionBody.qml"_s) << 11 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { forStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{ u"helloProperty"_s };
+
+ QTest::newRow("insideMethodBodyEnd")
+ << testFile(u"completions/functionBody.qml"_s) << 12 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { forStatementCompletion, CompletionItemKind::Snippet } }
+ << QStringList{ u"helloProperty"_s };
+
+ QTest::newRow("noBreakInMethodBody")
+ << testFile(u"completions/suggestContinueAndBreak.qml"_s) << 8 << 8
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable } }
+ << QStringList{ u"break"_s, u"continue"_s };
+
+ QTest::newRow("breakAndContinueInForLoop")
+ << testFile(u"completions/suggestContinueAndBreak.qml"_s) << 11 << 12
+ << ExpectedCompletions{ { u"break"_s, CompletionItemKind::Keyword },
+ { u"continue"_s, CompletionItemKind::Keyword },
+ }
+ << QStringList{};
+
+ QTest::newRow("noBreakInSwitch")
+ << testFile(u"completions/suggestContinueAndBreak.qml"_s) << 15 << 12
+ << ExpectedCompletions{ { caseStatementCompletion, CompletionItemKind::Snippet }, }
+ << QStringList{ u"continue"_s, u"break"_s };
+
+ QTest::newRow("breakInSwitchCase")
+ << testFile(u"completions/suggestContinueAndBreak.qml"_s) << 17 << 12
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"break"_s, CompletionItemKind::Keyword },
+ }
+ << QStringList{ u"continue"_s };
+
+ QTest::newRow("breakInSwitchDefault")
+ << testFile(u"completions/suggestContinueAndBreak.qml"_s) << 19 << 12
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"break"_s, CompletionItemKind::Keyword },
+ }
+ << QStringList{ u"continue"_s };
+
+ QTest::newRow("breakInSwitchSecondCase")
+ << testFile(u"completions/suggestContinueAndBreak.qml"_s) << 21 << 12
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"break"_s, CompletionItemKind::Keyword },
+ }
+ << QStringList{ u"continue"_s };
+
+ QTest::newRow("breakInLabel")
+ << testFile(u"completions/suggestContinueAndBreak.qml"_s) << 25 << 12
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"break"_s, CompletionItemKind::Keyword },
+ }
+ << QStringList{ u"continue"_s };
+
+ QTest::newRow("forLoopInsideOfLabel")
+ << testFile(u"completions/suggestContinueAndBreak.qml"_s) << 33 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"break"_s, CompletionItemKind::Keyword },
+ { u"continue"_s, CompletionItemKind::Keyword },
+ }
+ << QStringList{ };
+
+ QTest::newRow("switchInsideForLoopInsideOfLabel")
+ << testFile(u"completions/suggestContinueAndBreak.qml"_s) << 36 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"break"_s, CompletionItemKind::Keyword },
+ { u"continue"_s, CompletionItemKind::Keyword },
+ }
+ << QStringList{ };
+
+ QTest::newRow("switchInsideOfLabel")
+ << testFile(u"completions/suggestContinueAndBreak.qml"_s) << 45 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"break"_s, CompletionItemKind::Keyword },
+ }
+ << QStringList{ u"continue"_s };
+
+ QTest::newRow("forLoopInSwitchInsideOfLabel")
+ << testFile(u"completions/suggestContinueAndBreak.qml"_s) << 47 << 1
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ { u"break"_s, CompletionItemKind::Keyword },
+ { u"continue"_s, CompletionItemKind::Keyword },
+ }
+ << QStringList{ };
+
+ QTest::newRow("commaExpression")
+ << testFile(u"completions/commaExpression.qml"_s) << 5 << 18
+ << ExpectedCompletions{ { u"a"_s, CompletionItemKind::Variable },
+ { u"b"_s, CompletionItemKind::Variable },
+ { u"c"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion };
+
+ QTest::newRow("conditionalExpressionConsequence")
+ << testFile(u"completions/conditionalExpression.qml"_s) << 5 << 17
+ << ExpectedCompletions{ { u"a"_s, CompletionItemKind::Variable },
+ { u"b"_s, CompletionItemKind::Variable },
+ { u"c"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("conditionalExpressionAlternative")
+ << testFile(u"completions/conditionalExpression.qml"_s) << 5 << 30
+ << ExpectedCompletions{ { u"a"_s, CompletionItemKind::Variable },
+ { u"b"_s, CompletionItemKind::Variable },
+ { u"c"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("unaryMinus")
+ << testFile(u"completions/unaryExpression.qml"_s) << 5 << 10
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("unaryPlus")
+ << testFile(u"completions/unaryExpression.qml"_s) << 6 << 10
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("unaryTilde")
+ << testFile(u"completions/unaryExpression.qml"_s) << 7 << 10
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("unaryNot")
+ << testFile(u"completions/unaryExpression.qml"_s) << 8 << 10
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("typeof")
+ << testFile(u"completions/unaryExpression.qml"_s) << 9 << 16
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("delete")
+ << testFile(u"completions/unaryExpression.qml"_s) << 10 << 16
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("void")
+ << testFile(u"completions/unaryExpression.qml"_s) << 11 << 14
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("postDecrement")
+ << testFile(u"completions/unaryExpression.qml"_s) << 12 << 9
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("postIncrement")
+ << testFile(u"completions/unaryExpression.qml"_s) << 13 << 9
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("preDecrement")
+ << testFile(u"completions/unaryExpression.qml"_s) << 14 << 11
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("preIncrement")
+ << testFile(u"completions/unaryExpression.qml"_s) << 15 << 11
+ << ExpectedCompletions{ { u"x"_s, CompletionItemKind::Variable },
+ }
+ << QStringList{ propertyCompletion, letStatementCompletion };
+
+ QTest::newRow("attachedPropertyAfterDot")
+ << testFile("completions/attachedAndGroupedProperty.qml") << 8 << 15
+ << ExpectedCompletions({
+ { u"onCompleted"_s, CompletionItemKind::Method },
+ })
+ << QStringList{ u"QtQuick"_s, u"vector4d"_s, attachedTypeName, u"Rectangle"_s,
+ u"bad"_s };
+
+ QTest::newRow("groupedPropertyAfterDot")
+ << testFile("completions/attachedAndGroupedProperty.qml") << 10 << 15
+ << ExpectedCompletions({
+ { u"family"_s, CompletionItemKind::Property },
+ })
+ << QStringList{ u"QtQuick"_s, u"vector4d"_s, attachedTypeName, u"Rectangle"_s,
+ u"bad"_s, u"onCompleted"_s };
+
+ QTest::newRow("attachedPropertyAfterDotMissingRHS")
+ << testFile("completions/attachedPropertyMissingRHS.qml") << 7 << 17
+ << ExpectedCompletions({
+ { u"onCompleted"_s, CompletionItemKind::Method },
+ })
+ << QStringList{ u"QtQuick"_s, u"vector4d"_s, attachedTypeName, u"Rectangle"_s,
+ u"bad"_s };
+
+ QTest::newRow("groupedPropertyAfterDotMissingRHS")
+ << testFile("completions/groupedPropertyMissingRHS.qml") << 7 << 11
+ << ExpectedCompletions({
+ { u"family"_s, CompletionItemKind::Property },
+ })
+ << QStringList{ u"QtQuick"_s, u"vector4d"_s, attachedTypeName, u"Rectangle"_s,
+ u"bad"_s, u"onCompleted"_s };
+
+ QTest::newRow("dotFollowedByDefaultBinding")
+ << testFile("completions/afterDots.qml") << 11 << 31
+ << ExpectedCompletions({
+ { u"good"_s, CompletionItemKind::Property },
+ })
+ << QStringList{ u"bad"_s, u"QtQuick"_s, u"vector4d"_s,
+ attachedTypeName, u"Rectangle"_s, u"onCompleted"_s };
+
+ QTest::newRow("dotFollowedByBinding")
+ << testFile("completions/afterDots.qml") << 13 << 32
+ << ExpectedCompletions({
+ { u"good"_s, CompletionItemKind::Property },
+ })
+ << QStringList{ u"bad"_s, u"QtQuick"_s, u"vector4d"_s,
+ attachedTypeName, u"Rectangle"_s, u"onCompleted"_s };
+
+ QTest::newRow("dotFollowedByForStatement")
+ << testFile("completions/afterDots.qml") << 16 << 17
+ << ExpectedCompletions({
+ { u"good"_s, CompletionItemKind::Property },
+ })
+ << QStringList{
+ u"bad"_s, u"QtQuick"_s, u"vector4d"_s, attachedTypeName,
+ u"Rectangle"_s, u"onCompleted"_s, forStatementCompletion
+ };
+
+ QTest::newRow("qualifiedTypeCompletionWithoutQualifier")
+ << testFile("completions/quickcontrols_and_quicktemplates/qualifiedTypesCompletion.qml")
+ << 9 << 5
+ << ExpectedCompletions({
+ { u"T.Button"_s, CompletionItemKind::Constructor },
+ { u"Button"_s, CompletionItemKind::Constructor },
+ { u"Rectangle"_s, CompletionItemKind::Constructor },
+ })
+ << QStringList{ u"QtQuick"_s, u"vector4d"_s, u"bad"_s, u"onCompleted"_s };
+
+ QTest::newRow("qualifiedTypeCompletionWithoutQualifier2")
+ << testFile("completions/quickcontrols_and_quicktemplates/qualifiedTypesCompletion.qml")
+ << 10 << 19
+ << ExpectedCompletions({
+ { u"T.Button"_s, CompletionItemKind::Class },
+ { u"Button"_s, CompletionItemKind::Class },
+ { u"Rectangle"_s, CompletionItemKind::Class },
+ })
+ << QStringList{ u"QtQuick"_s, u"bad"_s, u"onCompleted"_s };
+
+ QTest::newRow("qualifiedTypeCompletionWithQualifier")
+ << testFile("completions/quickcontrols_and_quicktemplates/qualifiedTypesCompletion.qml")
+ << 9 << 7
+ << ExpectedCompletions({
+ { u"Button"_s, CompletionItemKind::Constructor },
+ })
+ << QStringList{ u"QtQuick"_s, u"vector4d"_s, attachedTypeName, u"Rectangle"_s,
+ u"bad"_s, u"onCompleted"_s, u"T.Button"_s };
+
+ QTest::newRow("qualifiedTypeCompletionWithQualifier2")
+ << testFile("completions/quickcontrols_and_quicktemplates/qualifiedTypesCompletion.qml")
+ << 10 << 21
+ << ExpectedCompletions({
+ { u"Button"_s, CompletionItemKind::Class },
+ })
+ << QStringList{ u"QtQuick"_s, attachedTypeName, u"Rectangle"_s,
+ u"bad"_s, u"onCompleted"_s, u"T.Button"_s };
+
+ QTest::newRow("parenthesizedExpression")
+ << testFile("completions/parenthesizedExpression.qml") << 8 << 10
+ << ExpectedCompletions({
+ { u"x"_s, CompletionItemKind::Variable },
+ })
+ << QStringList{ u"QtQuick"_s, u"Rectangle"_s, forStatementCompletion };
+
+ QTest::newRow("behindParenthesizedExpression")
+ << testFile("completions/parenthesizedExpression.qml") << 8 << 16
+ << ExpectedCompletions({})
+ << QStringList{ u"QtQuick"_s, attachedTypeName, u"Rectangle"_s, forStatementCompletion,
+ u"x"_s };
+
+ QTest::newRow("assumeBoundComponentsIdFromParent")
+ << testFile("completions/boundComponents.qml") << 14 << 33
+ << ExpectedCompletions{ { u"rootId"_s, CompletionItemKind::Value } }
+ << QStringList{ u"inRoot"_s };
+
+ QTest::newRow("assumeBoundComponentsPropertyFromParent")
+ << testFile("completions/boundComponents.qml") << 14 << 40
+ << ExpectedCompletions{ { u"inRoot"_s, CompletionItemKind::Property } }
+ << QStringList{ u"root"_s };
+}
+
+void tst_qmlls_utils::completions()
+{
+ QFETCH(QString, filePath);
+ QFETCH(int, line);
+ QFETCH(int, character);
+ QFETCH(ExpectedCompletions, expected);
+ QFETCH(QStringList, notExpected);
+
+ auto [env, file] = createEnvironmentAndLoadFile(filePath);
+
+ auto locations = QQmlLSUtils::itemsFromTextLocation(
+ file.field(QQmlJS::Dom::Fields::currentItem), line - 1, character - 1);
+
+ QEXPECT_FAIL("binaryExpressionMissingRHSWithSemicolon",
+ "Current parser cannot recover from this error yet!", Abort);
+ QEXPECT_FAIL("binaryExpressionMissingRHSWithStatement",
+ "Current parser cannot recover from this error yet!", Abort);
+ QCOMPARE(locations.size(), 1);
+
+ QString code;
+ {
+ QFile file(filePath);
+ QVERIFY(file.open(QIODeviceBase::ReadOnly));
+ code = QString::fromUtf8(file.readAll());
+ }
+
+ qsizetype pos = QQmlLSUtils::textOffsetFrom(code, line - 1, character - 1);
+ CompletionContextStrings ctxt{ code, pos };
+ QQmlLSCompletion completionEngine(m_pluginLoader);
+ QList<CompletionItem> completions =
+ completionEngine.completions(locations.front().domItem, ctxt);
+
+ if (expected.isEmpty()) {
+ if constexpr (enable_debug_output) {
+ if (!completions.isEmpty()) {
+ QStringList unexpected;
+ for (const auto &current : completions) {
+ unexpected << current.label;
+ }
+ qDebug() << "Received unexpected completions:" << unexpected.join(u", ");
+ }
+ }
+ QEXPECT_FAIL("singleton", "completion not implemented yet!", Abort);
+ QVERIFY(completions.isEmpty());
+ return;
+ }
+
+ QSet<QString> labels;
+ QStringList sortedLabels;
+ QDuplicateTracker<QByteArray> modulesTracker;
+ QDuplicateTracker<QByteArray> keywordsTracker;
+ QDuplicateTracker<QByteArray> classesTracker;
+ QDuplicateTracker<QByteArray> fieldsTracker;
+ QDuplicateTracker<QByteArray> propertiesTracker;
+ QDuplicateTracker<QByteArray> snippetTracker;
+
+ // avoid QEXPECT_FAIL tests to XPASS when completion order changes
+ std::sort(completions.begin(), completions.end(),
+ [](const CompletionItem&a, const CompletionItem&b) {return a.label < b.label;});
+
+ for (const CompletionItem &c : completions) {
+ // explicitly forbid marker structs created by QQmlJSImporter
+ QVERIFY(!c.label.contains("$internal$."));
+ QVERIFY(!c.label.contains("$module$."));
+ QVERIFY(!c.label.contains("$anonymous$."));
+
+ if (c.kind->toInt() == int(CompletionItemKind::Module)) {
+ QVERIFY2(!modulesTracker.hasSeen(c.label), "Duplicate module: " + c.label);
+ } else if (c.kind->toInt() == int(CompletionItemKind::Keyword)) {
+ QVERIFY2(!keywordsTracker.hasSeen(c.label), "Duplicate keyword: " + c.label);
+ } else if (c.kind->toInt() == int(CompletionItemKind::Class)) {
+ QVERIFY2(!classesTracker.hasSeen(c.label), "Duplicate class: " + c.label);
+ } else if (c.kind->toInt() == int(CompletionItemKind::Field)) {
+ QVERIFY2(!fieldsTracker.hasSeen(c.label), "Duplicate field: " + c.label);
+ } else if (c.kind->toInt() == int(CompletionItemKind::Snippet)) {
+ QVERIFY2(!snippetTracker.hasSeen(c.label), "Duplicate field: " + c.label);
+ if (c.insertText->contains('\n') || c.insertText->contains('\r')) {
+ QCOMPARE(c.insertTextMode, InsertTextMode::AdjustIndentation);
+ }
+ } else if (c.kind->toInt() == int(CompletionItemKind::Property)) {
+ QVERIFY2(!propertiesTracker.hasSeen(c.label), "Duplicate property: " + c.label);
+ QCOMPARE(c.insertText, std::nullopt);
+ }
+ labels << c.label;
+ sortedLabels << c.label;
+ }
+ const QString labelsForPrinting = sortedLabels.join(u", "_s);
+
+ for (const ExpectedCompletion &exp : expected) {
+ QEXPECT_FAIL("letStatementAfterEqual", "Completion not implemented yet!", Abort);
+
+ QVERIFY2(labels.contains(exp.label),
+ u"no %1 in %2"_s.arg(exp.label, labelsForPrinting).toUtf8());
+ if (labels.contains(exp.label)) {
+
+ bool foundEntry = false;
+ bool hasCorrectKind = false;
+ CompletionItemKind foundKind;
+ for (const CompletionItem &c : completions) {
+ if (c.label == exp.label) {
+ foundKind = static_cast<CompletionItemKind>(c.kind->toInt());
+ foundEntry = true;
+ if (foundKind == exp.kind) {
+ hasCorrectKind = true;
+ if (!exp.snippet.isEmpty()) {
+ QCOMPARE(QString::fromUtf8(c.insertText.value_or(QByteArray())),
+ exp.snippet);
+ }
+ break;
+ }
+ }
+ }
+
+ // Ignore QVERIFY for those completions not in the expected list.
+ if (!foundEntry)
+ continue;
+
+ QVERIFY2(hasCorrectKind,
+ qPrintable(QString::fromLatin1("Completion item '%1' has wrong kind '%2'")
+ .arg(exp.label)
+ .arg(QMetaEnum::fromType<CompletionItemKind>().valueToKey(
+ int(foundKind)))));
+ }
+ }
+ for (const QString &nexp : notExpected) {
+ QEXPECT_FAIL("ignoreNonRelatedTypesForPropertyDefinitionBinding",
+ "Filtering by Type not implemented yet, for example to avoid proposing "
+ "binding Items to Rectangle properties.",
+ Abort);
+ QVERIFY2(!labels.contains(nexp), u"found unexpected completion %1"_s.arg(nexp).toUtf8());
+ }
+}
+
+void tst_qmlls_utils::cmakeBuildCommand()
+{
+ const QString path = u"helloWorldPath"_s;
+ const QPair<QString, QStringList> expected{
+ u"cmake"_s, { u"--build"_s, path, u"-t"_s, u"all_qmltyperegistrations"_s }
+ };
+ QCOMPARE(QQmlLSUtils::cmakeBuildCommand(path), expected);
+}
+
+QTEST_MAIN(tst_qmlls_utils)
diff --git a/tests/auto/qmlls/utils/tst_qmlls_utils.h b/tests/auto/qmlls/utils/tst_qmlls_utils.h
new file mode 100644
index 0000000000..2f1ea19a2c
--- /dev/null
+++ b/tests/auto/qmlls/utils/tst_qmlls_utils.h
@@ -0,0 +1,95 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TST_QMLLS_UTILS_H
+#define TST_QMLLS_UTILS_H
+
+#include <QtJsonRpc/private/qjsonrpcprotocol_p.h>
+#include <QtLanguageServer/private/qlanguageserverprotocol_p.h>
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtCore/private/qfactoryloader_p.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qprocess.h>
+#include <QtCore/qlibraryinfo.h>
+
+#include <QtTest/qtest.h>
+
+#include <QtQmlLS/private/qqmllsutils_p.h>
+#include <QtQmlLS/private/qqmllscompletion_p.h>
+
+#include <iostream>
+
+using namespace Qt::StringLiterals;
+
+class tst_qmlls_utils : public QQmlDataTest
+{
+ Q_OBJECT
+
+ struct ExpectedCompletion
+ {
+ QString label;
+ QLspSpecification::CompletionItemKind kind;
+ QString snippet = {};
+ };
+ using ExpectedCompletions = QList<ExpectedCompletion>;
+
+ using ExpectedDocumentation = std::tuple<QString, QString, QString>;
+ using ExpectedDocumentations = QList<ExpectedDocumentation>;
+
+public:
+ tst_qmlls_utils()
+ : QQmlDataTest(QT_QMLLS_UTILS_DATADIR),
+ m_pluginLoader(QmlLSPluginInterface_iid, u"/qmlls"_s)
+ {
+ }
+
+private slots:
+ void textOffsetRowColumnConversions_data();
+ void textOffsetRowColumnConversions();
+
+ void findItemFromLocation_data();
+ void findItemFromLocation();
+
+ void findTypeDefinitionFromLocation_data();
+ void findTypeDefinitionFromLocation();
+
+ void findDefinitionFromLocation_data();
+ void findDefinitionFromLocation();
+
+ void findLocationOfItem_data();
+ void findLocationOfItem();
+
+ void findBaseObject();
+ void findBaseObject_data();
+
+ void findUsages();
+ void findUsages_data();
+
+ void renameUsages();
+ void renameUsages_data();
+
+ void resolveExpressionType();
+ void resolveExpressionType_data();
+
+ void isValidEcmaScriptIdentifier();
+ void isValidEcmaScriptIdentifier_data();
+
+ void completions_data();
+ void completions();
+
+ void cmakeBuildCommand();
+
+private:
+ using EnvironmentAndFile = std::tuple<QQmlJS::Dom::DomItem, QQmlJS::Dom::DomItem>;
+
+ EnvironmentAndFile createEnvironmentAndLoadFile(const QString &file);
+
+ using CacheKey = QString;
+ // avoid loading the same file over and over when running all the tests
+ QHash<CacheKey, std::shared_ptr<QQmlJS::Dom::DomEnvironment>> cache;
+ QFactoryLoader m_pluginLoader;
+
+};
+
+#endif // TST_QMLLS_UTILS_H
diff --git a/tests/auto/qmlnetwork/CMakeLists.txt b/tests/auto/qmlnetwork/CMakeLists.txt
new file mode 100644
index 0000000000..74cdf06a51
--- /dev/null
+++ b/tests/auto/qmlnetwork/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+add_subdirectory(qqmlnetworkinformation)
+if(QT_FEATURE_qml_ssl)
+ add_subdirectory(qqmlsslconfiguration)
+ add_subdirectory(qqmlsslkey)
+endif()
diff --git a/tests/auto/qmlnetwork/qqmlnetworkinformation/CMakeLists.txt b/tests/auto/qmlnetwork/qqmlnetworkinformation/CMakeLists.txt
new file mode 100644
index 0000000000..a9554a9295
--- /dev/null
+++ b/tests/auto/qmlnetwork/qqmlnetworkinformation/CMakeLists.txt
@@ -0,0 +1,39 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlnetworkinformation LANGUAGES C CXX ASM)
+ find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+endif()
+
+# Collect test data
+file(GLOB_RECURSE test_data_glob
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/data/tst_*)
+list(APPEND test_data ${test_data_glob})
+
+qt_internal_add_test(tst_qqmlnetworkinformation
+ QMLTEST
+ SOURCES
+ tst_qqmlnetworkinformation.cpp
+ LIBRARIES
+ Qt::QmlPrivate
+ Qt::QuickTestUtilsPrivate
+ Qt::Network
+ TESTDATA ${test_data}
+)
+
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qqmlnetworkinformation)
+endif()
+
+qt_internal_extend_target(tst_qqmlnetworkinformation CONDITION ANDROID OR IOS
+ DEFINES
+ QT_QMLTEST_DATADIR=":/data"
+)
+
+qt_internal_extend_target(tst_qqmlnetworkinformation CONDITION NOT ANDROID AND NOT IOS
+ DEFINES
+ QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+)
diff --git a/tests/auto/qmlnetwork/qqmlnetworkinformation/data/tst_networkinformation.qml b/tests/auto/qmlnetwork/qqmlnetworkinformation/data/tst_networkinformation.qml
new file mode 100644
index 0000000000..a429e05320
--- /dev/null
+++ b/tests/auto/qmlnetwork/qqmlnetworkinformation/data/tst_networkinformation.qml
@@ -0,0 +1,14 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+import QtNetwork
+
+QtObject {
+ property int local: NetworkInformation.Reachability.Local
+ property int reachability: NetworkInformation.reachability
+ property bool isBehindCaptivePortal: NetworkInformation.isBehindCaptivePortal
+ property int ethernet: NetworkInformation.TransportMedium.Ethernet
+ property int transportMedium: NetworkInformation.transportMedium
+ property bool isMetered: NetworkInformation.isMetered
+}
diff --git a/tests/auto/qmlnetwork/qqmlnetworkinformation/tst_qqmlnetworkinformation.cpp b/tests/auto/qmlnetwork/qqmlnetworkinformation/tst_qqmlnetworkinformation.cpp
new file mode 100644
index 0000000000..768d751c53
--- /dev/null
+++ b/tests/auto/qmlnetwork/qqmlnetworkinformation/tst_qqmlnetworkinformation.cpp
@@ -0,0 +1,51 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QQmlEngine>
+#include <QQmlComponent>
+#include <QtNetwork/qnetworkinformation.h>
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+
+class tst_qqmlnetworkinformation : public QQmlDataTest
+{
+ Q_OBJECT
+
+public:
+ explicit tst_qqmlnetworkinformation() : QQmlDataTest(QT_QMLTEST_DATADIR) { }
+
+private Q_SLOTS:
+ void networkInformation();
+};
+
+void tst_qqmlnetworkinformation::networkInformation()
+{
+ QNetworkInformation::loadDefaultBackend();
+ QNetworkInformation *networkinfo = QNetworkInformation::instance();
+#if defined(Q_OS_LINUX) || defined(Q_OS_WIN) || defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN)
+ QVERIFY(networkinfo);
+#else
+ QSKIP("Platform does not provide network information");
+#endif
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("tst_networkinformation.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QCOMPARE(object->property("local").toInt(),
+ static_cast<int>(QNetworkInformation::Reachability::Local));
+ QCOMPARE(object->property("reachability").toInt(),
+ static_cast<int>(networkinfo->reachability()));
+ QCOMPARE(object->property("isBehindCaptivePortal").toBool(),
+ networkinfo->isBehindCaptivePortal());
+ QCOMPARE(object->property("ethernet").toInt(),
+ static_cast<int>(QNetworkInformation::TransportMedium::Ethernet));
+ QCOMPARE(object->property("transportMedium").toInt(),
+ static_cast<int>(networkinfo->transportMedium()));
+ QCOMPARE(object->property("isMetered").toBool(), networkinfo->isMetered());
+}
+
+QTEST_MAIN(tst_qqmlnetworkinformation)
+
+#include "tst_qqmlnetworkinformation.moc"
diff --git a/tests/auto/qmlnetwork/qqmlsslconfiguration/CMakeLists.txt b/tests/auto/qmlnetwork/qqmlsslconfiguration/CMakeLists.txt
new file mode 100644
index 0000000000..bc5709dc86
--- /dev/null
+++ b/tests/auto/qmlnetwork/qqmlsslconfiguration/CMakeLists.txt
@@ -0,0 +1,43 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_sslconfiguration_qml LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_sslconfiguration_qml
+ QMLTEST
+ SOURCES
+ tst_sslconfiguration_qml.cpp
+ LIBRARIES
+ Qt::Qml
+ Qt::QuickTestUtilsPrivate
+ Qt::QmlNetwork
+)
+
+qt_policy(SET QTP0001 NEW)
+
+qt_add_qml_module(tst_sslconfiguration_qml
+ URI QmlTestUri
+ VERSION 1.0
+ QML_FILES
+ qml/tst_sslconfiguration.qml
+)
+
+set_source_files_properties("${CMAKE_CURRENT_LIST_DIR}/data/cert.pem"
+ PROPERTIES QT_RESOURCE_ALIAS data/cert.pem)
+set_source_files_properties("${CMAKE_CURRENT_LIST_DIR}/data/key.pem"
+ PROPERTIES QT_RESOURCE_ALIAS data/key.pem)
+
+qt_add_resources(tst_sslconfiguration_qml
+ "data"
+ PREFIX
+ "/"
+ FILES
+ "${CMAKE_CURRENT_LIST_DIR}/data/cert.pem"
+ "${CMAKE_CURRENT_LIST_DIR}/data/key.pem"
+)
+
+qt_autogen_tools_initial_setup(tst_sslconfiguration_qml)
diff --git a/tests/auto/qmlnetwork/qqmlsslconfiguration/data/cert.pem b/tests/auto/qmlnetwork/qqmlsslconfiguration/data/cert.pem
new file mode 100644
index 0000000000..3fb973e1be
--- /dev/null
+++ b/tests/auto/qmlnetwork/qqmlsslconfiguration/data/cert.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF6zCCA9OgAwIBAgIJAMPfLBc9ERZGMA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD
+VQQGEwJERTEPMA0GA1UECAwGQmVybGluMQ8wDQYDVQQHDAZCZXJsaW4xEzARBgNV
+BAoMClF0UHJvdG9idWYxDDAKBgNVBAsMA1JuRDESMBAGA1UEAwwJbG9jYWxob3N0
+MSMwIQYJKoZIhvcNAQkBFhRxdHByb3RvYnVmQGdtYWlsLmNvbTAeFw0xOTA0MjMx
+NTI5MzNaFw0yMDA0MjIxNTI5MzNaMIGLMQswCQYDVQQGEwJERTEPMA0GA1UECAwG
+QmVybGluMQ8wDQYDVQQHDAZCZXJsaW4xEzARBgNVBAoMClF0UHJvdG9idWYxDDAK
+BgNVBAsMA1JuRDESMBAGA1UEAwwJbG9jYWxob3N0MSMwIQYJKoZIhvcNAQkBFhRx
+dHByb3RvYnVmQGdtYWlsLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
+ggIBANCB7zdc6v+gsYCsGIYsT3iyGPgvFG7cJJWnQO9iW6Tn/kBcreYuCdVSSODK
+/NtPaA1r8j9FCDvLkzewNQ2Idv08/oKBYfOaVtQvh1cn7ktr1usiXtYv16cimeKk
+8iYbiczkZOah2xq+ivm9+05WkYTzcSjBpXg19894024GHd7oRV9G5MCr760k8YLM
+ALnoPpTl0yfs5cEcTybqvZFZNqkHDX2ziEbcF/mVcxcyEsmenbX6MI0easg2qZeq
+Sb7AW7tIMVoWUxDkUIor4vogbgU2IljAjzn0i+fPncB41TU5IiIU35vO67kFBXyI
+Ms3LpN1+Siz5HYHjwaWl0ecebuT83kP33VNc1ULkKJG5UbZUYfgZjUwZPgFFzVzQ
+cif0mhYj9s5Nmn6Q/twxeIXOIZAQdLOq625Wwx8bh+mGaV5mtw3wtXJjbceGa1z/
+Pnni4x2B7IfSiOzGLZZNRRHIjUskeONHUHn8YBrLLg5RT+tvPnGDVPh0cKEH2P4F
+cNRPmaqg75siFoJ+m3DlFM952tRcfzJumgbUfEnrL8bxTZPYVoq22qCDm3UGNW8n
+pthv8Y2hemv6V9lF050z2vpL2DtU9RmtkBWx7ipPUdsEOm4e0rdOCk7zo8IAiWMQ
+6o1L23IPTsqaEpqk3b7tT+5dtLkpeomAT8Hz91ChWUb6jrTVAgMBAAGjUDBOMB0G
+A1UdDgQWBBQIb2RjqkeMsUjH9QJ5BYnAtJ/vojAfBgNVHSMEGDAWgBQIb2RjqkeM
+sUjH9QJ5BYnAtJ/vojAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQDG
+2x+I9C+4XFCpg9KVA+BBi6+7yi4ulH0yv7W3hNWBV2MxTpvVN6RIt8xI1sPFXc2T
+g2wCIAIPGIPNDe8hO3gcfIIe059P+J3ZNjybUg5p6CR9O7kqgqV/nL4gVRuBJeYq
+6YLr1lKL9r3Zdbkq1tcaCaj816zdXVky0us72XP28/xJc96crgKzDI69vESy5jq6
+QT/HoBwYiSaWXNgb0zJzc//e0upXSLeTkYizAJ5OGkQ/MQYE7gDvtPlGVhQ0rnl/
+FLsiZJokuxtLOTvYJ8Gynjz3QwbClN/bmUbOgD0fqW6BEZyZSJ4zCz0BJnwg46gc
+IN+p6vi50MG4ZcJcnMl/3tAxt2RxHNLi0j21NSLyFj60gK+vL3/zzkdYF9ZxX1L+
+dqhTqioCVrV96rJIQbz6JrbFhUCdyEHYG7yi6LxHTUex33XouhGAfZ0lri5wWZq8
+0Rx8PEZ7SbjARtnvA7uXIAfgD+n3oqnkg9IDPH8PbdRcJrAdje3O2c1+OzTAC8ni
+czaCWG748gfZPe0JpENP7P56RTh9avj4sHISCx4r+sh0lruLp2JZPr9qtw09uWlq
+Mn58bcnDu9RjVfPXk43s9WfJC9XII+JoNcW3iJDSHxQb9XLvwR9ntWhkVvOKenPP
+b00kWr6FfId6fiOmUww5WkW+Wtt4XOYsypaN+DskeA==
+-----END CERTIFICATE-----
diff --git a/tests/auto/qmlnetwork/qqmlsslconfiguration/data/key.pem b/tests/auto/qmlnetwork/qqmlsslconfiguration/data/key.pem
new file mode 100644
index 0000000000..176f5210c1
--- /dev/null
+++ b/tests/auto/qmlnetwork/qqmlsslconfiguration/data/key.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDQge83XOr/oLGA
+rBiGLE94shj4LxRu3CSVp0DvYluk5/5AXK3mLgnVUkjgyvzbT2gNa/I/RQg7y5M3
+sDUNiHb9PP6CgWHzmlbUL4dXJ+5La9brIl7WL9enIpnipPImG4nM5GTmodsavor5
+vftOVpGE83EowaV4NffPeNNuBh3e6EVfRuTAq++tJPGCzAC56D6U5dMn7OXBHE8m
+6r2RWTapBw19s4hG3Bf5lXMXMhLJnp21+jCNHmrINqmXqkm+wFu7SDFaFlMQ5FCK
+K+L6IG4FNiJYwI859Ivnz53AeNU1OSIiFN+bzuu5BQV8iDLNy6Tdfkos+R2B48Gl
+pdHnHm7k/N5D991TXNVC5CiRuVG2VGH4GY1MGT4BRc1c0HIn9JoWI/bOTZp+kP7c
+MXiFziGQEHSzqutuVsMfG4fphmleZrcN8LVyY23Hhmtc/z554uMdgeyH0ojsxi2W
+TUURyI1LJHjjR1B5/GAayy4OUU/rbz5xg1T4dHChB9j+BXDUT5mqoO+bIhaCfptw
+5RTPedrUXH8ybpoG1HxJ6y/G8U2T2FaKttqgg5t1BjVvJ6bYb/GNoXpr+lfZRdOd
+M9r6S9g7VPUZrZAVse4qT1HbBDpuHtK3TgpO86PCAIljEOqNS9tyD07KmhKapN2+
+7U/uXbS5KXqJgE/B8/dQoVlG+o601QIDAQABAoICAGYHPsxDfoap1lHVZIa7RgQU
+eh1vxDrfJFPKrP62jYurLgHGmB2rZ4poIltFWOfj+lGfAcIuAHJqElbMtZkyrq8K
+Wqv3rburSVO5Eiv20Sc81MToY6nBbXBOgSijeA5nqU2GcU1d5D45AP5mFYPm3nxF
+N5ku8M5a8jEmuab7/T/nPpL5uNQDDlwWWMudEbnmyEDKGUJPLLoLJTww36QxGIsr
+dVGOOWAbMOwjUlcGXKUmJZw3mexj9vKTtPcPD9j0fa6uC+A+TlVUs4h5Iy8sEUoh
+jDsLtsowPQmo0VOujP3nQCmXNzghz70QlPe0GdAUF09/DcLl/6dgkJCDDKxgevhW
+GYfUSaR6gjg6/QYVHIea9wCkxW2jRXPvG6pBAAaoseS4n7M3IckzSol4Nwh2vmzA
+yvGMLlLUkNIYHJ/P29mMt+EoBrtdME8XZln0sCkQC5c0+owvyBsPEjrpnBtqvPse
+CNQaULUZnsJC3kbJeU/xPcqNa8pGjnpiHqjDFN4CUJAYnLDuAanow075DCkLKWej
+ziXWQoJ+RO4ml9Gy0qoHE76iEg9fvKx7aWIv0DSmhRvwKeI8kc1yPp8kACy1rOBu
+f9gvDDB4jMVDQKYRDbZ6kyRrHX5XKvJJ6vkpFBT1fLaWVdH8fOtIsDKaLhSTc0Ia
+TbcDJquaBeLnQmpH5439AoIBAQDpccVOJ2mE1n6sluXkzE/zW17jmWMrBXAtYpnt
+nkBO8SuwNzZW3V0LvCTpEVo1XupvVbuMvWzZyHgAevqDL77Z5FP63hO1l1yT3mcw
+WB1Kr9XTXm52DL4IGnp4agrI1+zp56q8o/PbJfkk3JhiEmpHa3rh575LcYVs8HXV
+5+cTFc5upygXX4odRazS7qXtZdyBL1w7KpZijZJqrcG3t4sjCKEOcZn6XFVFtfHE
+GWrAIz9kWORh5nZ9MTI9TR/4MHBYJ8G/9kwbrnce+FeZ4BTkZHqQTp2MHeC9AFro
+JCtG8y1rhh1cxzoUMB6s3qW6Q/7b2/Wx7Hb6RMFXRFYTaeVXAoIBAQDkp1o5E+OB
+ErGPRBHpt+7nmEFq+U+biNcNUvxTKtL9aQKix5Xt9zgSQTN9LmIhAOKDKfuU2Elb
+rX5tCTbalFYcpUX+wD+idvcgpc7Ju+tRMC5Ai9avuCJ0n2oQZiaxFz8GIPc/1C3a
+gC5s1HHr0qTDKcs37nBiay3lmll49J0grrl0NOEWROGDnILvvgCN8jQoMBN5Od5k
+zCPXFuWl3JhWKtSoF+isk/io2JjM2asZuz0zi4mzBnjnVfCM0dAHufoTMQ8aHiVZ
+45iXDIZY9c8frOLgeZeE12mYTWpxZHUuaZSoqoXuApmW3nhoGHYSfX7sORDTYS/4
+2PEJlhkkPs+zAoIBAQC33GybBn2cK1gv1NWSY7zgnelZdzjc7HaSuGMl/IsH4fkX
+3BSHS+f50yB7FLio6m3YbHy/932g9bxWHIXsBxHZCXV/U6PQVTuMFxHMyMmhRmYy
+COEVRynwtfIZnuOJlk85VsZptvPceccF2lyGeZyNTcDF5kFBqFJ/H9CfPfwIUxd4
+nVz9M7lTHspkg6PaG20VrliFHSC+1GQqc1nsubnzSNuYxa6RumFK+2dEnQQv+lL2
+VPDjjqFqLvIzx+fTEUuakw2NhI4jC0E0+kH8prmtvNmviMubTPjxwzLWPY58XhE6
+67F6nktHFTND0kRTNTSos1CK5wQ6Tya79c2ZksEXAoIBAAdI7a7z20O5fL67xHZV
+zd7DExJ9bvPdoDxkcHWV37MDLXpSMYyrW7X5LdLHL4ktpgnXxJQxb+Tj2itPJ9g+
+8Z9oBJrhNSXP9H+tyLDUs+KaTl7wFZ7zluVwTsjG+GScAP4I/tehwvQ7MT92ZUrG
+I0m0gyz9A8ee8o9mI4OfB4KLDo2NQb6b4zN2QRWyUAI1vUOqhHRQS62ac2ne6OIn
+7RKRusTAPkGBVWLLw9KC/NiNBp4ly/VQN3nnWwqhhKc6XaVO4tRKMZZzkeD+HSmo
+azjvIStVtGYfFtYrYUDLmpAn/PyCslGq84nC/MMURG7CYNDV4JtbdVPQVZ2gkpx9
+A9ECggEAGuw6sJAkp381dHgf6tTkwsOmJldX4Bjxi6q3vXzNwsou+uwYoLNvXVnl
+mfMQdswCGW1Hm1XPMSBqkleyaXChL4bqM/FJGz8DgBD85vWfaYPrfKIELlfSo5lD
+opBZ8wrAEa9rP2Fm1mbAiFFyXtK78y09CuuMgCL5jZjAQEbNFDOSwfcrJzNY+xU7
+KtsDGCm7OmUAizdWjnAfQKQlB94uk7PimI1Hhs8175fgwaSS3KUILSR8oj/gKFPS
+L7DqR8DsvyGg/JuHx+sdSG3T5q5zGzz2w03mDkoSyxWe36u3F3EyChhPfjcaSape
+0mVZG9D69wbsZefVDJii9NLvWThGog==
+-----END PRIVATE KEY-----
diff --git a/tests/auto/qmlnetwork/qqmlsslconfiguration/qml/tst_sslconfiguration.qml b/tests/auto/qmlnetwork/qqmlsslconfiguration/qml/tst_sslconfiguration.qml
new file mode 100644
index 0000000000..f4404e5557
--- /dev/null
+++ b/tests/auto/qmlnetwork/qqmlsslconfiguration/qml/tst_sslconfiguration.qml
@@ -0,0 +1,158 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtTest
+import QtNetwork
+import QmlTestUri
+
+Item {
+ id: root
+
+ property sslConfiguration userSslObject;
+ property sslConfiguration defaultSslObject;
+ property sslDtlsConfiguration dtlsDefaultSslObj;
+ property sslKey key;
+
+ TestCase {
+ name: "qtSslConfigurationTest"
+
+ function test_1initialization() {
+ userSslObject.peerVerifyMode = SslSocket.QueryPeer
+ userSslObject.peerVerifyDepth = 0
+ userSslObject.protocol = Ssl.TlsV1_2
+ userSslObject.sslOptions = [Ssl.SslOptionDisableEmptyFragments]
+
+ defaultSslObject.peerVerifyMode = SslSocket.VerifyPeer;
+ dtlsDefaultSslObj.peerVerifyMode = SslSocket.VerifyNone;
+
+ key.keyFile = ":/data/key.pem"
+ key.keyAlgorithm = Ssl.Rsa
+ key.keyFormat = Ssl.Pem
+
+ // Call invokable functions for ssl object
+ userSslObject.setCertificateFiles([":/data/cert.pem"])
+ userSslObject.setPrivateKey(key)
+ }
+
+ function test_sslEnumsFields_data() {
+ return [
+ // enum SslProtocol
+ { tag: "SslProtocol.TlsV1_2OrLater",
+ field: Ssl.TlsV1_2OrLater, answer: 7 },
+ { tag: "SslProtocol.DtlsV1_2",
+ field: Ssl.DtlsV1_2, answer: 10 },
+ { tag: "SslProtocol.DtlsV1_2OrLater",
+ field: Ssl.DtlsV1_2OrLater, answer: 11},
+ { tag: "SslProtocol.TlsV1_3",
+ field: Ssl.TlsV1_3, answer: 12 },
+ { tag: "SslProtocol.TlsV1_3OrLater",
+ field: Ssl.TlsV1_3OrLater, answer: 13 },
+ { tag: "SslProtocol.UnknownProtocol",
+ field: Ssl.UnknownProtocol, answer: -1 },
+
+ // enum EncodingFormat
+ { tag: "EncodingFormat.Pem",
+ field: Ssl.Pem, answer: 0 },
+ { tag: "EncodingFormat.Der",
+ field: Ssl.Der, answer: 1 },
+
+ // enum KeyType
+ { tag: "KeyType.key",
+ field: Ssl.PrivateKey, answer: 0 },
+ { tag: "KeyType.PublicKey",
+ field: Ssl.PublicKey, answer: 1 },
+
+ //enum KeyAlgorithm
+ { tag: "KeyAlgorithm.Opaque",
+ field: Ssl.Opaque, answer: 0 },
+ { tag: "KeyAlgorithm.Rsa",
+ field: Ssl.Rsa, answer: 1 },
+ { tag: "KeyAlgorithm.Dsa",
+ field: Ssl.Dsa, answer: 2 },
+ { tag: "KeyAlgorithm.Ec",
+ field: Ssl.Ec, answer: 3 },
+ { tag: "KeyAlgorithm.Dh",
+ field: Ssl.Dh, answer: 4 },
+
+ // enum SslOption
+ { tag: "SslOption.SslOptionDisableEmptyFragments",
+ field: Ssl.SslOptionDisableEmptyFragments, answer: 0x01 },
+ { tag: "SslOption.SslOptionDisableSessionTickets",
+ field: Ssl.SslOptionDisableSessionTickets, answer: 0x02 },
+ { tag: "SslOption.SslOptionDisableCompression",
+ field: Ssl.SslOptionDisableCompression, answer: 0x04 },
+ { tag: "SslOption.SslOptionDisableServerNameIndication",
+ field: Ssl.SslOptionDisableServerNameIndication, answer: 0x08 },
+ { tag: "SslOption.SslOptionDisableLegacyRenegotiation",
+ field: Ssl.SslOptionDisableLegacyRenegotiation, answer: 0x10 },
+ { tag: "SslOption.SslOptionDisableSessionSharing",
+ field: Ssl.SslOptionDisableSessionSharing, answer: 0x20 },
+ { tag: "SslOption.SslOptionDisableSessionPersistence",
+ field: Ssl.SslOptionDisableSessionPersistence, answer: 0x40 },
+ { tag: "SslOption.SslOptionDisableServerCipherPreference",
+ field: Ssl.SslOptionDisableServerCipherPreference, answer: 0x80 },
+
+ // enum PeerVerifyMode
+ { tag: "PeerVerifyMode.VerifyNone",
+ field: SslSocket.VerifyNone, answer: 0 },
+ { tag: "PeerVerifyMode.QueryPeer",
+ field: SslSocket.QueryPeer, answer: 1 },
+ { tag: "PeerVerifyMode.VerifyPeer",
+ field: SslSocket.VerifyPeer, answer: 2 },
+ { tag: "PeerVerifyMode.AutoVerifyPeer",
+ field: SslSocket.AutoVerifyPeer, answer: 3 }
+ ]
+ }
+
+ function test_sslEnumsFields(data) {
+ compare(data.field, data.answer)
+ }
+
+ function test_sslConfigurationFields_data() {
+ return [
+ { tag: "userSslObject is creatable object",
+ field: typeof userSslObject, answer: "object" },
+ { tag: "defaultSslObject is creatable object",
+ field: typeof defaultSslObject, answer: "object" },
+ { tag: "dtlsDefaultSslObj is creatable object",
+ field: typeof dtlsDefaultSslObj, answer: "object" },
+ { tag: "key is creatable object",
+ field: typeof key, answer: "object" },
+ { tag: "userSslObject.sslOptions is creatable object",
+ field: typeof userSslObject.sslOptions,
+ answer: "object" },
+
+ // userSslObject
+ { tag: "userSslObject.peerVerifyMode == Ssl.QueryPeer",
+ field: userSslObject.peerVerifyMode, answer: SslSocket.QueryPeer },
+ // defaultSslObject
+ { tag: "defaultSslObject.peerVerifyMode == Ssl.VerifyPeer",
+ field: defaultSslObject.peerVerifyMode, answer: SslSocket.VerifyPeer },
+ // dtlsDefaultSslObj
+ { tag: "dtlsDefaultSslObj.peerVerifyMode == Ssl.VerifyNone",
+ field: dtlsDefaultSslObj.peerVerifyMode,
+ answer: SslSocket.VerifyNone },
+
+ // userSslObject
+ { tag: "userSslObject.peerVerifyDepth == 0",
+ field: userSslObject.peerVerifyDepth, answer: 0 },
+ { tag: "userSslObject.sslOptions == Ssl.SslOptionDisableEmptyFragments",
+ field: userSslObject.sslOptions[0],
+ answer: Ssl.SslOptionDisableEmptyFragments },
+ { tag: "SSL configuration protocol == SslProtocol.TlsV1_2",
+ field: userSslObject.protocol, answer: Ssl.TlsV1_2 },
+ { tag: "key.keyFile == :/data/key.pem",
+ field: key.keyFile, answer: ":/data/key.pem" },
+ { tag: "key.keyAlgorithm == Ssl.Rsa",
+ field: key.keyAlgorithm, answer: Ssl.Rsa },
+ { tag: "key.keyFormat == Ssl.Pem",
+ field: key.keyFormat, answer: Ssl.Pem }
+ ]
+ }
+
+ function test_sslConfigurationFields(data) {
+ compare(data.field, data.answer)
+ }
+ }
+}
diff --git a/tests/auto/qmlnetwork/qqmlsslconfiguration/tst_sslconfiguration_qml.cpp b/tests/auto/qmlnetwork/qqmlsslconfiguration/tst_sslconfiguration_qml.cpp
new file mode 100644
index 0000000000..eded07c9ac
--- /dev/null
+++ b/tests/auto/qmlnetwork/qqmlsslconfiguration/tst_sslconfiguration_qml.cpp
@@ -0,0 +1,6 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtQuickTest>
+
+QUICK_TEST_MAIN(tst_sslconfiguration_qml)
diff --git a/tests/auto/qmlnetwork/qqmlsslkey/CMakeLists.txt b/tests/auto/qmlnetwork/qqmlsslkey/CMakeLists.txt
new file mode 100644
index 0000000000..eb9562add6
--- /dev/null
+++ b/tests/auto/qmlnetwork/qqmlsslkey/CMakeLists.txt
@@ -0,0 +1,29 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_sslkey_qml LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_sslkey_qml
+ QMLTEST
+ SOURCES
+ tst_sslkey_qml.cpp
+ LIBRARIES
+ Qt::Qml
+ Qt::QuickTestUtilsPrivate
+ Qt::QmlNetwork
+)
+
+qt_policy(SET QTP0001 NEW)
+
+qt_add_qml_module(tst_sslkey_qml
+ URI QmlTestUri
+ VERSION 1.0
+ QML_FILES
+ qml/tst_sslkey.qml
+)
+
+qt_autogen_tools_initial_setup(tst_sslkey_qml)
diff --git a/tests/auto/qmlnetwork/qqmlsslkey/qml/tst_sslkey.qml b/tests/auto/qmlnetwork/qqmlsslkey/qml/tst_sslkey.qml
new file mode 100644
index 0000000000..3b4aab2ec6
--- /dev/null
+++ b/tests/auto/qmlnetwork/qqmlsslkey/qml/tst_sslkey.qml
@@ -0,0 +1,60 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtTest
+import QtNetwork
+import QmlTestUri
+
+Item {
+ id: root
+
+ property sslKey keyFirst;
+ property sslKey keySecond;
+
+ TestCase {
+ name: "qtSslKeyTest"
+
+ function test_1initialization() {
+ keyFirst.keyFile = ":/assets/key.pem"
+ keyFirst.keyAlgorithm = Ssl.Rsa
+ keyFirst.keyFormat = Ssl.Pem
+ keyFirst.keyType = Ssl.PrivateKey
+
+ keySecond = keyFirst;
+ }
+
+ function test_sslConfigurationFields_data() {
+ return [
+ { tag: "key is creatable object",
+ field: typeof keyFirst, answer: "object" },
+ { tag: "keySecond is creatable object",
+ field: typeof keySecond, answer: "object" },
+
+ // key values
+ { tag: "keyFirst.keyFile == :/assets/key.pem",
+ field: keyFirst.keyFile, answer: ":/assets/key.pem" },
+ { tag: "keyFirst.keyAlgorithm == Ssl.Rsa",
+ field: keyFirst.keyAlgorithm, answer: Ssl.Rsa },
+ { tag: "keyFirst.keyFormat == Ssl.Pem",
+ field: keyFirst.keyFormat, answer: Ssl.Pem },
+ { tag: "keyFirst.keyType == Ssl.PrivateKey",
+ field: keyFirst.keyType, answer: Ssl.PrivateKey },
+
+ // keySecond values
+ { tag: "keySecond.keyFile == :/assets/key.pem",
+ field: keySecond.keyFile, answer: ":/assets/key.pem" },
+ { tag: "keySecond.keyAlgorithm == Ssl.Rsa",
+ field: keySecond.keyAlgorithm, answer: Ssl.Rsa },
+ { tag: "keySecond.keyFormat == Ssl.Pem",
+ field: keySecond.keyFormat, answer: Ssl.Pem },
+ { tag: "keySecond.keyType == Ssl.PrivateKey",
+ field: keySecond.keyType, answer: Ssl.PrivateKey }
+ ]
+ }
+
+ function test_sslConfigurationFields(data) {
+ compare(data.field, data.answer)
+ }
+ }
+}
diff --git a/tests/auto/qmlnetwork/qqmlsslkey/tst_sslkey_qml.cpp b/tests/auto/qmlnetwork/qqmlsslkey/tst_sslkey_qml.cpp
new file mode 100644
index 0000000000..9369c356d8
--- /dev/null
+++ b/tests/auto/qmlnetwork/qqmlsslkey/tst_sslkey_qml.cpp
@@ -0,0 +1,6 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtQuickTest>
+
+QUICK_TEST_MAIN(tst_sslkey_qml)
diff --git a/tests/auto/qmltest-blacklist/animators/Box.qml b/tests/auto/qmltest-blacklist/animators/Box.qml
index d32d0e7c8e..f1fe1d091e 100644
--- a/tests/auto/qmltest-blacklist/animators/Box.qml
+++ b/tests/auto/qmltest-blacklist/animators/Box.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/qmltest-blacklist/animators/tst_behavior.qml b/tests/auto/qmltest-blacklist/animators/tst_behavior.qml
index eedbad5441..d001b0d49e 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_behavior.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_behavior.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_mixed.qml b/tests/auto/qmltest-blacklist/animators/tst_mixed.qml
index b0f5cb01f5..cc3d36b7e5 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_mixed.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_mixed.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_mixedparallel.qml b/tests/auto/qmltest-blacklist/animators/tst_mixedparallel.qml
index 9e93021d38..96e762e6bd 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_mixedparallel.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_mixedparallel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_mixedsequential.qml b/tests/auto/qmltest-blacklist/animators/tst_mixedsequential.qml
index 9b0aee2a49..9a8d24fab8 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_mixedsequential.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_mixedsequential.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_multiwindow.qml b/tests/auto/qmltest-blacklist/animators/tst_multiwindow.qml
index d678c8db1d..f8e7096aa0 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_multiwindow.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_multiwindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_nested.qml b/tests/auto/qmltest-blacklist/animators/tst_nested.qml
index 8b73c07368..07ae9be3d2 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_nested.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_nested.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_on.qml b/tests/auto/qmltest-blacklist/animators/tst_on.qml
index f058aaacc1..264300e83c 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_on.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_on.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_opacity.qml b/tests/auto/qmltest-blacklist/animators/tst_opacity.qml
index d41537a637..e43163e593 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_opacity.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_opacity.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_parallel.qml b/tests/auto/qmltest-blacklist/animators/tst_parallel.qml
index bae616242d..16bdb4ac68 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_parallel.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_parallel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_restart.qml b/tests/auto/qmltest-blacklist/animators/tst_restart.qml
index 3e252ea273..0f247237c5 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_restart.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_restart.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_rotation.qml b/tests/auto/qmltest-blacklist/animators/tst_rotation.qml
index f72235b2e1..6af6f95803 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_rotation.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_rotation.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_scale.qml b/tests/auto/qmltest-blacklist/animators/tst_scale.qml
index 384c597c7c..3aef72eb34 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_scale.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_scale.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_sequential.qml b/tests/auto/qmltest-blacklist/animators/tst_sequential.qml
index bbcb84d46b..ef9026a217 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_sequential.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_sequential.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_stopped.qml b/tests/auto/qmltest-blacklist/animators/tst_stopped.qml
index 3f27fa1a69..0966a3145c 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_stopped.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_stopped.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_targetdestroyed.qml b/tests/auto/qmltest-blacklist/animators/tst_targetdestroyed.qml
index 104ecf2929..3cf6b90aa8 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_targetdestroyed.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_targetdestroyed.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Gunnar Sletta <gunnar@sletta.org>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_transformorigin.qml b/tests/auto/qmltest-blacklist/animators/tst_transformorigin.qml
index be74ae7b5f..5947e69700 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_transformorigin.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_transformorigin.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_transition.qml b/tests/auto/qmltest-blacklist/animators/tst_transition.qml
index be177491e9..1e9ea0f94b 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_transition.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_transition.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_x.qml b/tests/auto/qmltest-blacklist/animators/tst_x.qml
index c8132b7ce1..63d1cf90f6 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_x.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_x.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/animators/tst_y.qml b/tests/auto/qmltest-blacklist/animators/tst_y.qml
index a58f803d47..de3cf0a322 100644
--- a/tests/auto/qmltest-blacklist/animators/tst_y.qml
+++ b/tests/auto/qmltest-blacklist/animators/tst_y.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/item/tst_layerInPositioner.qml b/tests/auto/qmltest-blacklist/item/tst_layerInPositioner.qml
index 5acba142e4..6aead67530 100644
--- a/tests/auto/qmltest-blacklist/item/tst_layerInPositioner.qml
+++ b/tests/auto/qmltest-blacklist/item/tst_layerInPositioner.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
import QtTest 1.1
diff --git a/tests/auto/qmltest-blacklist/shortcut/CMakeLists.txt b/tests/auto/qmltest-blacklist/shortcut/CMakeLists.txt
index 962122f888..694f7522a7 100644
--- a/tests/auto/qmltest-blacklist/shortcut/CMakeLists.txt
+++ b/tests/auto/qmltest-blacklist/shortcut/CMakeLists.txt
@@ -7,6 +7,12 @@
## shortcut Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(shortcut LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(shortcut
GUI
QMLTEST
diff --git a/tests/auto/qmltest-blacklist/shortcut/tst_shortcut.qml b/tests/auto/qmltest-blacklist/shortcut/tst_shortcut.qml
index 9887f10c21..97ae2cc387 100644
--- a/tests/auto/qmltest-blacklist/shortcut/tst_shortcut.qml
+++ b/tests/auto/qmltest-blacklist/shortcut/tst_shortcut.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.8
import QtQuick.Window 2.2
diff --git a/tests/auto/qmltest/animatedimage/CMakeLists.txt b/tests/auto/qmltest/animatedimage/CMakeLists.txt
index 93f5b5edba..0887077356 100644
--- a/tests/auto/qmltest/animatedimage/CMakeLists.txt
+++ b/tests/auto/qmltest/animatedimage/CMakeLists.txt
@@ -7,6 +7,12 @@
## animatedimage Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(animatedimage LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(animatedimage
GUI
QMLTEST
diff --git a/tests/auto/qmltest/animatedimage/tst_animatedimage.qml b/tests/auto/qmltest/animatedimage/tst_animatedimage.qml
index cd46033acc..a5f248480e 100644
--- a/tests/auto/qmltest/animatedimage/tst_animatedimage.qml
+++ b/tests/auto/qmltest/animatedimage/tst_animatedimage.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/animations/CMakeLists.txt b/tests/auto/qmltest/animations/CMakeLists.txt
index dcabfffc4a..64084605c8 100644
--- a/tests/auto/qmltest/animations/CMakeLists.txt
+++ b/tests/auto/qmltest/animations/CMakeLists.txt
@@ -7,6 +7,12 @@
## animations Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(animations LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(animations
GUI
QMLTEST
diff --git a/tests/auto/qmltest/animations/tst_abstractanimationjobcrash.qml b/tests/auto/qmltest/animations/tst_abstractanimationjobcrash.qml
index fd9a082f26..bad8a1c0ba 100644
--- a/tests/auto/qmltest/animations/tst_abstractanimationjobcrash.qml
+++ b/tests/auto/qmltest/animations/tst_abstractanimationjobcrash.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/borderimage/CMakeLists.txt b/tests/auto/qmltest/borderimage/CMakeLists.txt
index 3120f6781f..c582dc3380 100644
--- a/tests/auto/qmltest/borderimage/CMakeLists.txt
+++ b/tests/auto/qmltest/borderimage/CMakeLists.txt
@@ -7,6 +7,12 @@
## borderimage Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(borderimage LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(borderimage
GUI
QMLTEST
diff --git a/tests/auto/qmltest/borderimage/InvalidSciFile.qml b/tests/auto/qmltest/borderimage/InvalidSciFile.qml
index 1f8af5741e..1e52515b04 100644
--- a/tests/auto/qmltest/borderimage/InvalidSciFile.qml
+++ b/tests/auto/qmltest/borderimage/InvalidSciFile.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qmltest/borderimage/tst_borderimage.qml b/tests/auto/qmltest/borderimage/tst_borderimage.qml
index 7227343361..ab075d69c3 100644
--- a/tests/auto/qmltest/borderimage/tst_borderimage.qml
+++ b/tests/auto/qmltest/borderimage/tst_borderimage.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/buttonclick/Button.qml b/tests/auto/qmltest/buttonclick/Button.qml
index 0dd684f780..f59ae5e3c7 100644
--- a/tests/auto/qmltest/buttonclick/Button.qml
+++ b/tests/auto/qmltest/buttonclick/Button.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qmltest/buttonclick/CMakeLists.txt b/tests/auto/qmltest/buttonclick/CMakeLists.txt
index e00f5c9f93..1368afc73b 100644
--- a/tests/auto/qmltest/buttonclick/CMakeLists.txt
+++ b/tests/auto/qmltest/buttonclick/CMakeLists.txt
@@ -7,6 +7,12 @@
## buttonclick Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(buttonclick LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(buttonclick
GUI
QMLTEST
diff --git a/tests/auto/qmltest/buttonclick/tst_buttonclick.qml b/tests/auto/qmltest/buttonclick/tst_buttonclick.qml
index ba1537cd7c..9bbba7985c 100644
--- a/tests/auto/qmltest/buttonclick/tst_buttonclick.qml
+++ b/tests/auto/qmltest/buttonclick/tst_buttonclick.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/createbenchmark/CMakeLists.txt b/tests/auto/qmltest/createbenchmark/CMakeLists.txt
index 3da0d6e7db..f3cda2637c 100644
--- a/tests/auto/qmltest/createbenchmark/CMakeLists.txt
+++ b/tests/auto/qmltest/createbenchmark/CMakeLists.txt
@@ -7,6 +7,12 @@
## createbenchmark Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(createbenchmark LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(createbenchmark
GUI
QMLTEST
diff --git a/tests/auto/qmltest/createbenchmark/item.qml b/tests/auto/qmltest/createbenchmark/item.qml
index b37bc121db..9ab0a763f5 100644
--- a/tests/auto/qmltest/createbenchmark/item.qml
+++ b/tests/auto/qmltest/createbenchmark/item.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qmltest/createbenchmark/tst_createbenchmark.qml b/tests/auto/qmltest/createbenchmark/tst_createbenchmark.qml
index 0a40474f76..898bbb7f58 100644
--- a/tests/auto/qmltest/createbenchmark/tst_createbenchmark.qml
+++ b/tests/auto/qmltest/createbenchmark/tst_createbenchmark.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/events/CMakeLists.txt b/tests/auto/qmltest/events/CMakeLists.txt
index 53e022ca41..865a8ff762 100644
--- a/tests/auto/qmltest/events/CMakeLists.txt
+++ b/tests/auto/qmltest/events/CMakeLists.txt
@@ -7,6 +7,12 @@
## events Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(events LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(events
GUI
QMLTEST
diff --git a/tests/auto/qmltest/events/tst_drag.qml b/tests/auto/qmltest/events/tst_drag.qml
index 7be981de4c..6885baa873 100644
--- a/tests/auto/qmltest/events/tst_drag.qml
+++ b/tests/auto/qmltest/events/tst_drag.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/events/tst_events.qml b/tests/auto/qmltest/events/tst_events.qml
index 341292c1c0..0011b63249 100644
--- a/tests/auto/qmltest/events/tst_events.qml
+++ b/tests/auto/qmltest/events/tst_events.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Window 2.0
diff --git a/tests/auto/qmltest/events/tst_touch.qml b/tests/auto/qmltest/events/tst_touch.qml
index dba656e21c..105945eeb6 100644
--- a/tests/auto/qmltest/events/tst_touch.qml
+++ b/tests/auto/qmltest/events/tst_touch.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jeremy Katz
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Window 2.0
diff --git a/tests/auto/qmltest/events/tst_wheel.qml b/tests/auto/qmltest/events/tst_wheel.qml
index ec3b19de6e..9acd81910f 100644
--- a/tests/auto/qmltest/events/tst_wheel.qml
+++ b/tests/auto/qmltest/events/tst_wheel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/fontloader/CMakeLists.txt b/tests/auto/qmltest/fontloader/CMakeLists.txt
index 8700e106de..618896d90c 100644
--- a/tests/auto/qmltest/fontloader/CMakeLists.txt
+++ b/tests/auto/qmltest/fontloader/CMakeLists.txt
@@ -7,6 +7,12 @@
## fontloader Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(fontloader LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(fontloader
GUI
QMLTEST
diff --git a/tests/auto/qmltest/fontloader/tst_fontloader.qml b/tests/auto/qmltest/fontloader/tst_fontloader.qml
index fe873f9360..eea8b44107 100644
--- a/tests/auto/qmltest/fontloader/tst_fontloader.qml
+++ b/tests/auto/qmltest/fontloader/tst_fontloader.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.1
import QtTest 1.1
diff --git a/tests/auto/qmltest/fuzzycompare/CMakeLists.txt b/tests/auto/qmltest/fuzzycompare/CMakeLists.txt
index 4c93595376..83b505af71 100644
--- a/tests/auto/qmltest/fuzzycompare/CMakeLists.txt
+++ b/tests/auto/qmltest/fuzzycompare/CMakeLists.txt
@@ -7,6 +7,12 @@
## fuzzycompare Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(fuzzycompare LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(fuzzycompare
GUI
QMLTEST
diff --git a/tests/auto/qmltest/fuzzycompare/tst_FuzzyCompare.qml b/tests/auto/qmltest/fuzzycompare/tst_FuzzyCompare.qml
index 2e4ae8cc67..6beb89f848 100644
--- a/tests/auto/qmltest/fuzzycompare/tst_FuzzyCompare.qml
+++ b/tests/auto/qmltest/fuzzycompare/tst_FuzzyCompare.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 Alexander Akulich <akulichalexander@gmail.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtTest 1.0
TestCase {
diff --git a/tests/auto/qmltest/gradient/CMakeLists.txt b/tests/auto/qmltest/gradient/CMakeLists.txt
index 48a339f128..038281c495 100644
--- a/tests/auto/qmltest/gradient/CMakeLists.txt
+++ b/tests/auto/qmltest/gradient/CMakeLists.txt
@@ -7,6 +7,12 @@
## gradient Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(gradient LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(gradient
GUI
QMLTEST
diff --git a/tests/auto/qmltest/gradient/tst_gradient.qml b/tests/auto/qmltest/gradient/tst_gradient.qml
index 368f2ba27e..91fcfada89 100644
--- a/tests/auto/qmltest/gradient/tst_gradient.qml
+++ b/tests/auto/qmltest/gradient/tst_gradient.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/image/CMakeLists.txt b/tests/auto/qmltest/image/CMakeLists.txt
index 31d4cc2ce7..d9aa506b35 100644
--- a/tests/auto/qmltest/image/CMakeLists.txt
+++ b/tests/auto/qmltest/image/CMakeLists.txt
@@ -7,6 +7,12 @@
## image Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(image LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(image
GUI
QMLTEST
diff --git a/tests/auto/qmltest/image/tst_image.qml b/tests/auto/qmltest/image/tst_image.qml
index 9e1698cdef..5077e04024 100644
--- a/tests/auto/qmltest/image/tst_image.qml
+++ b/tests/auto/qmltest/image/tst_image.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/itemgrabber/CMakeLists.txt b/tests/auto/qmltest/itemgrabber/CMakeLists.txt
index 378cba80d6..34b0483cd8 100644
--- a/tests/auto/qmltest/itemgrabber/CMakeLists.txt
+++ b/tests/auto/qmltest/itemgrabber/CMakeLists.txt
@@ -7,6 +7,12 @@
## itemgrabber Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(itemgrabber LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(itemgrabber
GUI
QMLTEST
diff --git a/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml b/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml
index 6ee09a9a5b..aad8722f03 100644
--- a/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml
+++ b/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
import QtTest 1.1
diff --git a/tests/auto/qmltest/layout/CMakeLists.txt b/tests/auto/qmltest/layout/CMakeLists.txt
index abd6682556..4b3e254e9d 100644
--- a/tests/auto/qmltest/layout/CMakeLists.txt
+++ b/tests/auto/qmltest/layout/CMakeLists.txt
@@ -7,6 +7,12 @@
## layout Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(layout LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(layout
GUI
QMLTEST
diff --git a/tests/auto/qmltest/layout/Container.qml b/tests/auto/qmltest/layout/Container.qml
index 63b26be1f0..402a704622 100644
--- a/tests/auto/qmltest/layout/Container.qml
+++ b/tests/auto/qmltest/layout/Container.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.5
import QtQuick.Layouts 1.2
diff --git a/tests/auto/qmltest/layout/ContainerUser.qml b/tests/auto/qmltest/layout/ContainerUser.qml
index 7e26ee46c2..c13aa584e3 100644
--- a/tests/auto/qmltest/layout/ContainerUser.qml
+++ b/tests/auto/qmltest/layout/ContainerUser.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.6
import QtQuick.Window 2.2
diff --git a/tests/auto/qmltest/layout/tst_layout.qml b/tests/auto/qmltest/layout/tst_layout.qml
index 910ec60a54..5d9799c6ef 100644
--- a/tests/auto/qmltest/layout/tst_layout.qml
+++ b/tests/auto/qmltest/layout/tst_layout.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.0
diff --git a/tests/auto/qmltest/listmodel/CMakeLists.txt b/tests/auto/qmltest/listmodel/CMakeLists.txt
index a88402f813..d70bd288e1 100644
--- a/tests/auto/qmltest/listmodel/CMakeLists.txt
+++ b/tests/auto/qmltest/listmodel/CMakeLists.txt
@@ -7,6 +7,12 @@
## listmodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(listmodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(listmodel
GUI
QMLTEST
diff --git a/tests/auto/qmltest/listmodel/tst_listmodel.qml b/tests/auto/qmltest/listmodel/tst_listmodel.qml
index d959991050..4ee07d8162 100644
--- a/tests/auto/qmltest/listmodel/tst_listmodel.qml
+++ b/tests/auto/qmltest/listmodel/tst_listmodel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/listview/CMakeLists.txt b/tests/auto/qmltest/listview/CMakeLists.txt
index dd796a2086..6935b2cecf 100644
--- a/tests/auto/qmltest/listview/CMakeLists.txt
+++ b/tests/auto/qmltest/listview/CMakeLists.txt
@@ -7,6 +7,12 @@
## listview Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(listview LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(listview
GUI
QMLTEST
diff --git a/tests/auto/qmltest/listview/data/MultiDelegate.qml b/tests/auto/qmltest/listview/data/MultiDelegate.qml
index 5b7f9d12ac..491171d8e8 100644
--- a/tests/auto/qmltest/listview/data/MultiDelegate.qml
+++ b/tests/auto/qmltest/listview/data/MultiDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQml.Models 2.12
diff --git a/tests/auto/qmltest/listview/data/MultiDelegate2.qml b/tests/auto/qmltest/listview/data/MultiDelegate2.qml
index e3d0fc64cb..9ff7b44458 100644
--- a/tests/auto/qmltest/listview/data/MultiDelegate2.qml
+++ b/tests/auto/qmltest/listview/data/MultiDelegate2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQml.Models 2.12
diff --git a/tests/auto/qmltest/listview/data/MultiDelegate3.qml b/tests/auto/qmltest/listview/data/MultiDelegate3.qml
index a51dbbb49f..2e13364c66 100644
--- a/tests/auto/qmltest/listview/data/MultiDelegate3.qml
+++ b/tests/auto/qmltest/listview/data/MultiDelegate3.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQml.Models 2.12
diff --git a/tests/auto/qmltest/listview/data/asynclistviewloader.qml b/tests/auto/qmltest/listview/data/asynclistviewloader.qml
index 40d0c97b8c..1c500717db 100644
--- a/tests/auto/qmltest/listview/data/asynclistviewloader.qml
+++ b/tests/auto/qmltest/listview/data/asynclistviewloader.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qmltest/listview/data/asyncloadercurrentindex.qml b/tests/auto/qmltest/listview/data/asyncloadercurrentindex.qml
index 25976d5246..ec2cb6c24c 100644
--- a/tests/auto/qmltest/listview/data/asyncloadercurrentindex.qml
+++ b/tests/auto/qmltest/listview/data/asyncloadercurrentindex.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qmltest/listview/tst_listview.qml b/tests/auto/qmltest/listview/tst_listview.qml
index e9c91e10f2..8d5204db40 100644
--- a/tests/auto/qmltest/listview/tst_listview.qml
+++ b/tests/auto/qmltest/listview/tst_listview.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.1
import QtTest 1.1
diff --git a/tests/auto/qmltest/objectmodel/CMakeLists.txt b/tests/auto/qmltest/objectmodel/CMakeLists.txt
index abbe499257..6e92bb81a8 100644
--- a/tests/auto/qmltest/objectmodel/CMakeLists.txt
+++ b/tests/auto/qmltest/objectmodel/CMakeLists.txt
@@ -7,6 +7,12 @@
## objectmodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(objectmodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(objectmodel
GUI
QMLTEST
diff --git a/tests/auto/qmltest/objectmodel/tst_objectmodel.qml b/tests/auto/qmltest/objectmodel/tst_objectmodel.qml
index 440bf0abb5..61439b81d6 100644
--- a/tests/auto/qmltest/objectmodel/tst_objectmodel.qml
+++ b/tests/auto/qmltest/objectmodel/tst_objectmodel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.1
import QtQml.Models 2.3
diff --git a/tests/auto/qmltest/pathview/CMakeLists.txt b/tests/auto/qmltest/pathview/CMakeLists.txt
index b7d23f62cf..995958565c 100644
--- a/tests/auto/qmltest/pathview/CMakeLists.txt
+++ b/tests/auto/qmltest/pathview/CMakeLists.txt
@@ -7,6 +7,12 @@
## pathview Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(pathview LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(pathview
GUI
QMLTEST
diff --git a/tests/auto/qmltest/positioners/CMakeLists.txt b/tests/auto/qmltest/positioners/CMakeLists.txt
index a2fc28a487..2e91df68b7 100644
--- a/tests/auto/qmltest/positioners/CMakeLists.txt
+++ b/tests/auto/qmltest/positioners/CMakeLists.txt
@@ -7,6 +7,12 @@
## positioners Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(positioners LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(positioners
GUI
QMLTEST
diff --git a/tests/auto/qmltest/positioners/tst_positioners.qml b/tests/auto/qmltest/positioners/tst_positioners.qml
index 3933616de2..1c7f8ff95e 100644
--- a/tests/auto/qmltest/positioners/tst_positioners.qml
+++ b/tests/auto/qmltest/positioners/tst_positioners.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.9
import QtTest 1.1
diff --git a/tests/auto/qmltest/qqmlbinding/CMakeLists.txt b/tests/auto/qmltest/qqmlbinding/CMakeLists.txt
index ea35d622e4..8cb767a1ca 100644
--- a/tests/auto/qmltest/qqmlbinding/CMakeLists.txt
+++ b/tests/auto/qmltest/qqmlbinding/CMakeLists.txt
@@ -7,6 +7,12 @@
## qqmlbinding Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(qqmlbinding LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(qqmlbinding
GUI
QMLTEST
diff --git a/tests/auto/qmltest/qqmlbinding/tst_binding.qml b/tests/auto/qmltest/qqmlbinding/tst_binding.qml
index 783ec6dbed..981a88d738 100644
--- a/tests/auto/qmltest/qqmlbinding/tst_binding.qml
+++ b/tests/auto/qmltest/qqmlbinding/tst_binding.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/qqmlbinding/tst_binding2.qml b/tests/auto/qmltest/qqmlbinding/tst_binding2.qml
index 91ccb95f71..2bf5a0166a 100644
--- a/tests/auto/qmltest/qqmlbinding/tst_binding2.qml
+++ b/tests/auto/qmltest/qqmlbinding/tst_binding2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/qtbug46798/CMakeLists.txt b/tests/auto/qmltest/qtbug46798/CMakeLists.txt
index 83564df53f..492a9bab04 100644
--- a/tests/auto/qmltest/qtbug46798/CMakeLists.txt
+++ b/tests/auto/qmltest/qtbug46798/CMakeLists.txt
@@ -7,6 +7,12 @@
## qtbug46798 Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(qtbug46798 LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(qtbug46798
GUI
QMLTEST
diff --git a/tests/auto/qmltest/qtbug46798/tst_qtbug46798.qml b/tests/auto/qmltest/qtbug46798/tst_qtbug46798.qml
index f749705232..a99bdf7af7 100644
--- a/tests/auto/qmltest/qtbug46798/tst_qtbug46798.qml
+++ b/tests/auto/qmltest/qtbug46798/tst_qtbug46798.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtQml.Models 2.3
diff --git a/tests/auto/qmltest/rectangle/CMakeLists.txt b/tests/auto/qmltest/rectangle/CMakeLists.txt
index 08986a3013..9df9422824 100644
--- a/tests/auto/qmltest/rectangle/CMakeLists.txt
+++ b/tests/auto/qmltest/rectangle/CMakeLists.txt
@@ -7,6 +7,12 @@
## rectangle Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(rectangle LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(rectangle
GUI
QMLTEST
diff --git a/tests/auto/qmltest/rectangle/tst_rectangle.qml b/tests/auto/qmltest/rectangle/tst_rectangle.qml
index 4292ea02cf..ab479cbbbf 100644
--- a/tests/auto/qmltest/rectangle/tst_rectangle.qml
+++ b/tests/auto/qmltest/rectangle/tst_rectangle.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtTest 1.1
diff --git a/tests/auto/qmltest/selftests/CMakeLists.txt b/tests/auto/qmltest/selftests/CMakeLists.txt
index 8122f203ee..d2af0775b1 100644
--- a/tests/auto/qmltest/selftests/CMakeLists.txt
+++ b/tests/auto/qmltest/selftests/CMakeLists.txt
@@ -7,6 +7,12 @@
## selftests Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(selftests LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(selftests
GUI
QMLTEST
diff --git a/tests/auto/qmltest/selftests/tst_compare.qml b/tests/auto/qmltest/selftests/tst_compare.qml
index 04949d5e9a..62ce80944f 100644
--- a/tests/auto/qmltest/selftests/tst_compare.qml
+++ b/tests/auto/qmltest/selftests/tst_compare.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/selftests/tst_compare_quickobjects.qml b/tests/auto/qmltest/selftests/tst_compare_quickobjects.qml
index 30c7133e97..90a1f31bcc 100644
--- a/tests/auto/qmltest/selftests/tst_compare_quickobjects.qml
+++ b/tests/auto/qmltest/selftests/tst_compare_quickobjects.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/selftests/tst_createTemporaryObject.qml b/tests/auto/qmltest/selftests/tst_createTemporaryObject.qml
index a54e5f1e7b..2d9742dc5b 100644
--- a/tests/auto/qmltest/selftests/tst_createTemporaryObject.qml
+++ b/tests/auto/qmltest/selftests/tst_createTemporaryObject.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.8
import QtQuick.Window 2.2
diff --git a/tests/auto/qmltest/selftests/tst_datadriven.qml b/tests/auto/qmltest/selftests/tst_datadriven.qml
index 49024699a6..a26233f40a 100644
--- a/tests/auto/qmltest/selftests/tst_datadriven.qml
+++ b/tests/auto/qmltest/selftests/tst_datadriven.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/selftests/tst_destroy.qml b/tests/auto/qmltest/selftests/tst_destroy.qml
index 96814c4b77..880e03936e 100644
--- a/tests/auto/qmltest/selftests/tst_destroy.qml
+++ b/tests/auto/qmltest/selftests/tst_destroy.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.1
import QtTest 1.1
diff --git a/tests/auto/qmltest/selftests/tst_findChild.qml b/tests/auto/qmltest/selftests/tst_findChild.qml
index c8af04810a..6cdaee4de9 100644
--- a/tests/auto/qmltest/selftests/tst_findChild.qml
+++ b/tests/auto/qmltest/selftests/tst_findChild.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/selftests/tst_grabImage.qml b/tests/auto/qmltest/selftests/tst_grabImage.qml
index 9cc22db9a6..9a1bfccdc9 100644
--- a/tests/auto/qmltest/selftests/tst_grabImage.qml
+++ b/tests/auto/qmltest/selftests/tst_grabImage.qml
@@ -1,6 +1,6 @@
// Copyright (C) 2017 Crimson AS <info@crimson.no>
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/selftests/tst_multiTestCase.qml b/tests/auto/qmltest/selftests/tst_multiTestCase.qml
index 220888a5da..90a6df8c2f 100644
--- a/tests/auto/qmltest/selftests/tst_multiTestCase.qml
+++ b/tests/auto/qmltest/selftests/tst_multiTestCase.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtTest
import QtQuick
diff --git a/tests/auto/qmltest/selftests/tst_selftests.qml b/tests/auto/qmltest/selftests/tst_selftests.qml
index 35089be68e..597a13632f 100644
--- a/tests/auto/qmltest/selftests/tst_selftests.qml
+++ b/tests/auto/qmltest/selftests/tst_selftests.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/selftests/tst_signalspy.qml b/tests/auto/qmltest/selftests/tst_signalspy.qml
new file mode 100644
index 0000000000..4346003a6f
--- /dev/null
+++ b/tests/auto/qmltest/selftests/tst_signalspy.qml
@@ -0,0 +1,53 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtTest
+
+TestCase {
+ id: testCase
+ name: "SignalSpy"
+
+ Component {
+ id: itemWithAmbigiousSignalNameOnChild
+ Item {
+ property Item child: Item {
+ property bool opened: true
+ signal opened()
+ }
+ }
+ }
+
+ Component {
+ id: signalSpy
+ SignalSpy {}
+ }
+
+ function init() {
+ failOnWarning(/.?/)
+ }
+
+ function test_ambigiousSignalName() {
+ let control = createTemporaryObject(itemWithAmbigiousSignalNameOnChild, testCase)
+ verify(control)
+
+ let openedSpy = signalSpy.createObject(control, {target: control.child, signalName: "opened"})
+ verify(openedSpy)
+ compare(openedSpy.target, control.child)
+ compare(openedSpy.signalName, "opened")
+ verify(openedSpy.valid)
+
+ // reset the target, i.e. disconnect the spy
+ openedSpy.target = null
+ compare(openedSpy.target, null)
+ compare(openedSpy.signalName, "opened")
+ verify(!openedSpy.valid)
+
+ // connect again to check that it will be disconnected
+ // on SignalSpy destruction with no issues/warnings/etc.
+ openedSpy.target = control.child
+ compare(openedSpy.target, control.child)
+ compare(openedSpy.signalName, "opened")
+ verify(openedSpy.valid)
+ }
+}
diff --git a/tests/auto/qmltest/selftests/tst_stringify.qml b/tests/auto/qmltest/selftests/tst_stringify.qml
index d4cd02e4b4..ed228417e2 100644
--- a/tests/auto/qmltest/selftests/tst_stringify.qml
+++ b/tests/auto/qmltest/selftests/tst_stringify.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/selftests/tst_tryVerify.qml b/tests/auto/qmltest/selftests/tst_tryVerify.qml
index 653afeac75..b510874c47 100644
--- a/tests/auto/qmltest/selftests/tst_tryVerify.qml
+++ b/tests/auto/qmltest/selftests/tst_tryVerify.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.8
import QtTest 1.1
diff --git a/tests/auto/qmltest/shadersource/CMakeLists.txt b/tests/auto/qmltest/shadersource/CMakeLists.txt
index d95af4100c..477aebbe7f 100644
--- a/tests/auto/qmltest/shadersource/CMakeLists.txt
+++ b/tests/auto/qmltest/shadersource/CMakeLists.txt
@@ -7,6 +7,12 @@
## shadersource Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(shadersource LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(shadersource
GUI
QMLTEST
diff --git a/tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml b/tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml
index daec74f745..9679298b46 100644
--- a/tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml
+++ b/tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtQuick.Window 2.0
diff --git a/tests/auto/qmltest/shadersource/tst_DynamicallyCreatedSource.qml b/tests/auto/qmltest/shadersource/tst_DynamicallyCreatedSource.qml
index 4d79062ed5..4e018143dd 100644
--- a/tests/auto/qmltest/shadersource/tst_DynamicallyCreatedSource.qml
+++ b/tests/auto/qmltest/shadersource/tst_DynamicallyCreatedSource.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Gunnar Sletta <gunnar@sletta.org>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml b/tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml
index 8391225933..c615ea3073 100644
--- a/tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml
+++ b/tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Window 2.0
diff --git a/tests/auto/qmltest/shadersource/tst_SourceItem.qml b/tests/auto/qmltest/shadersource/tst_SourceItem.qml
index 18e685b9b8..d7d50c8187 100644
--- a/tests/auto/qmltest/shadersource/tst_SourceItem.qml
+++ b/tests/auto/qmltest/shadersource/tst_SourceItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/shadersource/tst_SourcedFromOtherWindow.qml b/tests/auto/qmltest/shadersource/tst_SourcedFromOtherWindow.qml
index 2da2820fea..052b95dc2c 100644
--- a/tests/auto/qmltest/shadersource/tst_SourcedFromOtherWindow.qml
+++ b/tests/auto/qmltest/shadersource/tst_SourcedFromOtherWindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Window 2.0
diff --git a/tests/auto/qmltest/stability/CMakeLists.txt b/tests/auto/qmltest/stability/CMakeLists.txt
index a2af01649e..14f74822d8 100644
--- a/tests/auto/qmltest/stability/CMakeLists.txt
+++ b/tests/auto/qmltest/stability/CMakeLists.txt
@@ -7,6 +7,12 @@
## stability Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(stability LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(stability
GUI
QMLTEST
diff --git a/tests/auto/qmltest/stability/tst_unloadrepeater.qml b/tests/auto/qmltest/stability/tst_unloadrepeater.qml
index d446d916db..064df03fcb 100644
--- a/tests/auto/qmltest/stability/tst_unloadrepeater.qml
+++ b/tests/auto/qmltest/stability/tst_unloadrepeater.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest/text/CMakeLists.txt b/tests/auto/qmltest/text/CMakeLists.txt
index 41621ff0f3..91966a7712 100644
--- a/tests/auto/qmltest/text/CMakeLists.txt
+++ b/tests/auto/qmltest/text/CMakeLists.txt
@@ -7,6 +7,12 @@
## text Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(text LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(text
GUI
QMLTEST
diff --git a/tests/auto/qmltest/text/tst_text.qml b/tests/auto/qmltest/text/tst_text.qml
index 407238b0f3..7366e94067 100644
--- a/tests/auto/qmltest/text/tst_text.qml
+++ b/tests/auto/qmltest/text/tst_text.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/textedit/CMakeLists.txt b/tests/auto/qmltest/textedit/CMakeLists.txt
index 863a9f5ba3..0b955a0fef 100644
--- a/tests/auto/qmltest/textedit/CMakeLists.txt
+++ b/tests/auto/qmltest/textedit/CMakeLists.txt
@@ -7,6 +7,12 @@
## textedit Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(textedit LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(textedit
GUI
QMLTEST
diff --git a/tests/auto/qmltest/textedit/tst_textedit.qml b/tests/auto/qmltest/textedit/tst_textedit.qml
index bf53965ae5..c161429de0 100644
--- a/tests/auto/qmltest/textedit/tst_textedit.qml
+++ b/tests/auto/qmltest/textedit/tst_textedit.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/qmltest/textedit/tst_textedit_editingfinished.qml b/tests/auto/qmltest/textedit/tst_textedit_editingfinished.qml
index 1cc338fdea..493f214cb7 100644
--- a/tests/auto/qmltest/textedit/tst_textedit_editingfinished.qml
+++ b/tests/auto/qmltest/textedit/tst_textedit_editingfinished.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.6
import QtTest 1.1
diff --git a/tests/auto/qmltest/textinput/CMakeLists.txt b/tests/auto/qmltest/textinput/CMakeLists.txt
index 832dc58040..4397d05216 100644
--- a/tests/auto/qmltest/textinput/CMakeLists.txt
+++ b/tests/auto/qmltest/textinput/CMakeLists.txt
@@ -7,6 +7,12 @@
## textinput Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(textinput LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(textinput
GUI
QMLTEST
diff --git a/tests/auto/qmltest/textinput/tst_textinput.qml b/tests/auto/qmltest/textinput/tst_textinput.qml
index e734c44370..1a19c5b633 100644
--- a/tests/auto/qmltest/textinput/tst_textinput.qml
+++ b/tests/auto/qmltest/textinput/tst_textinput.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.14
import QtTest 1.1
@@ -97,7 +97,8 @@ Item {
}
function test_textentry() {
- txtentry.focus = true;
+ txtentry.forceActiveFocus()
+ verify(txtentry.activeFocus)
compare(txtentry.text, "")
keyClick(Qt.Key_H)
keyClick(Qt.Key_E)
diff --git a/tests/auto/qmltest/url/tst_url.qml b/tests/auto/qmltest/url/tst_url.qml
index 23bcc9b744..b3d46d6375 100644
--- a/tests/auto/qmltest/url/tst_url.qml
+++ b/tests/auto/qmltest/url/tst_url.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtTest 1.1
diff --git a/tests/auto/qmltest/window/CMakeLists.txt b/tests/auto/qmltest/window/CMakeLists.txt
index e80aa68dfd..da79240583 100644
--- a/tests/auto/qmltest/window/CMakeLists.txt
+++ b/tests/auto/qmltest/window/CMakeLists.txt
@@ -7,6 +7,12 @@
## window Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(window LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(window
GUI
QMLTEST
diff --git a/tests/auto/qmltest/window/tst_clickwindow.qml b/tests/auto/qmltest/window/tst_clickwindow.qml
index 81144c0923..d2ab052332 100644
--- a/tests/auto/qmltest/window/tst_clickwindow.qml
+++ b/tests/auto/qmltest/window/tst_clickwindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Window 2.0
diff --git a/tests/auto/quick/CMakeLists.txt b/tests/auto/quick/CMakeLists.txt
index 2ef42c5b2f..32a893defb 100644
--- a/tests/auto/quick/CMakeLists.txt
+++ b/tests/auto/quick/CMakeLists.txt
@@ -14,6 +14,7 @@ endif()
add_subdirectory(drawingmodes)
if(QT_FEATURE_private_tests)
+ add_subdirectory(doc)
add_subdirectory(examples)
add_subdirectory(nokeywords)
add_subdirectory(propertyrequirements)
@@ -42,6 +43,7 @@ if(QT_FEATURE_private_tests)
add_subdirectory(qquickdynamicpropertyanimation)
add_subdirectory(qquickborderimage)
add_subdirectory(qquickwindow)
+ add_subdirectory(qquickwindowcontainer)
add_subdirectory(qquickdeliveryagent)
add_subdirectory(qquickdrag)
add_subdirectory(qquickdragattached)
@@ -77,10 +79,10 @@ if(QT_FEATURE_private_tests)
add_subdirectory(qquickvisualdatamodel)
add_subdirectory(qquickview)
add_subdirectory(qquickview_extra)
- if(NOT ANDROID) # QTBUG-103099
- add_subdirectory(qquickcanvasitem)
+ add_subdirectory(qquickcanvasitem)
+ if(QT_FEATURE_quick_designer)
+ add_subdirectory(qquickdesignersupport)
endif()
- add_subdirectory(qquickdesignersupport)
add_subdirectory(qquickscreen)
add_subdirectory(touchmouse)
add_subdirectory(scenegraph)
@@ -91,8 +93,9 @@ if(QT_FEATURE_private_tests)
add_subdirectory(qquickshadereffect)
add_subdirectory(qquickanimatedsprite)
add_subdirectory(qquickspritesequence)
- add_subdirectory(qquickitemrhiintegration)
+ add_subdirectory(qquickrhiitem)
add_subdirectory(rendernode)
+ add_subdirectory(platform)
if(QT_FEATURE_opengl)
add_subdirectory(qquickframebufferobject)
diff --git a/tests/auto/quick/doc/CMakeLists.txt b/tests/auto/quick/doc/CMakeLists.txt
new file mode 100644
index 0000000000..1a7e1b834e
--- /dev/null
+++ b/tests/auto/quick/doc/CMakeLists.txt
@@ -0,0 +1,7 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# This directory contains auto tests for documentation examples/snippets.
+
+add_subdirectory(how-tos)
+
diff --git a/tests/auto/quick/doc/how-tos/CMakeLists.txt b/tests/auto/quick/doc/how-tos/CMakeLists.txt
new file mode 100644
index 0000000000..202ff38bb5
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/CMakeLists.txt
@@ -0,0 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+add_subdirectory(how-to-cpp-button)
+add_subdirectory(how-to-cpp-enum-js)
+add_subdirectory(how-to-qml)
diff --git a/tests/auto/quick/doc/how-tos/how-to-cpp-button/CMakeLists.txt b/tests/auto/quick/doc/how-tos/how-to-cpp-button/CMakeLists.txt
new file mode 100644
index 0000000000..34f370c7b3
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-cpp-button/CMakeLists.txt
@@ -0,0 +1,31 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_how-to-cpp-button LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_how-to-cpp-button
+ SOURCES
+ tst_how-to-cpp-button.cpp
+ LIBRARIES
+ Qt::Core
+ Qt::Gui
+ Qt::Quick
+ Qt::QuickPrivate
+ Qt::QuickControlsTestUtilsPrivate
+ Qt::QuickTemplates2Private
+)
+
+qt_policy(SET QTP0001 NEW)
+
+qt_add_qml_module(tst_how-to-cpp-button
+ URI MyModule
+ QML_FILES
+ Main.qml
+ SOURCES
+ backend.h
+ backend.cpp
+)
diff --git a/tests/auto/quick/doc/how-tos/how-to-cpp-button/Main.qml b/tests/auto/quick/doc/how-tos/how-to-cpp-button/Main.qml
new file mode 100644
index 0000000000..5150f6c6d6
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-cpp-button/Main.qml
@@ -0,0 +1,19 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+//! [file]
+import QtQuick.Controls
+
+import MyModule
+
+ApplicationWindow {
+ width: 400
+ height: 400
+ title: qsTr("C++ Button example")
+
+ Button {
+ text: qsTr("Click me")
+ onClicked: Backend.doStuff()
+ }
+}
+//! [file]
diff --git a/tests/auto/quick/doc/how-tos/how-to-cpp-button/backend.cpp b/tests/auto/quick/doc/how-tos/how-to-cpp-button/backend.cpp
new file mode 100644
index 0000000000..4143aea9e6
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-cpp-button/backend.cpp
@@ -0,0 +1,13 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+//! [file]
+#include "backend.h"
+
+#include <QDebug>
+
+void Backend::doStuff()
+{
+ qDebug() << "Did stuff!";
+}
+//! [file]
diff --git a/tests/auto/quick/doc/how-tos/how-to-cpp-button/backend.h b/tests/auto/quick/doc/how-tos/how-to-cpp-button/backend.h
new file mode 100644
index 0000000000..10249f5416
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-cpp-button/backend.h
@@ -0,0 +1,17 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+//! [file]
+#include <QObject>
+#include <QQmlEngine>
+
+class Backend : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+
+public:
+ Q_INVOKABLE void doStuff();
+};
+//! [file]
diff --git a/tests/auto/quick/doc/how-tos/how-to-cpp-button/tst_how-to-cpp-button.cpp b/tests/auto/quick/doc/how-tos/how-to-cpp-button/tst_how-to-cpp-button.cpp
new file mode 100644
index 0000000000..792f84ffc2
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-cpp-button/tst_how-to-cpp-button.cpp
@@ -0,0 +1,53 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtCore/qregularexpression.h>
+#include <QtTest/QtTest>
+#include <QtQml/qqmlapplicationengine.h>
+#include <QtQuick/qquickwindow.h>
+#include <QtQuickTemplates2/private/qquickbutton_p.h>
+#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QQuickControlsTestUtils;
+
+class tst_HowToCppButton : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_HowToCppButton();
+
+private slots:
+ void example();
+};
+
+tst_HowToCppButton::tst_HowToCppButton()
+{
+}
+
+void tst_HowToCppButton::example()
+{
+ QTest::failOnWarning(QRegularExpression(QStringLiteral(".?")));
+
+ QQmlApplicationEngine engine;
+ engine.loadFromModule("MyModule", "Main");
+ QCOMPARE(engine.rootObjects().size(), 1);
+
+ auto *window = qobject_cast<QQuickWindow*>(engine.rootObjects().at(0));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *button = window->findChild<QQuickButton*>();
+ QVERIFY(button);
+ QCOMPARE(button->text(), "Click me");
+ QTest::ignoreMessage(QtDebugMsg, "Did stuff!");
+ QVERIFY(clickButton(button));
+}
+
+QT_END_NAMESPACE
+
+QTEST_MAIN(tst_HowToCppButton)
+
+#include "tst_how-to-cpp-button.moc"
diff --git a/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/CMakeLists.txt b/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/CMakeLists.txt
new file mode 100644
index 0000000000..5adc456b4b
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/CMakeLists.txt
@@ -0,0 +1,25 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_how-to-cpp-enum-js LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_how-to-cpp-enum-js
+ SOURCES
+ backend.cpp
+ backend.h
+ tst_how-to-cpp-enum-js.cpp
+ LIBRARIES
+ Qt::Core
+ Qt::Qml
+)
+
+qt_add_resources(tst_how-to-cpp-enum-js "js"
+ PREFIX
+ /
+ FILES
+ script.mjs
+)
diff --git a/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/backend.cpp b/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/backend.cpp
new file mode 100644
index 0000000000..a78678cc18
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/backend.cpp
@@ -0,0 +1,36 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+//! [file]
+#include "backend.h"
+
+Backend::Backend(QJSEngine *engine) :
+ mEngine(engine)
+{
+}
+
+bool Backend::load()
+{
+ // Do some loading here...
+
+ const QJSValue module = mEngine->importModule(":/script.mjs");
+ if (module.isError()) {
+ qWarning() << "Error loading script.mjs:" << module.toString();
+ return false;
+ }
+
+ const QJSValue function = module.property("backendStatusUpdate");
+ if (!function.isCallable()) {
+ qWarning() << "backendStatusUpdate script function is not callable!";
+ return false;
+ }
+
+ const QJSValue functionResult = function.call(QJSValueList() << Loaded);
+ if (functionResult.isError()) {
+ qWarning() << "backendStatusUpdate script function had errors:" << functionResult.toString();
+ return false;
+ }
+
+ return true;
+}
+//! [file]
diff --git a/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/backend.h b/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/backend.h
new file mode 100644
index 0000000000..5e723d406e
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/backend.h
@@ -0,0 +1,29 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+//! [file]
+#include <QObject>
+#include <QJSEngine>
+
+class Backend : public QObject
+{
+ Q_OBJECT
+
+public:
+ Backend(QJSEngine *engine);
+
+ enum Status {
+ Unknown,
+ Error,
+ Loading,
+ Loaded
+ };
+
+ Q_ENUM(Status)
+
+ bool load();
+
+private:
+ QJSEngine *mEngine = nullptr;
+};
+//! [file]
diff --git a/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/script.mjs b/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/script.mjs
new file mode 100644
index 0000000000..a4f929222a
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/script.mjs
@@ -0,0 +1,13 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+//! [file]
+export function backendStatusUpdate(backendStatus) {
+ if (backendStatus === Backend.Error) {
+ console.warn("Error!")
+ return
+ }
+
+ console.log("Backend loaded successfully")
+}
+//! [file]
diff --git a/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/tst_how-to-cpp-enum-js.cpp b/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/tst_how-to-cpp-enum-js.cpp
new file mode 100644
index 0000000000..933a1cf3e3
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-cpp-enum-js/tst_how-to-cpp-enum-js.cpp
@@ -0,0 +1,47 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtCore/qregularexpression.h>
+#include <QtTest/QtTest>
+#include <QtQml/qjsengine.h>
+
+#include "backend.h"
+
+QT_BEGIN_NAMESPACE
+
+class tst_HowToCppEnumJs : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_HowToCppEnumJs();
+
+private slots:
+ void example();
+};
+
+tst_HowToCppEnumJs::tst_HowToCppEnumJs()
+{
+}
+
+void tst_HowToCppEnumJs::example()
+{
+ QTest::failOnWarning(QRegularExpression(QStringLiteral(".?")));
+
+ QJSEngine engine;
+ engine.installExtensions(QJSEngine::AllExtensions);
+
+ QJSValue backendJsMetaObject = engine.newQMetaObject(&Backend::staticMetaObject);
+ engine.globalObject().setProperty("Backend", backendJsMetaObject);
+
+ QTest::ignoreMessage(QtDebugMsg, "Backend loaded successfully");
+ Backend backend(&engine);
+ const bool loaded = backend.load();
+ QVERIFY(loaded);
+}
+
+QT_END_NAMESPACE
+
+QTEST_MAIN(tst_HowToCppEnumJs)
+
+#include "tst_how-to-cpp-enum-js.moc"
diff --git a/tests/auto/quick/doc/how-tos/how-to-qml/BLACKLIST b/tests/auto/quick/doc/how-tos/how-to-qml/BLACKLIST
new file mode 100644
index 0000000000..c878ca06be
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-qml/BLACKLIST
@@ -0,0 +1,5 @@
+# QTBUG-126222
+[activeFocusDebugging]
+macOS
+ubuntu-22.04
+
diff --git a/tests/auto/quick/doc/how-tos/how-to-qml/CMakeLists.txt b/tests/auto/quick/doc/how-tos/how-to-qml/CMakeLists.txt
new file mode 100644
index 0000000000..bdf84439c8
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-qml/CMakeLists.txt
@@ -0,0 +1,33 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_how-to-qml LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_how-to-qml
+ SOURCES
+ tst_how-to-qml.cpp
+ LIBRARIES
+ Qt::Core
+ Qt::Gui
+ Qt::Quick
+ Qt::QuickPrivate
+ Qt::QuickControlsTestUtilsPrivate
+ Qt::QuickTemplates2Private
+)
+
+qt_policy(SET QTP0001 NEW)
+
+qt_add_qml_module(tst_how-to-qml
+ URI HowToQml
+ QML_FILES
+ active-focus-debugging/ActiveFocusDebuggingMain.qml
+ time-picker/TimeComponentLabel.qml
+ time-picker/TimePickerDialog.qml
+ time-picker/TimePickerMain.qml
+ time-picker/TimePickerLabel.qml
+ time-picker/TimePicker.qml
+)
diff --git a/tests/auto/quick/doc/how-tos/how-to-qml/active-focus-debugging/ActiveFocusDebuggingMain.qml b/tests/auto/quick/doc/how-tos/how-to-qml/active-focus-debugging/ActiveFocusDebuggingMain.qml
new file mode 100644
index 0000000000..b0f48cdb59
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-qml/active-focus-debugging/ActiveFocusDebuggingMain.qml
@@ -0,0 +1,25 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+//! [file]
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 400
+ height: 400
+ visible: true
+ title: qsTr("Active focus debugging example")
+
+ onActiveFocusItemChanged: print("activeFocusItem: " + activeFocusItem)
+
+ Row {
+ TextField {
+ objectName: "textField1"
+ }
+ TextField {
+ objectName: "textField2"
+ }
+ }
+}
+//! [file]
diff --git a/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimeComponentLabel.qml b/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimeComponentLabel.qml
new file mode 100644
index 0000000000..6b1653bde5
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimeComponentLabel.qml
@@ -0,0 +1,29 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls.Material
+
+Label {
+ id: root
+ fontSizeMode: Label.Fit
+ horizontalAlignment: Label.AlignHCenter
+ verticalAlignment: Label.AlignVCenter
+
+ Material.foreground: Material.theme === Material.Light
+ ? Material.color(Material.Indigo, !dim ? Material.Shade500 : Material.Shade100)
+ : Material.color(Material.Indigo, dim ? Material.Shade300 : Material.Shade100)
+
+ Layout.fillHeight: true
+
+ property bool dim: false
+ property alias interactive: tapHandler.enabled
+
+ signal tapped
+
+ TapHandler {
+ id: tapHandler
+ onTapped: root.tapped()
+ }
+}
diff --git a/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePicker.qml b/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePicker.qml
new file mode 100644
index 0000000000..edcf864784
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePicker.qml
@@ -0,0 +1,325 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+//! [file]
+import QtQuick
+import QtQuick.Controls.Material
+
+Item {
+ id: root
+ implicitWidth: 250
+ implicitHeight: 250
+
+ enum Mode {
+ Hours,
+ Minutes
+ }
+
+ property int mode: TimePicker.Mode.Hours
+ property int hours
+ property int minutes
+ property bool is24Hour
+ property bool interactive: true
+
+ // The mode that the label delegates see, so that we can
+ // animate their opacity before their text changes.
+ property int __effectiveMode: TimePicker.Mode.Hours
+ // For 12 hour pickers, we can use 0 to 60 to represent all values.
+ property int __value: 0
+ // For 24 hour pickers, we need to store this extra flag.
+ property bool __is24HourValueSelected
+ // How many values the arm should snap to at a time.
+ readonly property int __stepSize: __getStepSize(mode)
+ readonly property int __to: 60
+ readonly property int __labelAngleStepSize: 360 / 12
+ property bool __switchingModes
+
+ // This signal could be used if TimePicker is used as a standalone component.
+ // It's emitted when the minute is selected.
+ signal accepted()
+
+ // Convenience for setting each property individually, but also
+ // ensures that the selector arm is properly rotated when there is
+ // a programmatic change in hours or minutes but not mode.
+ function openWith(mode, hours, minutes) {
+ root.mode = mode
+ root.hours = hours
+ root.minutes = minutes
+ __updateAfterModeOrTimeChange()
+ }
+
+ // Until QML gets private properties (QTBUG-11984), use the traditional
+ // double-underscore convention.
+ function __angleForValue(value: int): real {
+ return (value / __to) * 360
+ }
+
+ function __getStepSize(mode) {
+ return mode === TimePicker.Mode.Hours ? 5 : 1
+ }
+
+ function __updateAfterModeOrTimeChange() {
+ // We use a function for this rather than a binding, because we could be called before the
+ // __stepSize binding is evaluated.
+ if (mode === TimePicker.Mode.Hours) {
+ // modulo the hours value by __to because we want 60 (12) to be 0.
+ __value = hours * __getStepSize(mode) % __to
+ } else {
+ __value = minutes
+ }
+
+ __is24HourValueSelected = mode === TimePicker.Mode.Hours && hours >= 13
+ }
+
+ onModeChanged: __updateAfterModeOrTimeChange()
+
+ onIs24HourChanged: {
+ // Don't allow 24-hour values when we're not a 24-hour picker.
+ if (!is24Hour && hours > 12)
+ hours = 12
+ }
+
+ // Center dot.
+ Rectangle {
+ width: 6
+ height: 6
+ radius: width / 2
+ color: Material.primary
+ anchors.centerIn: parent
+ z: 1
+ }
+
+ Rectangle {
+ id: contentContainer
+ objectName: "contentContainer"
+ width: Math.min(parent.width, parent.height)
+ height: width
+ radius: width / 2
+ anchors.centerIn: parent
+ color: Material.theme === Material.Light ? "#eeeeee" : "#626262"
+
+ // Animate this so that we don't need an intermediate parent item for the
+ // labels to animate the opacity of that instead. That item would be required
+ // because we don't want to change the opacity of the contentContainer Rectangle.
+ property real labelOpacity: 1
+
+ function updateValueAfterPressPointChange() {
+ const y1 = height / 2
+ const x1 = width / 2
+ const y2 = tapHandler.point.position.y
+ const x2 = tapHandler.point.position.x
+ const yDistance = y2 - y1
+ const xDistance = x2 - x1
+ const angle = Math.atan2(yDistance, xDistance)
+
+ let angleInDegrees = (angle * (180 / Math.PI)) + 90.0
+ if (angleInDegrees < 0)
+ angleInDegrees = 360 + angleInDegrees
+
+ const normalisedAngle = angleInDegrees / 360.0
+ const rawValue = normalisedAngle * __to
+ // Snap to each step.
+ const steppedValue = Math.round(rawValue / __stepSize) * __stepSize
+ root.__value = steppedValue
+ // Account for the area where the angle wraps around from 360 to 0,
+ // otherwise values from 59.5 to 59.999[...] will register as 60 instead of 0.
+ if (rawValue > __to - __stepSize / 2)
+ root.__value = 0
+
+ const distanceFromCenter = Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2))
+ // Only allow selecting 24 hour values when it's in the correct mode.
+ root.__is24HourValueSelected = root.is24Hour && root.__effectiveMode === TimePicker.Mode.Hours
+ && distanceFromCenter < distanceFromCenterForLabels(true) + selectionIndicator.height * 0.5
+ }
+
+ // Returns the distance from our center at which a label should be centered over given is24Hour.
+ function distanceFromCenterForLabels(is24Hour) {
+ return contentContainer.radius - (is24Hour
+ ? selectionIndicator.height * 1.5 : selectionIndicator.height * 0.5)
+ }
+
+ states: [
+ State {
+ name: "hours"
+ when: root.mode === TimePicker.Mode.Hours
+ },
+ State {
+ name: "minutes"
+ when: root.mode === TimePicker.Mode.Minutes
+ }
+ ]
+
+ transitions: [
+ Transition {
+ // When the picker isn't interactive (e.g. when a dialog is opening),
+ // we shouldn't animate the opacity of the labels, as it looks wrong,
+ // and should only happen when switching between modes while the
+ // picker was already visible.
+ enabled: root.interactive
+
+ SequentialAnimation {
+ NumberAnimation {
+ target: contentContainer
+ property: "labelOpacity"
+ from: 1
+ to: 0
+ duration: 100
+ }
+
+ ScriptAction {
+ script: root.__effectiveMode = root.mode
+ }
+
+ NumberAnimation {
+ target: contentContainer
+ property: "labelOpacity"
+ from: 0
+ to: 1
+ duration: 100
+ }
+ }
+ },
+ Transition {
+ enabled: !root.interactive
+
+ // Since the transition above doesn't run when we're not interactive,
+ // we need to do the immediate property change here.
+ // See QTBUG-13268 for why we use a ScriptAction and not PropertyAction.
+ ScriptAction {
+ script: root.__effectiveMode = root.mode
+ }
+ }
+
+ ]
+
+ TapHandler {
+ id: tapHandler
+ gesturePolicy: TapHandler.ReleaseWithinBounds
+ // Don't allow input while switching modes, or a click on an hour could go through to a minute.
+ enabled: root.interactive && root.__effectiveMode === root.mode
+
+ onPointChanged: {
+ if (pressed) {
+ // Don't call this when not pressed, as the position will be invalid.
+ contentContainer.updateValueAfterPressPointChange()
+
+ // Update the value (like a "live" Slider) while the pointer position changes.
+ if (mode === TimePicker.Mode.Hours) {
+ root.hours = root.__value / root.__stepSize
+
+ if (root.hours === 0) {
+ // A value of 0 (when it's not a 24-hour picker) is 12.
+ // When it is a 24-hour picker, it's 0.
+ if (!root.__is24HourValueSelected)
+ root.hours = 12
+ } else if (root.__is24HourValueSelected) {
+ root.hours += 12
+ }
+ } else {
+ root.minutes = root.__value
+ }
+ } else {
+ // Select the value that was chosen in the press code above.
+ if (mode === TimePicker.Mode.Hours) {
+ mode = TimePicker.Mode.Minutes
+ } else {
+ // Does nothing in our example, but could be used to hide the dialog
+ // if it didn't have an OK button to accept it.
+ root.accepted()
+ }
+ }
+ }
+ }
+
+ // The line connecting the center dot to the selection indicator.
+ Rectangle {
+ id: selectionArm
+ objectName: "selectionArm"
+ width: 2
+ height: contentContainer.distanceFromCenterForLabels(root.__is24HourValueSelected)
+ color: Material.primary
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.verticalCenter
+ rotation: root.__angleForValue(root.__value)
+ transformOrigin: Item.Bottom
+ antialiasing: true
+
+ Rectangle {
+ id: selectionIndicator
+ objectName: "selectionIndicator"
+ width: 40
+ height: 40
+ radius: width / 2
+ color: Material.primary
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.top
+
+ Rectangle {
+ width: 4
+ height: 4
+ radius: width / 2
+ color: Material.color(Material.Indigo, Material.Shade100)
+ anchors.centerIn: parent
+ // Only show the circle within the indicator between minute labels.
+ visible: root.__effectiveMode === TimePicker.Mode.Minutes
+ && root.__value % 5 !== 0
+ }
+ }
+ }
+
+ Repeater {
+ id: labelRepeater
+ model: root.mode === TimePicker.Mode.Hours && root.is24Hour ? 24 : 12
+ delegate: Label {
+ id: labelDelegate
+ text: displayValue
+ font.pixelSize: Qt.application.font.pixelSize * (is24HourValue ? 0.85 : 1)
+ rotation: -rotationTransform.angle
+ opacity: contentContainer.labelOpacity
+ anchors.centerIn: parent
+
+ // TODO: remove me - QTBUG-122679
+ Component.onCompleted: print("created", labelDelegate, "at index", index)
+ Component.onDestruction: print("destroyed", labelDelegate, "at index", index)
+
+ required property int index
+ // From 0 to 60.
+ readonly property int value: (index * 5) % root.__to
+ property int displayValue: root.__effectiveMode === TimePicker.Mode.Hours
+ ? index === 0
+ ? 12
+ : index === 12
+ ? 0
+ : index
+ : value
+ // The picker's current value can equal ours but we still might not be current -
+ // it depends on whether it's a 24 hour value or not.
+ readonly property bool current: root.__value === value && root.__is24HourValueSelected == is24HourValue
+ readonly property bool is24HourValue: index >= 12
+
+ Material.foreground: current
+ // When the selection arm is over us, invert our color so it's legible.
+ ? Material.color(Material.Indigo, Material.Shade100)
+ : root.Material.theme === Material.Light
+ ? is24HourValue ? "#686868" : "#484848"
+ : Material.color(Material.Indigo, is24HourValue ? Material.Shade300 : Material.Shade100)
+
+ transform: [
+ Translate {
+ // We're already centered in our parent, so we can use this function
+ // to determine our position, which doesn't need to be aware of our height -
+ // it just needs to tell us where our center position should be.
+ y: -contentContainer.distanceFromCenterForLabels(labelDelegate.is24HourValue)
+ },
+ Rotation {
+ id: rotationTransform
+ angle: root.__angleForValue(labelDelegate.value)
+ origin.x: labelDelegate.width / 2
+ origin.y: labelDelegate.height / 2
+ }
+ ]
+ }
+ }
+ }
+}
+//! [file]
diff --git a/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePickerDialog.qml b/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePickerDialog.qml
new file mode 100644
index 0000000000..fa02234eb8
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePickerDialog.qml
@@ -0,0 +1,88 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+//! [file]
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls.Material
+
+Dialog {
+ id: root
+ standardButtons: Dialog.Ok | Dialog.Cancel
+ closePolicy: Dialog.NoAutoClose
+ // We don't want so much space between the picker and dialog buttons.
+ bottomPadding: 8
+
+ property int hours: 12
+ property int minutes: 0
+ property alias is24Hour: timePicker.is24Hour
+
+ property int __initialHours
+ property int __initialMinutes
+
+ signal timeAccepted
+ signal timeRejected
+
+ function openWithMode(mode) {
+ timePicker.openWith(mode !== undefined ? mode : TimePicker.Mode.Hours, hours, minutes)
+
+ __initialHours = hours
+ __initialMinutes = minutes
+
+ open()
+ }
+
+ onAccepted: {
+ root.hours = timePicker.hours
+ root.minutes = timePicker.minutes
+ root.timeAccepted()
+ }
+ onRejected: {
+ hours = __initialHours
+ minutes = __initialMinutes
+ // Also reset the picker's time so that the onIs24HourChanged handler below works as expected.
+ timePicker.hours = __initialHours
+ timePicker.minutes = __initialMinutes
+ root.timeRejected()
+ }
+
+ // If is24Hour changes programmatically (only while we're not open),
+ // make sure we adapt to any possible clamping it did in the transition from 24 hours to 12.
+ onIs24HourChanged: {
+ if (!opened)
+ root.hours = timePicker.hours
+ }
+
+ ColumnLayout {
+ anchors.fill: parent
+ spacing: 12
+
+ TimePickerLabel {
+ id: timeLabel
+ // Use TimePicker's time, because that is updated live, whereas our values
+ // are only changed once we've been accepted.
+ time: new Date(1970, 1, 1, timePicker.hours, timePicker.minutes)
+ hoursActive: timePicker.mode === TimePicker.Mode.Hours
+ showAmPm: !timePicker.is24Hour
+
+ Layout.fillWidth: true
+ // Push us down a bit so we're not so close to the top of the dialog.
+ Layout.topMargin: 8
+
+ onHoursSelected: timePicker.mode = TimePicker.Mode.Hours
+ onMinutesSelected: timePicker.mode = TimePicker.Mode.Minutes
+ }
+
+ TimePicker {
+ id: timePicker
+ objectName: "timePicker"
+ // Our TapHandler may handle the click event on the Label if we don't do this,
+ // causing an hour to be inadvertently selected.
+ interactive: root.opened
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+ }
+}
+//! [file]
diff --git a/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePickerLabel.qml b/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePickerLabel.qml
new file mode 100644
index 0000000000..66b651c0c5
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePickerLabel.qml
@@ -0,0 +1,126 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+//! [file]
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls.Material
+
+Item {
+ id: root
+ // Use TextMetrics' boundingRect.width rather than a RowLayout's implicitWidth
+ // because the latter can cause TimePickerDialog to jump around when the label text changes.
+ implicitWidth: fullTextMetrics.boundingRect.width + amPmLayout.implicitWidth + 80
+ implicitHeight: fullTextMetrics.boundingRect.height
+
+ property var time
+ property bool am: true
+ property bool showAmPm: true
+
+ property bool hoursActive: true
+
+ property int fontPixelSize: Qt.application.font.pixelSize * 4
+
+ signal hoursSelected
+ signal minutesSelected
+ signal amSelected
+ signal pmSelected
+
+ TextMetrics {
+ id: fullTextMetrics
+ font: hoursLabel.font
+ text: "99:99"
+ }
+
+ TextMetrics {
+ id: hourTextMetrics
+ font.family: hoursLabel.font.family
+ font.pixelSize: hoursLabel.fontInfo.pixelSize
+ text: "99"
+ }
+
+ TimeComponentLabel {
+ id: hoursLabel
+ objectName: "hoursLabel"
+ text: Qt.formatTime(root.time, "hh")
+ font.pixelSize: root.fontPixelSize
+ // Avoid any jumping around by using a dedicated TextMetrics object
+ // for our label too, and position ourselves based on its width.
+ x: colonLabel.x - hourTextMetrics.boundingRect.width - 4
+ anchors.verticalCenter: parent.verticalCenter
+ dim: !root.hoursActive
+
+ onTapped: root.hoursSelected()
+ }
+
+ TimeComponentLabel {
+ id: colonLabel
+ text: ":"
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ font.pixelSize: root.fontPixelSize
+ dim: true
+ }
+
+ TimeComponentLabel {
+ id: minutesLabel
+ objectName: "minutesLabel"
+ text: Qt.formatTime(root.time, "mm")
+ font.pixelSize: root.fontPixelSize
+ anchors.left: colonLabel.right
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ dim: root.hoursActive
+
+ onTapped: root.minutesSelected()
+ }
+
+ ColumnLayout {
+ id: amPmLayout
+ visible: root.showAmPm
+ // We also need to avoid the AM/PM label jumping around,
+ // so rather than anchor it to the right of the minutes label,
+ // we use colonLabel's horizontal center (which never changes), and fullTextMetrics.
+ anchors.left: colonLabel.horizontalCenter
+ anchors.leftMargin: fullTextMetrics.boundingRect.width / 2 + 12
+ anchors.verticalCenter: minutesLabel.verticalCenter
+
+ spacing: 0
+
+ ToolButton {
+ objectName: "amButton"
+ text: qsTr("AM")
+ autoExclusive: true
+
+ Material.foreground: Material.color(Material.Indigo,
+ root.am ? Material.Shade500 : Material.Shade100)
+
+ // Set the size explicitly to ensure that the buttons aren't too large.
+ // We also add 1 to the width because we want square ripple effects, not round.
+ Layout.preferredWidth: (implicitWidth * 0.7) + 1
+ Layout.preferredHeight: (implicitHeight * 0.7)
+
+ onClicked: {
+ root.am = true
+ root.amSelected()
+ }
+ }
+ ToolButton {
+ objectName: "pmButton"
+ text: qsTr("PM")
+ autoExclusive: true
+
+ Material.foreground: Material.color(Material.Indigo,
+ !root.am ? Material.Shade500 : Material.Shade100)
+
+ Layout.preferredWidth: (implicitWidth * 0.7) + 1
+ Layout.preferredHeight: (implicitHeight * 0.7)
+
+ onClicked: {
+ root.am = false
+ root.pmSelected()
+ }
+ }
+ }
+}
+//! [file]
diff --git a/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePickerMain.qml b/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePickerMain.qml
new file mode 100644
index 0000000000..c7c304613d
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-qml/time-picker/TimePickerMain.qml
@@ -0,0 +1,59 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+//! [file]
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls.Material
+
+ApplicationWindow {
+ id: window
+ width: 600
+ height: 600
+ visible: true
+ title: qsTr("Time Picker Example")
+
+ Material.theme: darkThemeSwitch.checked ? Material.Dark : Material.Light
+
+ // Shows the selected time and opens the dialog.
+ TimeComponentLabel {
+ id: openDialogLabel
+ width: parent.width - 80
+ anchors.centerIn: parent
+ font.pixelSize: Qt.application.font.pixelSize * 8
+ renderTypeQuality: Text.VeryHighRenderTypeQuality
+ interactive: !timePickerDialog.opened
+
+ text: Qt.formatTime(new Date(1970, 1, 1, timePickerDialog.hours, timePickerDialog.minutes), "hh:mm")
+
+ onTapped: timePickerDialog.openWithMode(TimePicker.Mode.Hours)
+ }
+
+ ColumnLayout {
+ // We always want the openDialogLabel to be centered in the window, not us.
+ // For that reason, we use anchors rather than putting the root items into a ColumnLayout.
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: openDialogLabel.bottom
+ anchors.topMargin: 24
+ spacing: 12
+
+ Switch {
+ id: is24HourSwitch
+ text: qsTr("24 Hour")
+ checked: timePickerDialog.is24Hour
+ }
+ Switch {
+ id: darkThemeSwitch
+ text: qsTr("Dark")
+ }
+ }
+
+ TimePickerDialog {
+ id: timePickerDialog
+ anchors.centerIn: parent
+ is24Hour: is24HourSwitch.checked
+
+ onTimeAccepted: print("A time was chosen - do something here!")
+ }
+}
+//! [file]
diff --git a/tests/auto/quick/doc/how-tos/how-to-qml/tst_how-to-qml.cpp b/tests/auto/quick/doc/how-tos/how-to-qml/tst_how-to-qml.cpp
new file mode 100644
index 0000000000..9b750a59ef
--- /dev/null
+++ b/tests/auto/quick/doc/how-tos/how-to-qml/tst_how-to-qml.cpp
@@ -0,0 +1,369 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtCore/qregularexpression.h>
+#include <QtTest/QtTest>
+#include <QtQml/qqmlapplicationengine.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickwindow.h>
+#include <QtQuick/private/qquickrepeater_p.h>
+#include <QtQuickTemplates2/private/qquickdialog_p.h>
+#include <QtQuickTemplates2/private/qquickdialogbuttonbox_p.h>
+#include <QtQuickTemplates2/private/qquicklabel_p.h>
+#include <QtQuickTemplates2/private/qquicktextfield_p.h>
+#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
+#include <QtQuickControlsTestUtils/private/dialogstestutils_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QQuickVisualTestUtils;
+using namespace QQuickControlsTestUtils;
+using namespace QQuickDialogTestUtils;
+
+// Allows us to use test macros outside of test functions.
+#define RETURN_IF_FAILED(expression) \
+expression; \
+if (QTest::currentTestFailed()) \
+ return
+
+class tst_HowToQml : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_HowToQml();
+
+private slots:
+ void init();
+ void activeFocusDebugging();
+ void timePicker();
+
+private:
+ QScopedPointer<QPointingDevice> touchScreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
+};
+
+tst_HowToQml::tst_HowToQml()
+{
+ qputenv("QML_NO_TOUCH_COMPRESSION", "1");
+}
+
+void tst_HowToQml::init()
+{
+// QTest::failOnWarning(QRegularExpression(QStringLiteral(".?")));
+}
+
+void tst_HowToQml::activeFocusDebugging()
+{
+ QQmlApplicationEngine engine;
+ engine.loadFromModule("HowToQml", "ActiveFocusDebuggingMain");
+ QCOMPARE(engine.rootObjects().size(), 1);
+
+ auto *window = qobject_cast<QQuickWindow*>(engine.rootObjects().at(0));
+ window->show();
+ window->requestActivate();
+ QTest::ignoreMessage(QtDebugMsg, QRegularExpression("activeFocusItem: .*\"ActiveFocusDebuggingMain\""));
+ QVERIFY(QTest::qWaitForWindowActive(window));
+
+ QTest::ignoreMessage(QtDebugMsg, QRegularExpression("activeFocusItem: .*\"textField1\""));
+ auto *textField1 = window->findChild<QQuickTextField*>("textField1");
+ QVERIFY(textField1);
+ textField1->forceActiveFocus();
+ QVERIFY(textField1->hasActiveFocus());
+
+ QTest::ignoreMessage(QtDebugMsg, QRegularExpression("activeFocusItem: .*\"textField2\""));
+ auto *textField2 = window->findChild<QQuickTextField*>("textField2");
+ QVERIFY(textField2);
+ QTest::keyClick(window, Qt::Key_Tab);
+ QVERIFY(textField2->hasActiveFocus());
+}
+
+void tst_HowToQml::timePicker()
+{
+ QQmlApplicationEngine engine;
+ engine.loadFromModule("HowToQml", "TimePickerMain");
+ QCOMPARE(engine.rootObjects().size(), 1);
+
+ auto *window = qobject_cast<QQuickWindow*>(engine.rootObjects().at(0));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *dialog = window->findChild<QQuickDialog *>();
+ QVERIFY(dialog);
+
+ auto *timePicker = dialog->findChild<QQuickItem *>("timePicker");
+ QVERIFY(timePicker);
+
+ auto *contentContainer = timePicker->findChild<QQuickItem *>("contentContainer");
+ QVERIFY(contentContainer);
+ const int contentRadius = contentContainer->property("radius").toReal();
+
+ auto *labelRepeater = timePicker->findChild<QQuickRepeater *>();
+ QVERIFY(labelRepeater);
+
+ auto *selectionArm = timePicker->findChild<QQuickItem *>("selectionArm");
+ QVERIFY(selectionArm);
+
+ auto *selectionIndicator = selectionArm->findChild<QQuickItem *>("selectionIndicator");
+ QVERIFY(selectionIndicator);
+ const int selectionIndicatorHeight = selectionIndicator->height();
+
+ auto angleForValue = [](int value) -> int {
+ return int((value / 60.0) * 360) % 360;
+ };
+
+ // Note that is24HourValue should be true if "value" is a 24-hour value,
+ // not if the picker's is24Hour property is true.
+ auto labelCenterPosForValue = [&](int value, bool is24HourValue = false) -> QPoint {
+ if (value < 0 || value > 60)
+ return {};
+
+ const qreal angle = angleForValue(value);
+
+ QTransform transform;
+ // Translate to the center.
+ transform.translate(contentRadius, contentRadius);
+ // Rotate to the correct angle.
+ transform.rotate(angle);
+ // Go outward.
+ const int labelDistance = is24HourValue ? selectionIndicatorHeight * 1.5 : selectionIndicatorHeight * 0.5;
+ transform.translate(0, -contentRadius + labelDistance);
+
+ const auto centerPos = transform.map(QPoint(0, 0));
+ return centerPos;
+ };
+
+ enum Mode {
+ Hours,
+ Minutes
+ };
+
+ const int valuesPerLabelStep = 5;
+ const bool TwelveHour = false;
+ const bool TwentyFourHour = true;
+
+ // Checks that all the labels are in their expected positions and that they have the correct text.
+ auto verifyLabels = [&](Mode expectedMode, bool is24Hour, int callerLineNumber) {
+ // When not in 24 hour mode, there are always 12 labels, regardless of whether it's showing hours or minutes.
+ const int expectedLabelCount = expectedMode == Hours && is24Hour ? 24 : 12;
+ QCOMPARE(labelRepeater->count(), expectedLabelCount);
+ for (int i = 0; i < expectedLabelCount; ++i) {
+ auto *labelDelegate = labelRepeater->itemAt(i);
+ QVERIFY2(labelDelegate, qPrintable(QString::fromLatin1("Expected valid label delegate item at index %1 (caller line %2)")
+ .arg(i).arg(callerLineNumber)));
+ // Use the waiting variant of the macro because there are opacity animations.
+ // TODO: is this causing the failure on line 224?
+ QTRY_VERIFY2(qFuzzyCompare(labelDelegate->opacity(), 1.0), qPrintable(QString::fromLatin1(
+ "Expected opacity of label delegate %1 at index %2 to be 1 but it's %3 (caller line %4) - QTBUG-118056: actual label delegate at this index is now %5")
+ .arg(QDebug::toString(labelDelegate)).arg(i).arg(labelDelegate->opacity()).arg(callerLineNumber).arg(QDebug::toString(labelRepeater->itemAt(i)))));
+
+ const int expectedValue = (i * valuesPerLabelStep) % 60;
+ const int actualValue = labelDelegate->property("value").toInt();
+ QVERIFY2(expectedValue == actualValue, qPrintable(QString::fromLatin1(
+ "Expected label's value at index %1 to be %2 but it's %3 (caller line %4)")
+ .arg(i).arg(expectedValue).arg(actualValue).arg(callerLineNumber)));
+
+ const QString expectedText = QString::number(expectedMode == Hours
+ ? (i == 0 ? 12 : (i == 12 ? 0 : i)) : i * valuesPerLabelStep);
+ // Use QTRY_VERIFY2 rather than QVERIFY2, because text changes are animated.
+ QTRY_VERIFY2(expectedText == labelDelegate->property("text").toString(), qPrintable(QString::fromLatin1(
+ "Expected label's text at index %1 to be %2 but it's %3 (caller line %4)").arg(i)
+ .arg(expectedText, labelDelegate->property("text").toString(), QString::number(callerLineNumber))));
+ }
+ };
+
+ auto verifySelectionIndicator = [&](int expectedValue, bool expect24HourValue, int callerLineNumber) {
+ const qreal actualRotation = int(selectionArm->rotation()) % 360;
+ const qreal expectedRotation = angleForValue(expectedValue);
+ QVERIFY2(qFuzzyCompare(actualRotation, expectedRotation), qPrintable(QString::fromLatin1(
+ "Expected selection arm's rotation to be %1 for expectedValue %2 but it's %3 (caller line %4)")
+ .arg(expectedRotation).arg(expectedValue).arg(actualRotation).arg(callerLineNumber)));
+
+ const QPoint expectedIndicatorCenterPos = labelCenterPosForValue(expectedValue, expect24HourValue);
+ const QPoint actualIndicatorCenterPos = selectionIndicator->mapToItem(
+ contentContainer, selectionIndicator->boundingRect().center().toPoint()).toPoint();
+ const QPoint difference = actualIndicatorCenterPos - expectedIndicatorCenterPos;
+ QVERIFY2(difference.x() <= 2 && difference.y() <= 2, qPrintable(QString::fromLatin1(
+ "Expected selection indicator's center position to be %1 (with 2 pixels of tolerance) but it's %2 (caller line %3)")
+ .arg(QDebug::toString(expectedIndicatorCenterPos), QDebug::toString(actualIndicatorCenterPos)).arg(callerLineNumber)));
+ };
+
+ auto valueForHour = [&](int hour) {
+ return (hour * valuesPerLabelStep) % 60;
+ };
+
+ // Open the picker to hours mode by clicking on the label.
+ auto *openDialogLabel = window->findChild<QQuickLabel *>(QString(), Qt::FindDirectChildrenOnly);
+ QVERIFY(openDialogLabel);
+ QCOMPARE(openDialogLabel->text(), "12:00");
+ QTest::touchEvent(window, touchScreen.data()).press(0, mapCenterToWindow(openDialogLabel));
+ QTest::touchEvent(window, touchScreen.data()).release(0, mapCenterToWindow(openDialogLabel));
+ QTRY_COMPARE(dialog->property("opened").toBool(), true);
+ // It should show hours.
+ RETURN_IF_FAILED(verifyLabels(Hours, TwelveHour, __LINE__));
+ RETURN_IF_FAILED(verifySelectionIndicator(0, TwelveHour, __LINE__));
+
+ // Select the 3rd hour.
+ const QPoint thirdHourPos = labelCenterPosForValue(valueForHour(3));
+ QTest::touchEvent(window, touchScreen.data()).press(0, mapToWindow(contentContainer, thirdHourPos));
+ RETURN_IF_FAILED(verifySelectionIndicator(valueForHour(3), TwelveHour, __LINE__));
+ QCOMPARE(timePicker->property("mode").toInt(), Hours);
+ QTest::touchEvent(window, touchScreen.data()).release(0, mapToWindow(contentContainer, thirdHourPos));
+ QCOMPARE(timePicker->property("hours").toInt(), 3);
+ QCOMPARE(timePicker->property("minutes").toInt(), 0);
+ // The dialog's values shouldn't change until the dialog has been accepted.
+ QCOMPARE(dialog->property("hours").toInt(), 12);
+ QCOMPARE(dialog->property("minutes").toInt(), 0);
+ // It should be showing minutes now.
+ QCOMPARE(timePicker->property("mode").toInt(), Minutes);
+ RETURN_IF_FAILED(verifyLabels(Minutes, TwelveHour, __LINE__));
+ RETURN_IF_FAILED(verifySelectionIndicator(0, TwelveHour, __LINE__));
+ auto *minutesLabel = dialog->findChild<QQuickLabel *>("minutesLabel");
+ QVERIFY(minutesLabel);
+ QCOMPARE(minutesLabel->property("dim").toBool(), false);
+
+ // Select the 59th minute.
+ const QPoint fiftyNinthMinutePos = labelCenterPosForValue(59);
+ QTest::touchEvent(window, touchScreen.data()).press(0, mapToWindow(contentContainer, fiftyNinthMinutePos));
+ RETURN_IF_FAILED(verifySelectionIndicator(59, TwelveHour, __LINE__));
+ QTest::touchEvent(window, touchScreen.data()).release(0, mapToWindow(contentContainer, fiftyNinthMinutePos));
+ QCOMPARE(timePicker->property("hours").toInt(), 3);
+ QCOMPARE(timePicker->property("minutes").toInt(), 59);
+ QCOMPARE(dialog->property("hours").toInt(), 12);
+ QCOMPARE(dialog->property("minutes").toInt(), 0);
+ // It shouldn't be closed until the OK or Cancel buttons are clicked.
+ QCOMPARE(dialog->property("opened").toBool(), true);
+
+ // Accept the dialog to make the changes.
+ auto *dialogButtonBox = qobject_cast<QQuickDialogButtonBox *>(dialog->footer());
+ QVERIFY(dialogButtonBox);
+ auto *okButton = findDialogButton(dialogButtonBox, "OK");
+ QTest::ignoreMessage(QtDebugMsg, "A time was chosen - do something here!");
+ QVERIFY(clickButton(okButton));
+ QTRY_COMPARE(dialog->property("visible").toBool(), false);
+ QCOMPARE(dialog->property("hours").toInt(), 3);
+ QCOMPARE(dialog->property("minutes").toInt(), 59);
+ QCOMPARE(openDialogLabel->text(), "03:59");
+
+ // Open it again.
+ QTest::touchEvent(window, touchScreen.data()).press(0, mapCenterToWindow(openDialogLabel));
+ QTest::touchEvent(window, touchScreen.data()).release(0, mapCenterToWindow(openDialogLabel));
+ QTRY_COMPARE(dialog->property("opened"), true);
+ RETURN_IF_FAILED(verifyLabels(Hours, TwelveHour, __LINE__));
+ RETURN_IF_FAILED(verifySelectionIndicator(valueForHour(3), TwelveHour, __LINE__));
+ // The time label should be unchanged.
+ QCOMPARE(openDialogLabel->text(), "03:59");
+
+ // Switch from hours to minutes by clicking on the minutes label.
+ QTest::touchEvent(window, touchScreen.data()).press(0, mapCenterToWindow(minutesLabel));
+ QTest::touchEvent(window, touchScreen.data()).release(0, mapCenterToWindow(minutesLabel));
+ RETURN_IF_FAILED(verifyLabels(Minutes, TwelveHour, __LINE__));
+ RETURN_IF_FAILED(verifySelectionIndicator(59, TwelveHour, __LINE__));
+
+ // Select the 1st minute.
+ const QPoint firstMinutePos = labelCenterPosForValue(1);
+ QTest::touchEvent(window, touchScreen.data()).press(0, mapToWindow(contentContainer, firstMinutePos));
+ RETURN_IF_FAILED(verifySelectionIndicator(1, TwelveHour, __LINE__));
+ QTest::touchEvent(window, touchScreen.data()).release(0, mapToWindow(contentContainer, firstMinutePos));
+ QCOMPARE(timePicker->property("hours").toInt(), 3);
+ QCOMPARE(timePicker->property("minutes").toInt(), 1);
+ // It shouldn't be closed until the OK or Cancel buttons are clicked.
+ QCOMPARE(dialog->property("opened").toBool(), true);
+
+ // Accept the dialog to make the changes.
+ QTest::ignoreMessage(QtDebugMsg, "A time was chosen - do something here!");
+ QVERIFY(clickButton(okButton));
+ QTRY_COMPARE(dialog->property("visible").toBool(), false);
+ QCOMPARE(dialog->property("hours").toInt(), 3);
+ QCOMPARE(dialog->property("minutes").toInt(), 1);
+ QCOMPARE(openDialogLabel->text(), "03:01");
+
+ // Check that hours and minutes set programmatically on the picker and dialog are respected.
+ QVERIFY(dialog->setProperty("hours", QVariant::fromValue(7)));
+ QVERIFY(dialog->setProperty("minutes", QVariant::fromValue(8)));
+ QCOMPARE(openDialogLabel->text(), "07:08");
+ // Open the picker to hours mode by clicking on the label.
+ QTest::touchEvent(window, touchScreen.data()).press(0, mapCenterToWindow(openDialogLabel));
+ QTest::touchEvent(window, touchScreen.data()).release(0, mapCenterToWindow(openDialogLabel));
+ QTRY_COMPARE(dialog->property("opened").toBool(), true);
+ RETURN_IF_FAILED(verifyLabels(Hours, TwelveHour, __LINE__));
+ RETURN_IF_FAILED(verifySelectionIndicator(valueForHour(7), TwelveHour, __LINE__));
+ QCOMPARE(timePicker->property("hours").toInt(), 7);
+ QCOMPARE(timePicker->property("minutes").toInt(), 8);
+
+ // Check that cancelling the dialog cancels any changes.
+ // Select the fourth hour.
+ const QPoint fourthHourPos = labelCenterPosForValue(20);
+ QTest::touchEvent(window, touchScreen.data()).press(0, mapToWindow(contentContainer, fourthHourPos));
+ RETURN_IF_FAILED(verifySelectionIndicator(valueForHour(4), TwelveHour, __LINE__));
+ QTest::touchEvent(window, touchScreen.data()).release(0, mapToWindow(contentContainer, fourthHourPos));
+ QCOMPARE(timePicker->property("hours").toInt(), 4);
+ QCOMPARE(timePicker->property("minutes").toInt(), 8);
+ auto *cancelButton = findDialogButton(dialogButtonBox, "Cancel");
+ QVERIFY(clickButton(cancelButton));
+ QTRY_COMPARE(dialog->property("visible").toBool(), false);
+ QCOMPARE(dialog->property("hours").toInt(), 7);
+ QCOMPARE(dialog->property("minutes").toInt(), 8);
+
+ // Test that the 24 hour mode works.
+ const bool isCi = qgetenv("QTEST_ENVIRONMENT") == "ci"; // QTBUG-122679
+ if (isCi)
+ qDebug() << "about to set is24hour to true";
+ QVERIFY(dialog->setProperty("is24Hour", QVariant::fromValue(true)));
+ if (isCi)
+ qDebug() << "about to open picker";
+ QTest::touchEvent(window, touchScreen.data()).press(0, mapCenterToWindow(openDialogLabel));
+ QTest::touchEvent(window, touchScreen.data()).release(0, mapCenterToWindow(openDialogLabel));
+ QTRY_COMPARE(dialog->property("opened").toBool(), true);
+ QCOMPARE(timePicker->property("mode").toInt(), Hours);
+ if (isCi)
+ qDebug() << "about to verify labels after switching to 24hr";
+ RETURN_IF_FAILED(verifyLabels(Hours, TwentyFourHour, __LINE__));
+ // TwelveHour because the selected value (7) is on the 12 hour "ring".
+ RETURN_IF_FAILED(verifySelectionIndicator(valueForHour(7), TwelveHour, __LINE__));
+ // It should still show the old time.
+ QCOMPARE(timePicker->property("hours").toInt(), 7);
+ QCOMPARE(timePicker->property("minutes").toInt(), 8);
+ QCOMPARE(dialog->property("hours").toInt(), 7);
+ QCOMPARE(dialog->property("minutes").toInt(), 8);
+
+ // Select the 23rd hour.
+ const QPoint twentyThirdHourPos = labelCenterPosForValue(valueForHour(11), TwentyFourHour);
+ QTest::touchEvent(window, touchScreen.data()).press(0, mapToWindow(contentContainer, twentyThirdHourPos));
+ RETURN_IF_FAILED(verifySelectionIndicator(valueForHour(23), TwentyFourHour, __LINE__));
+ QTest::touchEvent(window, touchScreen.data()).release(0, mapToWindow(contentContainer, twentyThirdHourPos));
+ QCOMPARE(timePicker->property("hours").toInt(), 23);
+ QCOMPARE(timePicker->property("minutes").toInt(), 8);
+ QCOMPARE(dialog->property("hours").toInt(), 7);
+ QCOMPARE(dialog->property("minutes").toInt(), 8);
+ RETURN_IF_FAILED(verifyLabels(Minutes, TwentyFourHour, __LINE__));
+ RETURN_IF_FAILED(verifySelectionIndicator(8, TwelveHour, __LINE__));
+
+ // Select the 20th minute.
+ const QPoint twentiethMinutePos = labelCenterPosForValue(20);
+ QTest::touchEvent(window, touchScreen.data()).press(0, mapToWindow(contentContainer, twentiethMinutePos));
+ RETURN_IF_FAILED(verifySelectionIndicator(20, TwelveHour, __LINE__));
+ QTest::touchEvent(window, touchScreen.data()).release(0, mapToWindow(contentContainer, twentiethMinutePos));
+ QCOMPARE(timePicker->property("hours").toInt(), 23);
+ QCOMPARE(timePicker->property("minutes").toInt(), 20);
+
+ // Go back to hours and make sure that the selection indicator is correct.
+ auto *hoursLabel = dialog->findChild<QQuickLabel *>("hoursLabel");
+ QVERIFY(hoursLabel);
+ QTest::touchEvent(window, touchScreen.data()).press(0, mapCenterToWindow(hoursLabel));
+ QTest::touchEvent(window, touchScreen.data()).release(0, mapCenterToWindow(hoursLabel));
+ RETURN_IF_FAILED(verifyLabels(Hours, TwentyFourHour, __LINE__));
+ RETURN_IF_FAILED(verifySelectionIndicator(valueForHour(23), TwentyFourHour, __LINE__));
+
+ // Accept.
+ QTest::ignoreMessage(QtDebugMsg, "A time was chosen - do something here!");
+ QVERIFY(clickButton(okButton));
+ QTRY_COMPARE(dialog->property("visible").toBool(), false);
+ QCOMPARE(dialog->property("hours").toInt(), 23);
+ QCOMPARE(dialog->property("minutes").toInt(), 20);
+}
+
+QT_END_NAMESPACE
+
+QTEST_MAIN(tst_HowToQml)
+
+#include "tst_how-to-qml.moc"
diff --git a/tests/auto/quick/drawingmodes/CMakeLists.txt b/tests/auto/quick/drawingmodes/CMakeLists.txt
index 1d680c7531..09f53f1037 100644
--- a/tests/auto/quick/drawingmodes/CMakeLists.txt
+++ b/tests/auto/quick/drawingmodes/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_drawingmodes Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_drawingmodes LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp b/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp
index 9cf3601a06..a68be8a745 100644
--- a/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp
+++ b/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
@@ -133,7 +133,7 @@ void tst_drawingmodes::points()
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
-#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
+#if QT_CONFIG(metal)
QSKIP("Skipping points test due to unexpected failures in M1 CI VM");
#endif
diff --git a/tests/auto/quick/examples/CMakeLists.txt b/tests/auto/quick/examples/CMakeLists.txt
index 4646fb82ca..74fe0fba51 100644
--- a/tests/auto/quick/examples/CMakeLists.txt
+++ b/tests/auto/quick/examples/CMakeLists.txt
@@ -1,5 +1,5 @@
# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
# Generated from examples.pro.
@@ -7,6 +7,12 @@
## tst_examples Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_quick_examples LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_quick_examples
SOURCES
tst_examples.cpp
diff --git a/tests/auto/quick/examples/tst_examples.cpp b/tests/auto/quick/examples/tst_examples.cpp
index de27fe92cb..4962f6b759 100644
--- a/tests/auto/quick/examples/tst_examples.cpp
+++ b/tests/auto/quick/examples/tst_examples.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QLibraryInfo>
@@ -54,7 +54,6 @@ tst_examples::tst_examples()
// Add directories you want excluded here
excludedDirs << "shared"; //Not an example
excludedDirs << "snippets/qml/path"; //No root QQuickItem
- excludedDirs << "examples/qml/qmlextensionplugins"; //Requires special import search path
// These snippets are not expected to run on their own.
excludedDirs << "snippets/qml/visualdatamodel_rootindex";
@@ -69,11 +68,9 @@ tst_examples::tst_examples()
#if !QT_CONFIG(opengl)
//No support for Particles
- excludedFiles << "examples/qml/dynamicscene/dynamicscene.qml";
excludedFiles << "examples/quick/animation/basics/color-animation.qml";
excludedFiles << "examples/quick/particles/affectors/content/age.qml";
- excludedFiles << "examples/quick/touchinteraction/multipointtouch/bearwhack.qml";
- excludedFiles << "examples/quick/touchinteraction/multipointtouch/multiflame.qml";
+ excludedFiles << "examples/quick/pointerhandlers/multiflame.qml";
excludedDirs << "examples/quick/particles";
// No Support for ShaderEffect
excludedFiles << "src/quick/doc/snippets/qml/animators.qml";
@@ -109,21 +106,19 @@ void tst_examples::namingConvention(const QDir &d)
return;
}
- QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
- QDir::Files);
+ const QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"), QDir::Files);
bool seenQml = !files.isEmpty();
bool seenLowercase = false;
- foreach (const QString &file, files) {
+ for (const QString &file : files) {
if (file.at(0).isLower())
seenLowercase = true;
}
if (!seenQml) {
- QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
- QDir::NoSymLinks);
- foreach (const QString &dir, dirs) {
+ const QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
+ for (const QString &dir : dirs) {
QDir sub = d;
sub.cd(dir);
namingConvention(sub);
@@ -144,11 +139,12 @@ void tst_examples::namingConvention(const QDir &d)
void tst_examples::namingConvention()
{
- QStringList examplesLocations;
- examplesLocations << QLibraryInfo::path(QLibraryInfo::ExamplesPath) + QLatin1String("/qml");
- examplesLocations << QLibraryInfo::path(QLibraryInfo::ExamplesPath) + QLatin1String("/quick");
+ const QStringList examplesLocations = {
+ QLibraryInfo::path(QLibraryInfo::ExamplesPath) + QLatin1String("/qml"),
+ QLibraryInfo::path(QLibraryInfo::ExamplesPath) + QLatin1String("/quick")
+ };
- foreach(const QString &examples, examplesLocations) {
+ for (const QString &examples : examplesLocations) {
QDir d(examples);
if (d.exists())
namingConvention(d);
@@ -167,9 +163,8 @@ QStringList tst_examples::findQmlFiles(const QDir &d)
QStringList cppfiles = d.entryList(QStringList() << QLatin1String("*.cpp"), QDir::Files);
if (cppfiles.isEmpty()) {
- QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
- QDir::Files);
- foreach (const QString &file, files) {
+ const QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"), QDir::Files);
+ for (const QString &file : files) {
if (file.at(0).isLower()) {
bool superContinue = false;
for (int ii = 0; ii < excludedFiles.size(); ++ii) {
@@ -187,9 +182,8 @@ QStringList tst_examples::findQmlFiles(const QDir &d)
}
- QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
- QDir::NoSymLinks);
- foreach (const QString &dir, dirs) {
+ const QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
+ for (const QString &dir : dirs) {
QDir sub = d;
sub.cd(dir);
rv << findQmlFiles(sub);
diff --git a/tests/auto/quick/geometry/CMakeLists.txt b/tests/auto/quick/geometry/CMakeLists.txt
index 5094c48e39..8231608a7f 100644
--- a/tests/auto/quick/geometry/CMakeLists.txt
+++ b/tests/auto/quick/geometry/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_geometry Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_geometry LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_geometry
SOURCES
tst_geometry.cpp
diff --git a/tests/auto/quick/geometry/tst_geometry.cpp b/tests/auto/quick/geometry/tst_geometry.cpp
index 08ef3c34d7..f3034977e5 100644
--- a/tests/auto/quick/geometry/tst_geometry.cpp
+++ b/tests/auto/quick/geometry/tst_geometry.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QString>
#include <QtTest/QtTest>
diff --git a/tests/auto/quick/nodes/CMakeLists.txt b/tests/auto/quick/nodes/CMakeLists.txt
index 85ed32e4dd..415179b79d 100644
--- a/tests/auto/quick/nodes/CMakeLists.txt
+++ b/tests/auto/quick/nodes/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_nodestest Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_nodestest LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_nodestest
SOURCES
tst_nodestest.cpp
diff --git a/tests/auto/quick/nodes/tst_nodestest.cpp b/tests/auto/quick/nodes/tst_nodestest.cpp
index 5cec3034d8..d91654a6f6 100644
--- a/tests/auto/quick/nodes/tst_nodestest.cpp
+++ b/tests/auto/quick/nodes/tst_nodestest.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QString>
#include <QtTest/QtTest>
@@ -18,28 +18,23 @@
#include <QtGui/qpa/qplatformintegration.h>
#include <QtGui/qoffscreensurface.h>
-#include <QtGui/private/qrhi_p.h>
-#include <QtGui/private/qrhinull_p.h>
+#include <rhi/qrhi.h>
#if QT_CONFIG(opengl)
# include <QOpenGLContext>
-# include <QtGui/private/qrhigles2_p.h>
# define TST_GL
#endif
#if QT_CONFIG(vulkan)
# include <QVulkanInstance>
-# include <QtGui/private/qrhivulkan_p.h>
# define TST_VK
#endif
#ifdef Q_OS_WIN
-#include <QtGui/private/qrhid3d11_p.h>
# define TST_D3D11
#endif
-#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
-# include <QtGui/private/qrhimetal_p.h>
+#if QT_CONFIG(metal)
# define TST_MTL
#endif
diff --git a/tests/auto/quick/nokeywords/CMakeLists.txt b/tests/auto/quick/nokeywords/CMakeLists.txt
index 947c1e72de..44e371ab3a 100644
--- a/tests/auto/quick/nokeywords/CMakeLists.txt
+++ b/tests/auto/quick/nokeywords/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_nokeywords Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_nokeywords LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_nokeywords
SOURCES
tst_nokeywords.cpp
diff --git a/tests/auto/quick/nokeywords/tst_nokeywords.cpp b/tests/auto/quick/nokeywords/tst_nokeywords.cpp
index 80350477fd..190c9fac34 100644
--- a/tests/auto/quick/nokeywords/tst_nokeywords.cpp
+++ b/tests/auto/quick/nokeywords/tst_nokeywords.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#define QT_NO_KEYWORDS
#undef signals
diff --git a/tests/auto/quick/platform/CMakeLists.txt b/tests/auto/quick/platform/CMakeLists.txt
new file mode 100644
index 0000000000..6a5f5760fc
--- /dev/null
+++ b/tests/auto/quick/platform/CMakeLists.txt
@@ -0,0 +1,6 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(ANDROID)
+ add_subdirectory(android)
+endif()
diff --git a/tests/auto/quick/platform/android/CMakeLists.txt b/tests/auto/quick/platform/android/CMakeLists.txt
new file mode 100644
index 0000000000..d902be5aac
--- /dev/null
+++ b/tests/auto/quick/platform/android/CMakeLists.txt
@@ -0,0 +1,4 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+add_subdirectory(qtandroiditemmodel)
diff --git a/tests/auto/quick/platform/android/qtandroiditemmodel/CMakeLists.txt b/tests/auto/quick/platform/android/qtandroiditemmodel/CMakeLists.txt
new file mode 100644
index 0000000000..d8cdb763c0
--- /dev/null
+++ b/tests/auto/quick/platform/android/qtandroiditemmodel/CMakeLists.txt
@@ -0,0 +1,25 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## tst_qtandroiditemmodel Test:
+#####################################################################
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qtandroiditemmodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qtandroiditemmodel
+ SOURCES
+ tst_qtandroiditemmodel.cpp
+ LIBRARIES
+ Qt::Gui
+ Qt::Quick
+ Qt::QuickPrivate
+)
+
+set_property(TARGET tst_qtandroiditemmodel APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
+ ${CMAKE_CURRENT_SOURCE_DIR}/testdata
+)
diff --git a/tests/auto/quick/platform/android/qtandroiditemmodel/testdata/src/org/qtproject/qt/android/tests/TestModel.java b/tests/auto/quick/platform/android/qtandroiditemmodel/testdata/src/org/qtproject/qt/android/tests/TestModel.java
new file mode 100644
index 0000000000..6bfb1dbc2f
--- /dev/null
+++ b/tests/auto/quick/platform/android/qtandroiditemmodel/testdata/src/org/qtproject/qt/android/tests/TestModel.java
@@ -0,0 +1,120 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+package org.qtproject.qt.android.tests;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.qtproject.qt.android.QtAbstractItemModel;
+import org.qtproject.qt.android.QtModelIndex;
+
+public class TestModel extends QtAbstractItemModel {
+ int m_rows = 0;
+ int m_cols = 0;
+
+ @Override
+ public int columnCount(QtModelIndex parent) {
+ return parent.isValid() ? 0 : m_cols;
+ }
+
+ @Override
+ public Object data(QtModelIndex index, int role) {
+ int r = index.row();
+ int c = index.column();
+ if (r < 0 || c < 0 || c > m_cols || r > m_rows)
+ return null;
+
+ switch (role) {
+ case 0:
+ return String.format("r%d/c%d", r, c);
+ case 1:
+ return new Boolean(((r + c) % 2) == 0);
+ case 2:
+ return new Integer((c << 8) + r);
+ case 3:
+ return new Double((r + 1.0) / (c + 1.0));
+ case 4:
+ return new Long((c << 8) * (r << 8));
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public QtModelIndex index(int row, int column, QtModelIndex parent) {
+ return hasIndex(row, column, parent) ? createIndex(row, column, 0) : new QtModelIndex();
+ }
+
+ @Override
+ public QtModelIndex parent(QtModelIndex qtModelIndex) {
+ return new QtModelIndex();
+ }
+
+ @Override
+ public int rowCount(QtModelIndex parent) {
+ return parent.isValid() ? 0 : m_rows;
+ }
+
+ @Override
+ public HashMap<Integer,String> roleNames(){
+ final HashMap<Integer,String> roles = new HashMap<Integer,String>();
+ roles.put(0, "stringRole");
+ roles.put(1, "booleanRole");
+ roles.put(2, "integerRole");
+ roles.put(3, "doubleRole");
+ roles.put(4, "longRole");
+ return roles;
+ }
+
+ @Override public boolean canFetchMore(QtModelIndex parent)
+ {
+ return !parent.isValid() && (m_rows < 30);
+ }
+
+ @Override public void fetchMore(QtModelIndex parent)
+ {
+ if (!canFetchMore(parent))
+ return;
+ int toAdd = Math.min(10, 30 - rowCount(parent));
+ beginInsertRows(new QtModelIndex(), m_rows, m_rows + toAdd - 1);
+ m_rows += toAdd;
+ endInsertRows();
+ }
+
+ public void addRow() {
+ beginInsertRows(new QtModelIndex(), m_rows, m_rows);
+ m_rows++;
+ endInsertRows();
+ }
+
+ public void removeRow() {
+ if (m_rows == 0)
+ return;
+ beginRemoveRows(new QtModelIndex(), 0, 0);
+ m_rows--;
+ endRemoveRows();
+ }
+
+ public void addCol() {
+ beginInsertColumns(new QtModelIndex(), m_cols, m_cols);
+ m_cols++;
+ endInsertColumns();
+ }
+
+ public void removeCol() {
+ if (m_cols == 0)
+ return;
+ beginRemoveColumns(new QtModelIndex(), 0, 0);
+ m_cols--;
+ endRemoveColumns();
+ }
+
+ public void reset() {
+ beginResetModel();
+ m_rows = 0;
+ m_cols = 0;
+ endResetModel();
+ }
+}
diff --git a/tests/auto/quick/platform/android/qtandroiditemmodel/tst_qtandroiditemmodel.cpp b/tests/auto/quick/platform/android/qtandroiditemmodel/tst_qtandroiditemmodel.cpp
new file mode 100644
index 0000000000..ae1971df01
--- /dev/null
+++ b/tests/auto/quick/platform/android/qtandroiditemmodel/tst_qtandroiditemmodel.cpp
@@ -0,0 +1,182 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtTest/QTest>
+
+#include <QtQuick/private/qandroiditemmodelproxy_p.h>
+#include <QtQuick/private/qandroidmodelindexproxy_p.h>
+#include <QtQuick/private/qandroidtypes_p.h>
+
+#include <QGuiApplication>
+#include <QtCore/qabstractitemmodel.h>
+#include <QtCore/qjniobject.h>
+#include <QtCore/qjnitypes.h>
+#include <QtCore/qstring.h>
+
+using namespace Qt::Literals;
+
+Q_DECLARE_JNI_CLASS(JTestModel, "org/qtproject/qt/android/tests/TestModel")
+
+class tst_QtAndroidItemModel : public QObject
+{
+ Q_OBJECT
+ JTestModel jModel;
+ QAbstractItemModel *qProxy;
+ void resetModel();
+
+private slots:
+ void initTestCase();
+ void cleanup();
+ void addRow();
+ void addColumn();
+ void removeRow();
+ void removeColumn();
+ void roleNames();
+ void fetchMore();
+ void hasIndex();
+ void data();
+};
+
+void tst_QtAndroidItemModel::initTestCase()
+{
+ QVERIFY(jModel.isValid());
+ qProxy = QAndroidItemModelProxy::createNativeProxy(jModel);
+ QVERIFY(qProxy);
+}
+
+void tst_QtAndroidItemModel::cleanup()
+{
+ resetModel();
+}
+
+void tst_QtAndroidItemModel::addRow()
+{
+ const int rowsBefore = qProxy->rowCount();
+ jModel.callMethod<void>("addRow");
+ QCOMPARE_EQ(qProxy->rowCount(), rowsBefore + 1);
+}
+
+void tst_QtAndroidItemModel::addColumn()
+{
+ const int columnsBefore = qProxy->columnCount();
+ jModel.callMethod<void>("addCol");
+ QCOMPARE_EQ(qProxy->columnCount(), columnsBefore + 1);
+}
+
+void tst_QtAndroidItemModel::removeRow()
+{
+ jModel.callMethod<void>("addRow");
+ jModel.callMethod<void>("addRow");
+ QCOMPARE_EQ(qProxy->rowCount(), 2);
+ jModel.callMethod<void>("removeRow");
+ QCOMPARE_EQ(qProxy->rowCount(), 1);
+ jModel.callMethod<void>("removeRow");
+ QCOMPARE_EQ(qProxy->rowCount(), 0);
+}
+
+void tst_QtAndroidItemModel::removeColumn()
+{
+ jModel.callMethod<void>("addCol");
+ jModel.callMethod<void>("addCol");
+ QCOMPARE_EQ(qProxy->columnCount(), 2);
+ jModel.callMethod<void>("removeCol");
+ QCOMPARE_EQ(qProxy->columnCount(), 1);
+ jModel.callMethod<void>("removeCol");
+ QCOMPARE_EQ(qProxy->columnCount(), 0);
+}
+
+void tst_QtAndroidItemModel::roleNames()
+{
+ const static QHash<int, QByteArray> expectedRoles = { { 0, "stringRole" },
+ { 1, "booleanRole" },
+ { 2, "integerRole" },
+ { 3, "doubleRole" },
+ { 4, "longRole" } };
+ QCOMPARE(qProxy->roleNames(), expectedRoles);
+}
+
+void tst_QtAndroidItemModel::fetchMore()
+{
+ // In the Java TestModel :
+ // canFetchMore() returns true when row count is less than 30
+ // fetchMore() adds 10 rows at most, or the remaining until row count is 30
+ QVERIFY(qProxy->canFetchMore(QModelIndex()));
+ qProxy->fetchMore(QModelIndex());
+ QCOMPARE_EQ(qProxy->rowCount(), 10);
+ QVERIFY(qProxy->canFetchMore(QModelIndex()));
+ qProxy->fetchMore(QModelIndex());
+ QCOMPARE_EQ(qProxy->rowCount(), 20);
+ jModel.callMethod<void>("addRow");
+ QVERIFY(qProxy->canFetchMore(QModelIndex()));
+ qProxy->fetchMore(QModelIndex());
+ QCOMPARE_EQ(qProxy->rowCount(), 30);
+ QVERIFY(!qProxy->canFetchMore(QModelIndex()));
+}
+
+void tst_QtAndroidItemModel::hasIndex()
+{
+ // fetchMore() adds 10 rows
+ qProxy->fetchMore(QModelIndex());
+ jModel.callMethod<void>("addCol");
+ jModel.callMethod<void>("addCol");
+
+ for (int r = 0; r < 10; ++r) {
+ for (int c = 0; c < 2; ++c) {
+ QVERIFY(qProxy->hasIndex(r, c));
+ }
+ }
+}
+
+void tst_QtAndroidItemModel::data()
+{
+ const static QHash<int, QMetaType::Type> roleToType = { { 0, QMetaType::QString },
+ { 1, QMetaType::Bool },
+ { 2, QMetaType::Int },
+ { 3, QMetaType::Double },
+ { 4, QMetaType::Long } };
+ QVERIFY(qProxy->canFetchMore(QModelIndex()));
+ qProxy->fetchMore(QModelIndex());
+ QCOMPARE_EQ(qProxy->rowCount(), 10);
+ jModel.callMethod<void>("addCol");
+ jModel.callMethod<void>("addCol");
+ jModel.callMethod<void>("addCol");
+
+ for (int r = 0; r < 10; ++r) {
+ for (int c = 0; c < 3; ++c) {
+ QModelIndex index = qProxy->index(r, c);
+ for (int role : roleToType.keys()) {
+ const QVariant data = qProxy->data(index, role);
+ QCOMPARE_EQ(data.typeId(), roleToType[role]);
+ switch (role) {
+ case 0:
+ QCOMPARE(data.toString(),
+ "r%1/c%2"_L1.arg(QString::number(r), QString::number(c)));
+ break;
+ case 1:
+ QCOMPARE(data.toBool(), ((r + c) % 2) == 0);
+ break;
+ case 2:
+ QCOMPARE(data.toInt(), (c << 8) + r);
+ break;
+ case 3:
+ QVERIFY(qFuzzyCompare(data.toDouble(), (1.0 + r) / (1.0 + c)));
+ break;
+ case 4:
+ QCOMPARE(data.toULongLong(), ((c << 8) * (r << 8)));
+ break;
+ }
+ }
+ }
+ }
+}
+
+void tst_QtAndroidItemModel::resetModel()
+{
+ jModel.callMethod<void>("reset");
+ QCOMPARE_EQ(qProxy->rowCount(), 0);
+ QCOMPARE_EQ(qProxy->columnCount(), 0);
+}
+
+#include "tst_qtandroiditemmodel.moc"
+
+QTEST_MAIN(tst_QtAndroidItemModel)
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST b/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST
index 5c5f2c9ed9..fd3d9d96b8 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST
@@ -5,8 +5,6 @@ opensuse-leap
windows gcc
[touchDragFlickableBehindButton]
windows gcc
-[touchDragSliderAndFlickable]
-* # QTBUG-86729
# QTBUG-95887
[mouseDragSlider]
opensuse-leap
@@ -26,3 +24,7 @@ android
android
[touchAndDragHandlerOnFlickable]
android
+# QTBUG-118063
+[nativeGesturePinchOnFlickableWithParentTapHandler]
+opensuse-leap
+
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/CMakeLists.txt b/tests/auto/quick/pointerhandlers/flickableinterop/CMakeLists.txt
index b3c93bf804..3836aefbb2 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_flickableinterop Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_flickableinterop LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml
index e3f15f399f..9483a12d1c 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml
index e4b2fb512d..ec790c9b99 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml
index 0afd397a62..cba135269f 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml
index 7f3045595d..99b53e6afb 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnFlickable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnFlickable.qml
index a253465a78..f6748da19c 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnFlickable.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnFlickable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml
index 224172b9d9..562dc156f9 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml
index 2cbb40e416..bbd5f5b278 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml
index 5468b5d98c..740b698fd4 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickable.qml
new file mode 100644
index 0000000000..e594f165b2
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickable.qml
@@ -0,0 +1,49 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Flickable {
+ id: root
+ width: 800
+ height: 480
+ contentWidth: 1000
+ contentHeight: 600
+
+ Rectangle {
+ id: pinchable
+ objectName: "pinchable"
+ border.color: "black"
+ color: pinch.active ? "salmon" : "peachpuff"
+ x: 100
+ y: 100
+ width: 200
+ height: 200
+ radius: 80
+ PinchHandler {
+ id: pinch
+ }
+ PointHandler {
+ id: p1
+ target: Rectangle {
+ parent: pinchable
+ color: "green"
+ visible: p1.active
+ x: p1.point.position.x - width / 2
+ y: p1.point.position.y - height / 2
+ width: 9; height: width; radius: width / 2
+ }
+ }
+ PointHandler {
+ id: p0
+ target: Rectangle {
+ parent: pinchable
+ color: "red"
+ visible: p0.active
+ x: p0.point.position.x - width / 2
+ y: p0.point.position.y - height / 2
+ width: 9; height: width; radius: width / 2
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickableWithParentTapHandler.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickableWithParentTapHandler.qml
new file mode 100644
index 0000000000..2660952f16
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickableWithParentTapHandler.qml
@@ -0,0 +1,24 @@
+import QtQuick
+
+Rectangle {
+ width: 320
+ height: 320
+
+ TapHandler {
+ onTapped: color = "tomato"
+ }
+
+ Flickable {
+ anchors.fill: parent
+ contentWidth: content.width
+ contentHeight: content.height
+ Rectangle {
+ id: content
+ objectName: "pinchable"
+ width: 150
+ height: 150
+ color: "wheat"
+ PinchHandler {}
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnFlickable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnFlickable.qml
index 6c2854b28d..dc32b1d82c 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnFlickable.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnFlickable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml
index 99f3c2a98b..f4c0e5daaa 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml
index baa6d99cd2..0293ad03b0 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp
index 05b764029a..790c7c771e 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -11,6 +11,7 @@
#include <QtQuick/private/qquickitemview_p.h>
#include <QtQuick/private/qquickpointerhandler_p.h>
#include <QtQuick/private/qquickdraghandler_p.h>
+#include <QtQuick/private/qquickpinchhandler_p.h>
#include <QtQuick/private/qquicktaphandler_p.h>
#include <QtQuick/private/qquicktableview_p.h>
#include <qpa/qwindowsysteminterface.h>
@@ -31,7 +32,6 @@ class tst_FlickableInterop : public QQmlDataTest
public:
tst_FlickableInterop()
: QQmlDataTest(QT_QMLTEST_DATADIR)
- , touchDevice(QTest::createTouchDevice())
{}
private slots:
@@ -55,10 +55,15 @@ private slots:
void touchDragSliderAndFlickable();
void touchAndDragHandlerOnFlickable_data();
void touchAndDragHandlerOnFlickable();
+ void pinchHandlerOnFlickable();
+ void nativeGesturePinchOnFlickableWithParentTapHandler_data();
+ void nativeGesturePinchOnFlickableWithParentTapHandler();
private:
void createView(QScopedPointer<QQuickView> &window, const char *fileName);
- QPointingDevice *touchDevice;
+ QScopedPointer<QPointingDevice> touchDevice = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
+ QScopedPointer<QPointingDevice> touchpad = QScopedPointer<QPointingDevice>(
+ QTest::createTouchDevice(QInputDevice::DeviceType::TouchPad));
};
void tst_FlickableInterop::createView(QScopedPointer<QQuickView> &window, const char *fileName)
@@ -97,24 +102,24 @@ void tst_FlickableInterop::touchTapButton()
// Button changes pressed state and emits tapped on release
QPoint p1 = button->mapToScene(QPointF(20, 20)).toPoint();
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).press(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(button->property("pressed").toBool());
- QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).release(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!button->property("pressed").toBool());
QCOMPARE(tappedSpy.size(), 1);
// We can drag <= dragThreshold and the button still acts normal, Flickable doesn't grab
p1 = button->mapToScene(QPointF(20, 20)).toPoint();
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).press(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(button->property("pressed").toBool());
p1 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(button->property("pressed").toBool());
- QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).release(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!button->property("pressed").toBool());
QCOMPARE(tappedSpy.size(), 2);
@@ -145,11 +150,11 @@ void tst_FlickableInterop::touchDragFlickableBehindButton()
tappedSpy.clear();
QPoint p1 = button->mapToScene(QPointF(20, 20)).toPoint();
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).press(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(button->property("pressed").toBool());
p1 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(button->property("pressed").toBool());
int i = 0;
@@ -157,14 +162,14 @@ void tst_FlickableInterop::touchDragFlickableBehindButton()
// Button is no longer pressed because Flickable steals the grab
for (; i < 100 && !flickable->isMoving(); ++i) {
p1 += QPoint(1, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
}
qCDebug(lcPointerTests) << "flickable started moving after" << i << "moves, when we got to" << p1;
QVERIFY(flickable->isMoving());
QCOMPARE(i, 2);
QVERIFY(!button->property("pressed").toBool());
- QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).release(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(!button->property("pressed").toBool());
QCOMPARE(tappedSpy.size(), 0);
@@ -241,7 +246,7 @@ void tst_FlickableInterop::mouseDragFlickableBehindButton()
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_VERIFY(button->property("pressed").toBool());
p1 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QVERIFY(button->property("pressed").toBool());
int i = 0;
for (; i < 100 && !flickable->isMoving(); ++i) {
@@ -278,19 +283,19 @@ void tst_FlickableInterop::touchDragSlider()
// Drag the slider in the allowed (vertical) direction
tappedSpy.clear();
QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint() - QPoint(0, 8);
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).press(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(slider->property("pressed").toBool());
p1 += QPoint(0, dragThreshold);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(slider->property("pressed").toBool());
QCOMPARE(slider->property("value").toInt(), 49);
p1 += QPoint(0, 1);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
p1 += QPoint(0, 10);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(slider->property("value").toInt() < 49);
QVERIFY(!flickable->isMoving());
@@ -299,12 +304,12 @@ void tst_FlickableInterop::touchDragSlider()
// Now that the DragHandler is active, the Flickable will not steal the grab
// even if we move a large distance horizontally
p1 += QPoint(dragThreshold * 2, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(!flickable->isMoving());
// Release, and do not expect the tapped signal
- QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).release(1, p1, window);
QQuickTouchUtils::flush(window);
QCOMPARE(tappedSpy.size(), 0);
QCOMPARE(translationChangedSpy.size(), 1);
@@ -417,24 +422,24 @@ void tst_FlickableInterop::touchDragFlickableBehindSlider()
// because Flickable steals the grab
tappedSpy.clear();
QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint();
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).press(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(slider->property("pressed").toBool());
p1 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(slider->property("pressed").toBool());
int i = 0;
for (; i < 100 && !flickable->isMoving(); ++i) {
p1 += QPoint(1, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
}
qCDebug(lcPointerTests) << "flickable started moving after" << i << "moves, when we got to" << p1;
QVERIFY(flickable->isMoving());
QCOMPARE(i, 2);
QVERIFY(!slider->property("pressed").toBool());
- QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).release(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(!slider->property("pressed").toBool());
QCOMPARE(tappedSpy.size(), 0);
@@ -508,19 +513,19 @@ void tst_FlickableInterop::touchDragFlickableBehindItemWithHandlers()
QPoint p1 = rect->mapToScene(rect->clipRect().center()).toPoint();
QPoint originP1 = p1;
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).press(1, p1, window);
QQuickTouchUtils::flush(window);
for (int i = 0; i < dragThreshold * 3; ++i) {
p1 = originP1;
p1.rx() += i;
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
}
QCOMPARE(flickable->isMoving(), expectedFlickableMoving);
if (!expectedFlickableMoving) {
QVERIFY(rect->mapToScene(rect->clipRect().center()).toPoint().x() > originP1.x());
}
- QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).release(1, p1, window);
QQuickTouchUtils::flush(window);
}
@@ -585,7 +590,7 @@ void tst_FlickableInterop::touchDragSliderAndFlickable()
QVERIFY(knob);
QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
QVERIFY(flickable);
- QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false);
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice.get(), false);
// The knob is initially centered over the slider's "groove"
qreal initialXOffset = qAbs(knob->mapToScene(knob->clipRect().center()).x() - slider->mapToScene
@@ -623,7 +628,10 @@ void tst_FlickableInterop::touchDragSliderAndFlickable()
QQuickTouchUtils::flush(window);
qCDebug(lcPointerTests) << "step" << i << ": fingers @" << p1 << p2 << "is Flickable moving yet?" << flickable->isMoving();
}
- QVERIFY(flickable->isMoving());
+ // In Qt 6, Flickable doesn't see the second touchpoint, so it doesn't move.
+ // One way to see this is that Flickable is more immune to stray touches than it otherwise would be.
+ // But time will tell if we are missing out on something useful, which was possible in Qt 5 (QTBUG-123490).
+ QCOMPARE(flickable->isMoving(), false);
qreal knobSliderXOffset = qAbs(knob->mapToScene(knob->clipRect().center()).toPoint().x() -
slider->mapToScene(slider->clipRect().center()).toPoint().x()) - initialXOffset;
if (knobSliderXOffset > 1)
@@ -715,7 +723,7 @@ void tst_FlickableInterop::touchAndDragHandlerOnFlickable()
}
// Drag one finger on the Flickable (between delegates) and make sure it flicks
- QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false);
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice.get(), false);
QPoint p1(780, 460);
if (delegate)
p1 = delegate->mapToScene(delegate->clipRect().bottomRight()).toPoint() + QPoint(-1, 1);
@@ -782,6 +790,187 @@ void tst_FlickableInterop::touchAndDragHandlerOnFlickable()
touchSeq.release(1, p1, window).commit();
}
+void tst_FlickableInterop::pinchHandlerOnFlickable()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("pinchOnFlickable.qml")));
+ QQuickFlickable *flickable = qmlobject_cast<QQuickFlickable*>(window.rootObject());
+ QVERIFY(flickable);
+ QQuickPointerHandler *pinchHandler = flickable->findChild<QQuickPointerHandler*>();
+ QVERIFY(pinchHandler);
+ QQuickItem *pinchable = pinchHandler->target();
+ QVERIFY(pinchable);
+
+ QSignalSpy flickMoveSpy(flickable, &QQuickFlickable::movementStarted);
+ QSignalSpy grabChangedSpy(touchDevice.get(), &QPointingDevice::grabChanged);
+
+ QObject *grabber = nullptr;
+ connect(touchDevice.get(), &QPointingDevice::grabChanged,
+ [&grabber](QObject *g, QPointingDevice::GrabTransition transition, const QPointerEvent *, const QEventPoint &) {
+ if (transition == QPointingDevice::GrabTransition::GrabExclusive)
+ grabber = g;
+ });
+
+ QPoint p0 = pinchable->mapToScene({50, 100}).toPoint();
+ QPoint p1 = pinchable->mapToScene({150, 100}).toPoint();
+ QTest::QTouchEventSequence touch = QTest::touchEvent(&window, touchDevice.get());
+
+ touch.press(0, p0, &window).press(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
+ int activeStep = -1;
+ int grabTransitionCount = 0;
+ // drag two fingers down: PinchHandler moves the item; Flickable doesn't grab, because there are 2 points
+ for (int i = 0; i < 4; ++i) {
+ p0 += QPoint(0, dragThreshold);
+ p1 += QPoint(0, dragThreshold);
+ touch.move(0, p0, &window).move(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
+ if (pinchHandler->active() && activeStep < 0) {
+ qCDebug(lcPointerTests) << "pinch began at step" << i;
+ activeStep = i;
+ QCOMPARE(grabber, pinchHandler);
+ grabTransitionCount = grabChangedSpy.count();
+ }
+ }
+ QVERIFY(pinchHandler->active());
+ QCOMPARE(grabChangedSpy.count(), grabTransitionCount);
+ QCOMPARE(grabber, pinchHandler);
+ qreal scale = pinchable->scale();
+ QCOMPARE(scale, 1);
+ qreal rot = pinchable->rotation();
+ QCOMPARE(rot, 0);
+ // start expanding and rotating
+ for (int i = 0; i < 4; ++i) {
+ p0 += QPoint(-5, 10);
+ p1 += QPoint(5, -10);
+ touch.move(0, p0, &window).move(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
+ QVERIFY(pinchHandler->active());
+ // PinchHandler keeps grab: no more transitions
+ QCOMPARE(grabChangedSpy.count(), grabTransitionCount);
+ QCOMPARE(grabber, pinchHandler);
+ QTRY_COMPARE_GT(pinchable->scale(), scale);
+ scale = pinchable->scale();
+ QCOMPARE_LT(pinchable->rotation(), rot);
+ rot = pinchable->rotation();
+ }
+ touch.release(0, p0, &window).release(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
+ QTRY_COMPARE(pinchHandler->active(), false);
+ QCOMPARE(flickMoveSpy.count(), 0); // Flickable never moved
+}
+
+void tst_FlickableInterop::nativeGesturePinchOnFlickableWithParentTapHandler_data()
+{
+ QTest::addColumn<const QPointingDevice*>("device");
+ QTest::addColumn<Qt::MouseButton>("button");
+ QTest::addColumn<Qt::NativeGestureType>("gesture");
+ QTest::addColumn<qreal>("value");
+ QTest::addColumn<qreal>("expectedPropertyValue");
+
+ const QPointingDevice *constTouchPad = touchpad.data();
+
+ QTest::newRow("touchpad: left and rotate") << constTouchPad << Qt::LeftButton << Qt::RotateNativeGesture << 5.0 << 10.0;
+ QTest::newRow("touchpad: right and rotate") << constTouchPad << Qt::RightButton << Qt::RotateNativeGesture << 5.0 << 10.0;
+ QTest::newRow("touchpad: left and scale") << constTouchPad << Qt::LeftButton << Qt::ZoomNativeGesture << 0.1 << 1.21;
+ QTest::newRow("touchpad: right and scale") << constTouchPad << Qt::RightButton << Qt::ZoomNativeGesture << 0.1 << 1.21;
+
+ const auto *mouse = QPointingDevice::primaryPointingDevice();
+ if (mouse->type() == QInputDevice::DeviceType::Mouse) {
+ QTest::newRow("mouse: left and rotate") << mouse << Qt::LeftButton << Qt::RotateNativeGesture << 5.0 << 10.0;
+ QTest::newRow("mouse: right and rotate") << mouse << Qt::RightButton << Qt::RotateNativeGesture << 5.0 << 10.0;
+ QTest::newRow("mouse: left and scale") << mouse << Qt::LeftButton << Qt::ZoomNativeGesture << 0.1 << 1.21;
+ QTest::newRow("mouse: right and scale") << mouse << Qt::RightButton << Qt::ZoomNativeGesture << 0.1 << 1.21;
+ } else {
+ qCWarning(lcPointerTests) << "skipping mouse tests: primary device is not a mouse" << mouse;
+ }
+}
+
+void tst_FlickableInterop::nativeGesturePinchOnFlickableWithParentTapHandler()
+{
+ QFETCH(const QPointingDevice*, device);
+ QFETCH(Qt::MouseButton, button);
+ QFETCH(Qt::NativeGestureType, gesture);
+ QFETCH(qreal, value);
+ QFETCH(qreal, expectedPropertyValue);
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("pinchOnFlickableWithParentTapHandler.qml")));
+ QQuickFlickable *flickable = window.rootObject()->findChild<QQuickFlickable*>();
+ QVERIFY(flickable);
+ QQuickPointerHandler *pinchHandler = flickable->findChild<QQuickPinchHandler*>();
+ QVERIFY(pinchHandler);
+ QQuickItem *pinchable = pinchHandler->target();
+ QVERIFY(pinchable);
+ QQuickTapHandler *tapHandler = window.rootObject()->findChild<QQuickTapHandler*>();
+ QVERIFY(tapHandler);
+ const bool expectTap = button & tapHandler->acceptedButtons();
+
+ QSignalSpy flickMoveSpy(flickable, &QQuickFlickable::movementStarted);
+ QSignalSpy grabChangedSpy(touchDevice.get(), &QPointingDevice::grabChanged);
+ QSignalSpy tapActiveSpy(tapHandler, &QQuickTapHandler::activeChanged);
+ QSignalSpy tapSpy(tapHandler, &QQuickTapHandler::tapped);
+
+ QObject *grabber = nullptr;
+ connect(device, &QPointingDevice::grabChanged,
+ [&grabber](QObject *g, QPointingDevice::GrabTransition transition, const QPointerEvent *, const QEventPoint &) {
+ if (transition == QPointingDevice::GrabTransition::GrabExclusive)
+ grabber = g;
+ });
+
+ const QPoint pinchPos(75, 75);
+ const QPoint outsidePos(200, 200);
+
+ // move to position
+ QTest::mouseMove(&window, pinchPos);
+
+ // pinch via native gesture
+ ulong ts = 502; // after the mouse move, which is at time 501 in practice
+ QWindowSystemInterface::handleGestureEvent(&window, ts++, touchpad.get(),
+ Qt::BeginNativeGesture, pinchPos, pinchPos);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ for (int i = 0; i < 2; ++i) {
+ QWindowSystemInterface::handleGestureEventWithRealValue(&window, ts++, touchpad.get(),
+ gesture, value, pinchPos, pinchPos);
+ }
+ if (gesture == Qt::RotateNativeGesture)
+ QTRY_COMPARE(pinchHandler->parentItem()->rotation(), expectedPropertyValue);
+ else if (gesture == Qt::ZoomNativeGesture)
+ QTRY_COMPARE(pinchHandler->parentItem()->scale(), expectedPropertyValue);
+ QVERIFY(pinchHandler->active());
+ QCOMPARE(grabChangedSpy.count(), 0);
+ QCOMPARE(grabber, nullptr);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ QWindowSystemInterface::handleGestureEvent(&window, ts++, touchpad.get(),
+ Qt::EndNativeGesture, pinchPos, pinchPos);
+
+ // tap in square: TapHandler detects tap iff acceptedButtons permits
+ // TODO delay; unfortunately this also begins at timestamp 502 because we don't have testlib
+ // functions to send gesture events, and QQuickTest::pointerPress() doesn't take a delay value
+ QQuickTest::pointerPress(device, &window, 0, pinchPos, button);
+ QCOMPARE(tapHandler->point().id(), expectTap ? 0 : -1);
+ QQuickTest::pointerRelease(device, &window, 0, pinchPos, button);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ QCOMPARE(tapSpy.size() != 0, expectTap);
+ QCOMPARE(tapActiveSpy.size(), 0);
+ QCOMPARE(tapHandler->point().id(), -1); // does not keep tracking after release
+
+ // move outside: nothing should happen;
+ // but QTBUG-108896 happened because TapHandler was setting pointInfo to track this moving point
+ QQuickTest::pointerMove(device, &window, 0, outsidePos);
+ QCOMPARE(tapHandler->point().id(), -1); // does not track after mouse move
+
+ // tap outside: nothing happens
+ tapSpy.clear();
+ tapActiveSpy.clear();
+ QQuickTest::pointerPress(device, &window, 0, outsidePos, button);
+ QQuickTest::pointerRelease(device, &window, 0, outsidePos, button);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ QCOMPARE(tapSpy.size(), 0);
+ QCOMPARE(tapActiveSpy.size(), 0);
+}
+
QTEST_MAIN(tst_FlickableInterop)
#include "tst_flickableinterop.moc"
diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/CMakeLists.txt b/tests/auto/quick/pointerhandlers/mousearea_interop/CMakeLists.txt
index f66a7e8d0d..22123e6385 100644
--- a/tests/auto/quick/pointerhandlers/mousearea_interop/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_mousearea_interop Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_mousearea_interop LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/data/dragTakeOverFromSibling.qml b/tests/auto/quick/pointerhandlers/mousearea_interop/data/dragTakeOverFromSibling.qml
index 846c31cc61..1bde433dba 100644
--- a/tests/auto/quick/pointerhandlers/mousearea_interop/data/dragTakeOverFromSibling.qml
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/data/dragTakeOverFromSibling.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp b/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp
index 3c288cbb3b..b1a480b9cf 100644
--- a/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -16,6 +16,8 @@
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
+#include <QtCore/qpointer.h>
+
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
class tst_MouseAreaInterop : public QQmlDataTest
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/BLACKLIST b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/BLACKLIST
index 3f01d3a7d4..80d6dd0ee8 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/BLACKLIST
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/BLACKLIST
@@ -1,2 +1,3 @@
-[touchesThenPinch]
-* # QTBUG-86729
+# QTBUG-118062
+[touchDrag]
+opensuse-leap
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/CMakeLists.txt b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/CMakeLists.txt
index b0843f726b..9f19e8b427 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_multipointtoucharea_interop Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_multipointtoucharea_interop LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/dragParentOfMPTA.qml b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/dragParentOfMPTA.qml
index e6ebfdd552..ad4494eb25 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/dragParentOfMPTA.qml
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/dragParentOfMPTA.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml
index b6fad6fade..199292e015 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
@@ -35,8 +35,8 @@ Rectangle {
Item {
id: crosshairs
property TouchPoint touchPoint
- x: touchPoint.x - width / 2
- y: touchPoint.y - height / 2
+ x: touchPoint?.x - width / 2
+ y: touchPoint?.y - height / 2
width: 300; height: 300
visible: touchPoint.pressed
rotation: touchPoint.rotation
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/unloadHandlerOnPress.qml b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/unloadHandlerOnPress.qml
index e8b8fe769e..868a5265a6 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/unloadHandlerOnPress.qml
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/unloadHandlerOnPress.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
index ab64f6bb24..a4cc182422 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -15,6 +15,8 @@
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
+#include <QtCore/qpointer.h>
+
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
class tst_MptaInterop : public QQmlDataTest
@@ -250,7 +252,7 @@ void tst_MptaInterop::touchesThenPinch()
}
qCDebug(lcPointerTests) << "drag started after" << dragTookGrab
<< "moves; ended with translation" << drag->activeTranslation();
- QCOMPARE(devPriv->pointById(1)->exclusiveGrabber, drag);
+ QCOMPARE(devPriv->pointById(2)->exclusiveGrabber, drag);
QTRY_VERIFY(drag->activeTranslation().x() > 0);
touch.release(2, p2).commit();
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquickdraghandler/CMakeLists.txt
index 06cc34441a..23087c1d48 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickdraghandler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickdraghandler LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml
index 7a305e7b79..065b0aaed8 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml
index e3f15f399f..9483a12d1c 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml
index 502891cd1b..200e846207 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml
index 1041cd4f07..47be6052ad 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.15
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml
index 7a4dc3a69a..5d700cdd08 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml
index 146881e0a4..ea71da5623 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml
index e805adbcb8..6c7a25c148 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/snapMode.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/snapMode.qml
index 0a3d3618a8..30b28ac9e8 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/snapMode.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/snapMode.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
index 9d6e4409d0..15df656b93 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -17,6 +17,8 @@
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
+#include <QtCore/qpointer.h>
+
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
class tst_DragHandler : public QQmlDataTest
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST b/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST
index 1c4499753a..c0d73ff05f 100644
--- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST
@@ -3,3 +3,6 @@ macos # Can't move cursor (QTBUG-76312)
# QTBUG-103065
[movingItemWithHoverHandler]
android
+[window]
+opensuse-leap # QTBUG-122405
+
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquickhoverhandler/CMakeLists.txt
index 25c8dfd604..a2e7d640d5 100644
--- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickhoverhandler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickhoverhandler LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/changingCursor.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/changingCursor.qml
new file mode 100644
index 0000000000..42b658a4d4
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/changingCursor.qml
@@ -0,0 +1,37 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.15
+
+
+Rectangle {
+ id: brownRect
+ objectName: "brownRect"
+
+ width: 400
+ height: 400
+
+ HoverHandler {
+ id: hh
+ cursorShape: parent.colorIndex == 0 ?
+ Qt.CrossCursor :
+ Qt.OpenHandCursor
+ }
+
+ property list<color> colors: ["beige", "brown"]
+ property int colorIndex: 0
+
+ color: colors[colorIndex]
+
+ Timer {
+ id: colorTimer
+ interval: 200
+ running: true
+ repeat: true
+
+ onTriggered: {
+ parent.colorIndex = (parent.colorIndex + 1) % parent.colors.length;
+ parent.color = parent.colors[parent.colorIndex];
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverDeviceCursors.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverDeviceCursors.qml
index edb56ffdc6..48e130a35e 100644
--- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverDeviceCursors.qml
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverDeviceCursors.qml
@@ -3,47 +3,53 @@ import QtQuick
Item {
width: 200; height: 200
- HoverHandler {
- objectName: "stylus"
- acceptedDevices: PointerDevice.Stylus
- acceptedPointerTypes: PointerDevice.Pen
- cursorShape: Qt.CrossCursor
- }
+ Rectangle {
+ width: 100; height: 100
+ anchors.centerIn: parent
+ border.color: "black"
- HoverHandler {
- objectName: "stylus eraser"
- acceptedDevices: PointerDevice.Stylus
- acceptedPointerTypes: PointerDevice.Eraser
- cursorShape: Qt.PointingHandCursor
- }
+ HoverHandler {
+ objectName: "stylus"
+ acceptedDevices: PointerDevice.Stylus
+ acceptedPointerTypes: PointerDevice.Pen
+ cursorShape: Qt.CrossCursor
+ }
- HoverHandler {
- objectName: "airbrush"
- acceptedDevices: PointerDevice.Airbrush
- acceptedPointerTypes: PointerDevice.Pen
- cursorShape: Qt.BusyCursor
- }
+ HoverHandler {
+ objectName: "stylus eraser"
+ acceptedDevices: PointerDevice.Stylus
+ acceptedPointerTypes: PointerDevice.Eraser
+ cursorShape: Qt.PointingHandCursor
+ }
- HoverHandler {
- objectName: "airbrush eraser"
- acceptedDevices: PointerDevice.Airbrush
- acceptedPointerTypes: PointerDevice.Eraser
- cursorShape: Qt.OpenHandCursor
- }
+ HoverHandler {
+ objectName: "airbrush"
+ acceptedDevices: PointerDevice.Airbrush
+ acceptedPointerTypes: PointerDevice.Pen
+ cursorShape: Qt.BusyCursor
+ }
- HoverHandler {
- objectName: "mouse"
- acceptedDevices: PointerDevice.Mouse
- // acceptedPointerTypes can be omitted because Mouse is not ambiguous.
- // When a genuine mouse move is sent, there's a conflict, and this one should win.
- cursorShape: Qt.IBeamCursor
- }
+ HoverHandler {
+ objectName: "airbrush eraser"
+ acceptedDevices: PointerDevice.Airbrush
+ acceptedPointerTypes: PointerDevice.Eraser
+ cursorShape: Qt.OpenHandCursor
+ }
+
+ HoverHandler {
+ objectName: "mouse"
+ acceptedDevices: PointerDevice.Mouse
+ // acceptedPointerTypes can be omitted because Mouse is not ambiguous.
+ // When a genuine mouse move is sent, there's a conflict, and this one should win.
+ cursorShape: Qt.IBeamCursor
+ }
- HoverHandler {
- objectName: "conflictingMouse"
- acceptedDevices: PointerDevice.Mouse
- // acceptedPointerTypes can be omitted because Mouse is not ambiguous.
- // When a genuine mouse move is sent, there's a conflict, and this one should lose.
- cursorShape: Qt.ClosedHandCursor
+ HoverHandler {
+ objectName: "conflictingMouse"
+ acceptedDevices: PointerDevice.Mouse
+ // acceptedPointerTypes can be omitted because Mouse is not ambiguous.
+ // When a genuine mouse move is sent, there's a conflict, and this one should lose.
+ cursorShape: Qt.ClosedHandCursor
+ }
}
}
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverHandler.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverHandler.qml
new file mode 100644
index 0000000000..60dfc53c40
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverHandler.qml
@@ -0,0 +1,17 @@
+import QtQuick
+
+Item {
+ width: 320
+ height: 240
+
+ Rectangle {
+ width: 100
+ height: 100
+ anchors.centerIn: parent
+ color: hh.hovered ? "lightsteelblue" : "beige"
+
+ HoverHandler {
+ id: hh
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml
index 43d9827ad7..ca30a7fe99 100644
--- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.15
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
index e488c0486f..0569fed472 100644
--- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -48,9 +48,13 @@ private slots:
void deviceCursor();
void addHandlerFromCpp();
void ensureHoverHandlerWorksWhenItemHasHoverDisabled();
+ void changeCursor();
+ void touchDrag();
private:
void createView(QScopedPointer<QQuickView> &window, const char *fileName);
+
+ QScopedPointer<QPointingDevice> touchscreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
};
void tst_HoverHandler::createView(QScopedPointer<QQuickView> &window, const char *fileName)
@@ -567,6 +571,17 @@ void tst_HoverHandler::deviceCursor()
QCOMPARE(eraserHandler->isHovered(), false);
QCOMPARE(aibrushHandler->isHovered(), false);
QCOMPARE(airbrushEraserHandler->isHovered(), true); // there was no fresh QTabletEvent to tell it not to be hovered
+
+ // hover with the stylus again, then move the mouse outside the handlers' parent item
+ testStylusDevice(QInputDevice::DeviceType::Stylus, QPointingDevice::PointerType::Pen,
+ Qt::CrossCursor, stylusHandler);
+ QTest::mouseMove(&window, QPoint(180, 180));
+ // the mouse has left the item: all its HoverHandlers should be unhovered (QTBUG-116505)
+ QCOMPARE(stylusHandler->isHovered(), false);
+ QCOMPARE(eraserHandler->isHovered(), false);
+ QCOMPARE(aibrushHandler->isHovered(), false);
+ QCOMPARE(airbrushEraserHandler->isHovered(), false);
+ QCOMPARE(mouseHandler->isHovered(), false);
}
void tst_HoverHandler::addHandlerFromCpp()
@@ -671,6 +686,74 @@ void tst_HoverHandler::ensureHoverHandlerWorksWhenItemHasHoverDisabled()
QCOMPARE(spy.size(), 2);
}
+void tst_HoverHandler::changeCursor()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "changingCursor.qml");
+ QQuickView * window = windowPtr.data();
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickItem *item = window->findChild<QQuickItem *>("brownRect");
+ QVERIFY(item);
+ QQuickHoverHandler *hh = item->findChild<QQuickHoverHandler *>();
+ QVERIFY(hh);
+
+ QPoint itemCenter(item->mapToScene(QPointF(item->width() / 2, item->height() / 2)).toPoint());
+ QSignalSpy hoveredSpy(hh, SIGNAL(hoveredChanged()));
+
+ QTest::mouseMove(window, itemCenter);
+
+ QTRY_COMPARE(hoveredSpy.size(), 1);
+
+#if QT_CONFIG(cursor)
+ QTRY_COMPARE(window->cursor().shape(), Qt::CrossCursor);
+ QTRY_COMPARE(window->cursor().shape(), Qt::OpenHandCursor);
+ QTRY_COMPARE(window->cursor().shape(), Qt::CrossCursor);
+ QTRY_COMPARE(window->cursor().shape(), Qt::OpenHandCursor);
+#endif
+}
+
+void tst_HoverHandler::touchDrag()
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("hoverHandler.qml")));
+ const QQuickItem *root = window.rootObject();
+ QQuickHoverHandler *handler = root->findChild<QQuickHoverHandler *>();
+ QVERIFY(handler);
+
+ // polishAndSync() calls flushFrameSynchronousEvents() before emitting afterAnimating()
+ QSignalSpy frameSyncSpy(&window, &QQuickWindow::afterAnimating);
+
+ const QPoint out(root->width() - 1, root->height() / 2);
+ QPoint in(root->width() / 2, root->height() / 2);
+
+ QTest::touchEvent(&window, touchscreen.get()).press(0, out, &window);
+ QQuickTouchUtils::flush(&window);
+ QCOMPARE(handler->isHovered(), false);
+
+ frameSyncSpy.clear();
+ QTest::touchEvent(&window, touchscreen.get()).move(0, in, &window);
+ QQuickTouchUtils::flush(&window);
+ QTRY_COMPARE(handler->isHovered(), true);
+ QCOMPARE(handler->point().scenePosition(), in);
+
+ in += {10, 10};
+ QTest::touchEvent(&window, touchscreen.get()).move(0, in, &window);
+ QQuickTouchUtils::flush(&window);
+ // ensure that the color change is visible
+ QTRY_COMPARE_GE(frameSyncSpy.size(), 1);
+ QCOMPARE(handler->isHovered(), true);
+ QCOMPARE(handler->point().scenePosition(), in);
+
+ QTest::touchEvent(&window, touchscreen.get()).move(0, out, &window);
+ QQuickTouchUtils::flush(&window);
+ QTRY_COMPARE_GE(frameSyncSpy.size(), 2);
+ QCOMPARE(handler->isHovered(), false);
+
+ QTest::touchEvent(&window, touchscreen.get()).release(0, out, &window);
+}
+
QTEST_MAIN(tst_HoverHandler)
#include "tst_qquickhoverhandler.moc"
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquickpinchhandler/CMakeLists.txt
index f16dfa3421..1334607ab2 100644
--- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickpinchhandler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpinchhandler LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/nullTarget.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/nullTarget.qml
index a348938aca..9d9903fc0e 100644
--- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/nullTarget.qml
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/nullTarget.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.15
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchAndDrag.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchAndDrag.qml
index 70c105836f..ddd63ec720 100644
--- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchAndDrag.qml
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchAndDrag.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml
index 37f22c949a..2b9b3eb156 100644
--- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
@@ -35,7 +35,14 @@ Rectangle {
}
}
- Text { color: "magenta"; z: 1; text: "scale: " + blackRect.scale}
+ Text {
+ color: "magenta"
+ z: 1
+ text: "scale: " + blackRect.scale +
+ "\npos: " + blackRect.x.toFixed(2) + ", " + blackRect.y.toFixed(2) +
+ "\ntranslation: active " + pincharea.activeTranslation.x.toFixed(2) + ", " + pincharea.activeTranslation.y.toFixed(2) +
+ "\n persistent " + pincharea.persistentTranslation.x.toFixed(2) + ", " + pincharea.persistentTranslation.y.toFixed(2)
+ }
Rectangle {
id: blackRect
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/threeFingers.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/threeFingers.qml
index dbebf92933..ed9220f99e 100644
--- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/threeFingers.qml
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/threeFingers.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/transformedPinchHandler.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/transformedPinchHandler.qml
index 56fa8c9f8e..f25d0e9f38 100644
--- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/transformedPinchHandler.qml
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/transformedPinchHandler.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp
index a61cbd76db..78483c5bdb 100644
--- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
@@ -34,6 +34,8 @@ private slots:
void scaleThreeFingers();
void scaleNativeGesture_data();
void scaleNativeGesture();
+ void cumulativeNativeGestures_data();
+ void cumulativeNativeGestures();
void pan();
void dragAxesEnabled_data();
void dragAxesEnabled();
@@ -43,8 +45,8 @@ private slots:
void transformedpinchHandler();
private:
- QPointingDevice *touchscreen = QTest::createTouchDevice();
- QPointingDevice *touchpad = QTest::createTouchDevice(QInputDevice::DeviceType::TouchPad);
+ QScopedPointer<QPointingDevice> touchscreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
+ QScopedPointer<QPointingDevice> touchpad = QScopedPointer<QPointingDevice>(QTest::createTouchDevice(QInputDevice::DeviceType::TouchPad));
};
void tst_QQuickPinchHandler::cleanupTestCase()
@@ -230,13 +232,13 @@ void tst_QQuickPinchHandler::scale()
QVERIFY(pinchHandler != nullptr);
QQuickItem *blackRect = (hasTarget ? pinchHandler->target() : pinchHandler->parentItem());
QVERIFY(blackRect != nullptr);
- QSignalSpy grabChangedSpy(pinchHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition, QEventPoint)));
+ QSignalSpy grabChangedSpy(pinchHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition,QEventPoint)));
QSignalSpy scaleChangedSpy(pinchHandler, &QQuickPinchHandler::scaleChanged);
if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
QPoint p0(80, 80);
QPoint p1(100, 100);
- QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(&window, touchscreen);
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(&window, touchscreen.get());
pinchSequence.press(0, p0, &window).commit();
QQuickTouchUtils::flush(&window);
// In order for the stationary point to remember its previous position,
@@ -383,7 +385,7 @@ void tst_QQuickPinchHandler::scaleThreeFingers()
QPoint p1(220, 80);
QPoint p2(150, 220);
{
- QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen);
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen.get());
pinchSequence.press(0, p0, window).commit();
QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
@@ -488,10 +490,10 @@ void tst_QQuickPinchHandler::scaleNativeGesture()
// so as to compensate for the change in size, to hold the centroid in place
const QPointF expectedPos = targetPos + QPointF( (pinchPos.x() - target->x()) * (expectedScale - 1),
(pinchPos.y() - target->y()) * (expectedScale - 1) );
- QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad,
+ QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad.get(),
Qt::BeginNativeGesture, pinchPos, pinchPos);
if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
- QWindowSystemInterface::handleGestureEventWithRealValue(window, ts++, touchpad,
+ QWindowSystemInterface::handleGestureEventWithRealValue(window, ts++, touchpad.get(),
Qt::ZoomNativeGesture, scale - 1, pinchPos, pinchPos);
if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
QTRY_COMPARE(target->scale(), expectedScale);
@@ -509,7 +511,7 @@ void tst_QQuickPinchHandler::scaleNativeGesture()
QCOMPARE(pinchHandler->activeRotation(), 0);
QCOMPARE(pinchHandler->rotationAxis()->persistentValue(), 0);
QCOMPARE(pinchHandler->rotationAxis()->activeValue(), 0);
- QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad,
+ QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad.get(),
Qt::EndNativeGesture, pinchPos, pinchPos);
QTRY_COMPARE(pinchHandler->active(), false);
QCOMPARE(target->scale(), expectedScale);
@@ -528,9 +530,9 @@ void tst_QQuickPinchHandler::scaleNativeGesture()
const qreal reverseScale = (1 / expectedScale);
pinchPos = QPointF(110, 110);
pinchLocalPos = target->mapFromScene(pinchPos);
- QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad,
+ QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad.get(),
Qt::BeginNativeGesture, pinchPos, pinchPos);
- QWindowSystemInterface::handleGestureEventWithRealValue(window, ts++, touchpad,
+ QWindowSystemInterface::handleGestureEventWithRealValue(window, ts++, touchpad.get(),
Qt::ZoomNativeGesture, reverseScale - 1, pinchPos, pinchPos);
QTRY_COMPARE(target->scale(), 1);
QCOMPARE(pinchHandler->active(), true);
@@ -541,7 +543,7 @@ void tst_QQuickPinchHandler::scaleNativeGesture()
QCOMPARE(pinchHandler->persistentScale(), 1);
QCOMPARE(pinchHandler->activeScale(), reverseScale);
QCOMPARE(pinchHandler->scaleAxis()->activeValue(), reverseScale);
- QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad,
+ QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad.get(),
Qt::EndNativeGesture, pinchPos, pinchPos);
QTRY_COMPARE(pinchHandler->active(), false);
QCOMPARE(target->scale(), 1);
@@ -550,6 +552,127 @@ void tst_QQuickPinchHandler::scaleNativeGesture()
QCOMPARE(pinchHandler->scaleAxis()->activeValue(), 1);
}
+void tst_QQuickPinchHandler::cumulativeNativeGestures_data()
+{
+ QTest::addColumn<const QPointingDevice*>("device");
+ QTest::addColumn<Qt::NativeGestureType>("gesture");
+ QTest::addColumn<qreal>("value");
+ QTest::addColumn<QList<QPoint>>("expectedTargetTranslations");
+
+ const auto *touchpadDevice = touchpad.get();
+ const auto *mouse = QPointingDevice::primaryPointingDevice();
+
+ QTest::newRow("touchpad: rotate") << touchpadDevice << Qt::RotateNativeGesture << 5.0
+ << QList<QPoint>{{-2, 2}, {-5, 4}, {-7, 6}, {-10, 7}};
+ QTest::newRow("touchpad: scale") << touchpadDevice << Qt::ZoomNativeGesture << 0.1
+ << QList<QPoint>{{3, 3}, {5, 5}, {8, 8}, {12, 12}};
+ if (mouse->type() == QInputDevice::DeviceType::Mouse) {
+ QTest::newRow("mouse: rotate") << mouse << Qt::RotateNativeGesture << 5.0
+ << QList<QPoint>{{-2, 2}, {-5, 4}, {-7, 6}, {-10, 7}};
+ QTest::newRow("mouse: scale") << mouse << Qt::ZoomNativeGesture << 0.1
+ << QList<QPoint>{{3, 3}, {5, 5}, {8, 8}, {12, 12}};
+ } else {
+ qCWarning(lcPointerTests) << "skipping mouse tests: primary device is not a mouse" << mouse;
+ }
+}
+
+void tst_QQuickPinchHandler::cumulativeNativeGestures()
+{
+ QFETCH(const QPointingDevice*, device);
+ QFETCH(Qt::NativeGestureType, gesture);
+ QFETCH(qreal, value);
+ QFETCH(QList<QPoint>, expectedTargetTranslations);
+
+ QCOMPARE(expectedTargetTranslations.size(), 4);
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("pinchproperties.qml")));
+ QVERIFY(window.rootObject() != nullptr);
+ qApp->processEvents();
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(window.rootObject());
+ QVERIFY(root != nullptr);
+ QQuickPinchHandler *pinchHandler = root->findChild<QQuickPinchHandler*>("pinchHandler");
+ QVERIFY(pinchHandler != nullptr);
+ QQuickItem *target = root->findChild<QQuickItem*>("blackrect");
+ QVERIFY(target != nullptr);
+ QCOMPARE(pinchHandler->target(), target);
+
+ ulong ts = 1;
+ qreal expectedScale = 1;
+ qreal expectedRotation = 0;
+ QPointF pinchPos(75, 75);
+ const QPointF initialTargetPos(target->position());
+ QWindowSystemInterface::handleGestureEvent(&window, ts++, device,
+ Qt::BeginNativeGesture, pinchPos, pinchPos);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ for (int i = 1; i <= 4; ++i) {
+ QWindowSystemInterface::handleGestureEventWithRealValue(&window, ts++, device,
+ gesture, value, pinchPos, pinchPos);
+ qApp->processEvents();
+ switch (gesture) {
+ case Qt::ZoomNativeGesture:
+ expectedScale = qBound(qreal(0.5), qPow(1 + value, i), qreal(4));
+ break;
+ case Qt::RotateNativeGesture:
+ expectedRotation = qBound(qreal(0), value * i, qreal(90));
+ break;
+ default:
+ break; // PinchHandler doesn't react to the others
+ }
+
+ qCDebug(lcPointerTests) << i << gesture << "with value" << value
+ << ": scale" << target->scale() << "expected" << expectedScale
+ << ": rotation" << target->rotation() << "expected" << expectedRotation;
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ QCOMPARE(target->scale(), expectedScale);
+ QCOMPARE(target->rotation(), expectedRotation);
+ QCOMPARE(pinchHandler->persistentScale(), expectedScale);
+ QCOMPARE(pinchHandler->activeScale(), expectedScale);
+ QCOMPARE(pinchHandler->scaleAxis()->persistentValue(), expectedScale);
+ QCOMPARE(pinchHandler->scaleAxis()->activeValue(), expectedScale);
+ QCOMPARE(pinchHandler->persistentRotation(), expectedRotation);
+ QCOMPARE(pinchHandler->activeRotation(), expectedRotation);
+ QCOMPARE(pinchHandler->rotationAxis()->persistentValue(), expectedRotation);
+ QCOMPARE(pinchHandler->rotationAxis()->activeValue(), expectedRotation);
+ // The target gets transformed around the gesture position, for which
+ // QQuickItemPrivate::adjustedPosForTransform() computes its new position to compensate.
+ QPointF delta = target->position() - initialTargetPos;
+ qCDebug(lcPointerTests) << "target moved by" << delta << "to" << target->position()
+ << "active trans" << pinchHandler->activeTranslation()
+ << "perst trans" << pinchHandler->persistentTranslation();
+ QCOMPARE_NE(target->position(), initialTargetPos);
+ QCOMPARE(delta.toPoint(), expectedTargetTranslations.at(i - 1));
+ // The native pinch gesture cannot include a translation component (and
+ // the cursor doesn't move while you are performing the gesture on a touchpad).
+ QCOMPARE(pinchHandler->activeTranslation(), QPointF());
+ // The target only moves to compensate for scale and rotation changes, and that's
+ // not reflected in PinchHandler.persistentTranslation.
+ QCOMPARE(pinchHandler->persistentTranslation(), QPointF());
+ }
+ QCOMPARE(pinchHandler->active(), true);
+ qCDebug(lcPointerTests) << "centroid: local" << pinchHandler->centroid().position()
+ << "scene" << pinchHandler->centroid().scenePosition();
+ QCOMPARE(pinchHandler->persistentScale(), expectedScale);
+ QCOMPARE(pinchHandler->activeScale(), expectedScale);
+ QCOMPARE(pinchHandler->scaleAxis()->activeValue(), expectedScale);
+ QWindowSystemInterface::handleGestureEvent(&window, ts++, device,
+ Qt::EndNativeGesture, pinchPos, pinchPos);
+ QTRY_COMPARE(pinchHandler->active(), false);
+ QCOMPARE(target->scale(), expectedScale);
+ QCOMPARE(target->rotation(), expectedRotation);
+ QCOMPARE(pinchHandler->persistentScale(), expectedScale);
+ QCOMPARE(pinchHandler->activeScale(), 1);
+ QCOMPARE(pinchHandler->scaleAxis()->persistentValue(), expectedScale);
+ QCOMPARE(pinchHandler->scaleAxis()->activeValue(), 1);
+ QCOMPARE(pinchHandler->persistentRotation(), expectedRotation);
+ QCOMPARE(pinchHandler->activeRotation(), 0);
+ QCOMPARE(pinchHandler->rotationAxis()->persistentValue(), expectedRotation);
+ QCOMPARE(pinchHandler->rotationAxis()->activeValue(), 0);
+ QCOMPARE(pinchHandler->activeTranslation(), QPointF());
+ QCOMPARE(pinchHandler->persistentTranslation(), QPointF());
+}
+
void tst_QQuickPinchHandler::pan()
{
QQuickView *window = QQuickViewTestUtils::createView();
@@ -575,7 +698,7 @@ void tst_QQuickPinchHandler::pan()
QPoint p1(100, 100);
{
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
- QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen);
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen.get());
pinchSequence.press(0, p0, window).commit();
QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
@@ -649,7 +772,7 @@ void tst_QQuickPinchHandler::pan()
// pan x beyond bound
p0 += QPoint(100,100);
p1 += QPoint(100,100);
- QTest::touchEvent(window, touchscreen).move(0, p0, window).move(1, p1, window);
+ QTest::touchEvent(window, touchscreen.get()).move(0, p0, window).move(1, p1, window);
QQuickTouchUtils::flush(window);
QCOMPARE(blackRect->x(), 140.0);
@@ -657,7 +780,7 @@ void tst_QQuickPinchHandler::pan()
QCOMPARE(translationChangedSpy.size(), 5);
QCOMPARE(translationChangedSpy.last().first().value<QVector2D>(), QVector2D(100, 100));
- QTest::touchEvent(window, touchscreen).release(0, p0, window).release(1, p1, window);
+ QTest::touchEvent(window, touchscreen.get()).release(0, p0, window).release(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(!root->property("pinchActive").toBool());
}
@@ -697,7 +820,7 @@ void tst_QQuickPinchHandler::dragAxesEnabled()
QPoint blackRectPos = blackRect->position().toPoint();
// press two points, one above the rectangle's center and one below
- QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen);
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen.get());
pinchSequence.press(0, p0, window).press(1, p1, window).commit();
QQuickTouchUtils::flush(window);
@@ -734,7 +857,7 @@ void tst_QQuickPinchHandler::dragAxesEnabled()
QCOMPARE(blackRect->position().toPoint().x(), xEnabled ? 140 : blackRectPos.x()); // because of xAxis.maximum
QCOMPARE(blackRect->position().toPoint().y(), yEnabled ? 170 : blackRectPos.y()); // because of yAxis.maximum
- QTest::touchEvent(window, touchscreen).release(0, p0, window).release(1, p1, window);
+ QTest::touchEvent(window, touchscreen.get()).release(0, p0, window).release(1, p1, window);
QQuickTouchUtils::flush(window);
}
@@ -763,7 +886,7 @@ void tst_QQuickPinchHandler::retouch()
QPoint p0(80, 80);
QPoint p1(100, 100);
{
- QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen);
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen.get());
pinchSequence.press(0, p0, window).commit();
QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
@@ -846,7 +969,7 @@ void tst_QQuickPinchHandler::cancel()
QPoint p0(80, 80);
QPoint p1(100, 100);
{
- QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen);
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen.get());
pinchSequence.press(0, p0, window).commit();
QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
@@ -876,7 +999,7 @@ void tst_QQuickPinchHandler::cancel()
QSKIP("cancel is not supported atm");
- QTouchEvent cancelEvent(QEvent::TouchCancel, touchscreen);
+ QTouchEvent cancelEvent(QEvent::TouchCancel, touchscreen.get());
QCoreApplication::sendEvent(window, &cancelEvent);
QQuickTouchUtils::flush(window);
@@ -932,7 +1055,7 @@ void tst_QQuickPinchHandler::transformedpinchHandler()
const int threshold = qApp->styleHints()->startDragDistance();
{
- QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(view, touchscreen);
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(view, touchscreen.get());
// start pinchHandler
pinchSequence.press(0, p0, view).commit();
QQuickTouchUtils::flush(view);
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquickpointerhandler/CMakeLists.txt
index da110a6398..e15b802814 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointerhandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickpointerhandler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpointerhandler LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/clip.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/clip.qml
new file mode 100644
index 0000000000..7bc3907c8c
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/clip.qml
@@ -0,0 +1,36 @@
+import QtQuick
+import Qt.test 1.0
+
+Item {
+ width: 200
+ height: 200
+
+ Rectangle {
+ id: circle
+ y: 0
+ width: 100
+ height: width
+ radius: width/2
+ color: "#3e1"
+ clip: true
+
+ // Rectangle contains() is not affected by its 'radius' property
+ containmentMask: QtObject {
+ property alias radius: circle.radius
+ function contains(point: point) : bool {
+ return (Math.pow(point.x - radius, 2) + Math.pow(point.y - radius, 2)) < Math.pow(radius, 2)
+ }
+ }
+ EventHandler {
+ objectName: "circle eventHandler"
+ }
+ Rectangle {
+ width: circle.width/2
+ height: width
+ color: "red"
+ EventHandler {
+ objectName: "eventHandler"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/grabberSceneChange.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/grabberSceneChange.qml
new file mode 100644
index 0000000000..7bc6028bc2
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/grabberSceneChange.qml
@@ -0,0 +1,78 @@
+import QtQuick
+
+Window {
+ id: root
+ visible: true
+ objectName: "root"
+ width: 320
+ height: 480
+
+ property bool useTimer : false
+ property int grabChangedCounter : 0
+
+ Item {
+ id: back
+ anchors.fill: parent
+
+ Rectangle {
+ id: background
+ anchors.fill: parent
+ color: "blue"
+ }
+
+ Rectangle {
+ id: container
+ objectName: "container"
+ anchors.fill: parent
+ anchors.margins: 50
+ z: 2
+
+ Rectangle {
+ id: likeButton
+ color: "gray"
+ anchors.centerIn: parent
+ width: 200
+ height: 200
+
+ DragHandler {
+ id: handler
+ objectName: "dragHandler"
+ grabPermissions: PointerHandler.CanTakeOverFromItems
+ onGrabChanged: {
+ ++grabChangedCounter
+ }
+ }
+ }
+ }
+
+ Timer {
+ id: reparentTimer
+ running: false
+ interval: 100
+ repeat: false
+ onTriggered: {
+ container.parent = null
+ }
+ }
+
+ Rectangle {
+ id: likeButton2
+ color: "yellow"
+ anchors.centerIn: parent
+ width: 100
+ height: 100
+ z: 3
+
+ MultiPointTouchArea {
+ id: press
+ anchors.fill: parent
+ onPressed: {
+ if (useTimer)
+ reparentTimer.running = true
+ else
+ container.parent = null
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp
index aa89ad0631..1120cb54c2 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -162,6 +162,7 @@ public:
class EventHandler : public QQuickPointerHandler
{
+ Q_OBJECT
public:
EventHandler(QQuickItem *parent = nullptr) :
QQuickPointerHandler(parent) {}
@@ -231,6 +232,9 @@ private slots:
void dynamicCreationInWindow();
void cppConstruction();
void reparenting();
+ void grabberSceneChange_data();
+ void grabberSceneChange();
+ void clip();
protected:
bool eventFilter(QObject *, QEvent *event) override
@@ -749,6 +753,112 @@ void tst_PointerHandlers::reparenting()
}
}
+/*!
+ Verify that removing an item that has a grabbing handler from the scene
+ does not result in crashes in our event dispatching code. The item's window()
+ pointer will be nullptr, so the handler must have released the grab, or never
+ gotten the grab, depending on when the item gets removed.
+
+ See QTBUG-114475.
+*/
+void tst_PointerHandlers::grabberSceneChange_data()
+{
+ QTest::addColumn<bool>("useTimer");
+ QTest::addColumn<int>("grabChangedCount");
+
+ QTest::addRow("Immediately") << false << 0;
+ QTest::addRow("Delayed") << true << 2;
+}
+
+void tst_PointerHandlers::grabberSceneChange()
+{
+ QFETCH(const bool, useTimer);
+ QFETCH(const int, grabChangedCount);
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("grabberSceneChange.qml"));
+ QQuickWindow *window = qobject_cast<QQuickWindow*>(component.create());
+ QScopedPointer<QQuickWindow> cleanup(window);
+ QVERIFY(window);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ window->setProperty("useTimer", useTimer);
+
+ QQuickItem *container = window->findChild<QQuickItem *>("container");
+
+ QPoint p1 = QPoint(window->width() / 2, window->height() / 2);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ // The container gets removed from this window, either immediately on
+ // press, or through a timer.
+ QTRY_COMPARE(container->parentItem(), nullptr);
+
+ QEXPECT_FAIL("Delayed",
+ "PointerHandlers don't release their grab when item is removed", Continue);
+ QCOMPARE(window->property("grabChangedCounter").toInt(), grabChangedCount);
+
+ // this should not crash
+ QTest::mouseMove(window, p1 + QPoint(5, 5));
+}
+
+void tst_PointerHandlers::clip()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "clip.qml");
+ QQuickView * window = windowPtr.data();
+ QVERIFY(window);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ EventHandler *handler = window->contentItem()->findChild<EventHandler*>("eventHandler");
+ EventHandler *circleHandler = window->contentItem()->findChild<EventHandler*>("circle eventHandler");
+
+ QCOMPARE(handler->pressEventCount, 0);
+ QCOMPARE(circleHandler->pressEventCount, 0);
+ QCOMPARE(handler->releaseEventCount, 0);
+ QCOMPARE(circleHandler->releaseEventCount, 0);
+
+ const QPoint rectPt = QPoint(1, 1);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, rectPt);
+ QCOMPARE(handler->pressEventCount, 1);
+ QCOMPARE(circleHandler->pressEventCount, 0);
+
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, rectPt);
+ QCOMPARE(handler->releaseEventCount, 1);
+ QCOMPARE(circleHandler->releaseEventCount, 0);
+
+
+ handler->pressEventCount = 0;
+ circleHandler->pressEventCount = 0;
+ handler->releaseEventCount = 0;
+ circleHandler->releaseEventCount = 0;
+
+ const QPoint rectAndCirclePt = QPoint(49 ,49);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, rectAndCirclePt);
+ QCOMPARE(handler->pressEventCount, 1);
+ QCOMPARE(circleHandler->pressEventCount, 1);
+
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, rectAndCirclePt);
+ QCOMPARE(handler->releaseEventCount, 1);
+ QCOMPARE(circleHandler->releaseEventCount, 1);
+
+
+ handler->pressEventCount = 0;
+ circleHandler->pressEventCount = 0;
+ handler->releaseEventCount = 0;
+ circleHandler->releaseEventCount = 0;
+
+ const QPoint circlePt = QPoint(51 ,51);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, circlePt);
+ QCOMPARE(handler->pressEventCount, 0);
+ QCOMPARE(circleHandler->pressEventCount, 1);
+
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, circlePt);
+ QCOMPARE(handler->releaseEventCount, 0);
+ QCOMPARE(circleHandler->releaseEventCount, 1);
+}
+
QTEST_MAIN(tst_PointerHandlers)
#include "tst_qquickpointerhandler.moc"
diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquickpointhandler/CMakeLists.txt
index 969df8a4ce..aa73218361 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointhandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickpointhandler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpointhandler LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/data/multiPointTracker.qml b/tests/auto/quick/pointerhandlers/qquickpointhandler/data/multiPointTracker.qml
index d813160f44..616d526592 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointhandler/data/multiPointTracker.qml
+++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/data/multiPointTracker.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/data/pointTracker.qml b/tests/auto/quick/pointerhandlers/qquickpointhandler/data/pointTracker.qml
index 54d7ff7212..2de03703e8 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointhandler/data/pointTracker.qml
+++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/data/pointTracker.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp
index 4435580d92..e1641c282e 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -18,6 +18,8 @@
#include <QtQuickTestUtils/private/viewtestutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
+#include <QtCore/qpointer.h>
+
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
class tst_PointHandler : public QQmlDataTest
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST b/tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST
index d13d25390b..1559014480 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST
@@ -1,11 +1,3 @@
-# QTBUG-95939
-[touchGesturePolicyDragThreshold]
-opensuse-leap
-
-# QTBUG-95939
-[mouseGesturePolicyDragThreshold]
-opensuse-leap
-
# QTBUG-103072
[gesturePolicyDragWithinBounds]
android
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt
index cab8fc1a0d..94834e04c6 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicktaphandler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicktaphandler LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
index fa58d76e4a..fc1e623902 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
@@ -10,13 +10,20 @@ Rectangle {
property alias pressed: tap.pressed
property bool checked: false
property alias gesturePolicy: tap.gesturePolicy
+ property alias longPressThreshold: tap.longPressThreshold
property point tappedPosition: Qt.point(0, 0)
+ property real timeHeldWhenTapped: 0
+ property real timeHeldWhenLongPressed: 0
signal tapped
signal canceled
width: label.implicitWidth * 1.5; height: label.implicitHeight * 2.0
border.color: "#9f9d9a"; border.width: 1; radius: height / 4; antialiasing: true
+ function assignUndefinedLongPressThreshold() {
+ tap.longPressThreshold = undefined
+ }
+
gradient: Gradient {
GradientStop { position: 0.0; color: tap.pressed ? "#b8b5b2" : "#efebe7" }
GradientStop { position: 1.0; color: "#b8b5b2" }
@@ -25,14 +32,17 @@ Rectangle {
TapHandler {
id: tap
objectName: label.text
- longPressThreshold: 100 // CI can be insanely slow, so don't demand a timely release to generate onTapped
onSingleTapped: console.log("Single tap")
onDoubleTapped: console.log("Double tap")
- onTapped: {
- console.log("Tapped")
+ onTapped: (eventPoint, button) => {
+ console.log("Tapped", button, eventPoint)
tapFlash.start()
root.tappedPosition = point.scenePosition
root.tapped()
+ root.timeHeldWhenTapped = tap.timeHeld // eventPoint.timeHeld is already 0
+ }
+ onLongPressed: {
+ root.timeHeldWhenLongPressed = tap.timeHeld
}
onCanceled: root.canceled()
}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml
index e3f15f399f..9483a12d1c 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml
index c5f2f6e1ae..b36fcdef08 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml
index 5731f51f38..04fbbc176b 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
@@ -9,19 +9,25 @@ Item {
Button {
objectName: "DragThreshold"
label: "DragThreshold"
- x: 10; y: 10; width: parent.width - 20; height: 40
+ x: 10; y: 10; width: 300; height: 40
gesturePolicy: TapHandler.DragThreshold
}
Button {
objectName: "WithinBounds"
label: "WithinBounds"
- x: 10; y: 60; width: parent.width - 20; height: 40
+ x: 10; y: 60; width: 300; height: 40
gesturePolicy: TapHandler.WithinBounds
}
Button {
objectName: "ReleaseWithinBounds"
label: "ReleaseWithinBounds"
- x: 10; y: 110; width: parent.width - 20; height: 40
+ x: 10; y: 110; width: 300; height: 40
gesturePolicy: TapHandler.ReleaseWithinBounds
}
+ Button {
+ objectName: "DragWithinBounds"
+ label: "DragWithinBounds"
+ x: 10; y: 160; width: 300; height: 40
+ gesturePolicy: TapHandler.DragWithinBounds
+ }
}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/dragReleaseMenu.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/dragReleaseMenu.qml
index 1f819a937f..5f60ef879e 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/dragReleaseMenu.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/dragReleaseMenu.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nested.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nested.qml
index f9db2d7179..c0f0b10bf4 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nested.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nested.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
Item {
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nestedAndSibling.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nestedAndSibling.qml
new file mode 100644
index 0000000000..7732c42082
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nestedAndSibling.qml
@@ -0,0 +1,39 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+import QtQuick.Controls 2.15
+
+Item {
+ width: 360
+ height: 280
+
+ Rectangle {
+ width: 200; height: 200; x: 100; y: 10
+ color: th1.pressed ? "blue" : "lightblue"
+
+ TapHandler {
+ id: th1
+ objectName: "th1"
+ }
+
+ Rectangle {
+ width: 200; height: 200; x: 50; y: 50
+ color: th2.pressed ? "steelblue" : "lightsteelblue"
+
+ TapHandler {
+ id: th2
+ objectName: "th2"
+ }
+ }
+ }
+
+ Rectangle {
+ width: 200; height: 200; x: 10; y: 50
+ color: th3.pressed ? "goldenrod" : "beige"
+
+ TapHandler {
+ id: th3
+ objectName: "th3"
+ }
+ }
+}
+
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml
index 3517afe9c3..85f5c87b39 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml
index 54adc87c54..026be48f83 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
index f000d48171..1dab0836cd 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -44,10 +44,12 @@ private slots:
void touchMultiTap();
void mouseMultiTap_data();
void mouseMultiTap();
+ void mouseMultiTapLeftRight_data();
+ void mouseMultiTapLeftRight();
void singleTapDoubleTap_data();
void singleTapDoubleTap();
- void touchLongPress();
- void mouseLongPress();
+ void longPress_data();
+ void longPress();
void buttonsMultiTouch();
void componentUserBehavioralOverride();
void rightLongPressIgnoreWheel();
@@ -55,6 +57,8 @@ private slots:
void nonTopLevelParentWindow();
void nestedDoubleTap_data();
void nestedDoubleTap();
+ void nestedAndSiblingPropagation_data();
+ void nestedAndSiblingPropagation();
private:
void createView(QScopedPointer<QQuickView> &window, const char *fileName,
@@ -507,6 +511,23 @@ void tst_TapHandler::touchMultiTap()
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!button->property("pressed").toBool());
QCOMPARE(tappedSpy.size(), 4);
+
+ // Test a stray touch begin
+ tappedSpy.clear();
+ constexpr int count = 2;
+ for (int i = 0; i < count; ++i) {
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ p1 -= QPoint(dragThreshold, dragThreshold);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(dragThreshold, dragThreshold);
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ }
+ QCOMPARE(tappedSpy.count(), count);
}
void tst_TapHandler::mouseMultiTap_data()
@@ -592,6 +613,66 @@ void tst_TapHandler::mouseMultiTap()
QCOMPARE(singleTapSpy.size(), expectedSingleTapsAfterWaiting);
}
+void tst_TapHandler::mouseMultiTapLeftRight_data()
+{
+ QTest::addColumn<QQuickTapHandler::ExclusiveSignals>("exclusiveSignals");
+ QTest::addColumn<int>("expectedSingleTaps");
+ QTest::addColumn<int>("expectedDoubleTaps");
+ QTest::addColumn<int>("expectedTabCount2");
+ QTest::addColumn<int>("expectedTabCount3");
+
+ QTest::newRow("NotExclusive") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::NotExclusive)
+ << 3 << 0 << 1 << 1;
+ QTest::newRow("SingleTap") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap)
+ << 3 << 0 << 1 << 1;
+ QTest::newRow("DoubleTap") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::DoubleTap)
+ << 0 << 0 << 1 << 1;
+ QTest::newRow("SingleTap|DoubleTap") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap | QQuickTapHandler::DoubleTap)
+ << 0 << 0 << 1 << 1;
+}
+
+void tst_TapHandler::mouseMultiTapLeftRight() //QTBUG-111557
+{
+ QFETCH(QQuickTapHandler::ExclusiveSignals, exclusiveSignals);
+ QFETCH(int, expectedSingleTaps);
+ QFETCH(int, expectedDoubleTaps);
+ QFETCH(int, expectedTabCount2);
+ QFETCH(int, expectedTabCount3);
+
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttons.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *button = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
+ QVERIFY(button);
+ QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>();
+ QVERIFY(tapHandler);
+ tapHandler->setExclusiveSignals(exclusiveSignals);
+ tapHandler->setAcceptedButtons(Qt::LeftButton | Qt::RightButton);
+ QSignalSpy tappedSpy(button, SIGNAL(tapped()));
+ QSignalSpy singleTapSpy(tapHandler, &QQuickTapHandler::singleTapped);
+ QSignalSpy doubleTapSpy(tapHandler, &QQuickTapHandler::doubleTapped);
+
+ // Click once with the left button
+ QPoint p1 = button->mapToScene(QPointF(2, 2)).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
+
+ // Click again with the right button -> should reset tabCount()
+ QTest::mousePress(window, Qt::RightButton, Qt::NoModifier, p1, 10);
+ QTest::mouseRelease(window, Qt::RightButton, Qt::NoModifier, p1, 10);
+
+ QCOMPARE(tapHandler->tapCount(), expectedTabCount2);
+
+ // Click again with the left button -> should reset tabCount()
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
+
+ QCOMPARE(tapHandler->tapCount(), expectedTabCount3);
+ QCOMPARE(singleTapSpy.size(), expectedSingleTaps);
+ QCOMPARE(doubleTapSpy.size(), expectedDoubleTaps);
+}
+
void tst_TapHandler::singleTapDoubleTap_data()
{
QTest::addColumn<QPointingDevice::DeviceType>("deviceType");
@@ -653,12 +734,13 @@ void tst_TapHandler::singleTapDoubleTap()
QSignalSpy singleTapSpy(tapHandler, &QQuickTapHandler::singleTapped);
QSignalSpy doubleTapSpy(tapHandler, &QQuickTapHandler::doubleTapped);
- auto tap = [window, tapHandler, deviceType, this](const QPoint &p1) {
+ auto tap = [window, tapHandler, deviceType, this](const QPoint &p1, int delay = 10) {
switch (static_cast<QPointingDevice::DeviceType>(deviceType)) {
case QPointingDevice::DeviceType::Mouse:
- QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1, delay);
break;
case QPointingDevice::DeviceType::TouchScreen:
+ QTest::qWait(delay);
QTest::touchEvent(window, touchDevice).press(0, p1, window);
QTRY_VERIFY(tapHandler->isPressed());
QTest::touchEvent(window, touchDevice).release(0, p1, window);
@@ -679,78 +761,211 @@ void tst_TapHandler::singleTapDoubleTap()
QTRY_COMPARE(doubleTapSpy.size(), expectedDoubleTapCount);
QCOMPARE(tappedSpy.size(), 2);
QCOMPARE(singleTapSpy.size(), expectedEndingSingleTapCount);
-}
-void tst_TapHandler::touchLongPress()
-{
- QScopedPointer<QQuickView> windowPtr;
- createView(windowPtr, "buttons.qml");
- QQuickView * window = windowPtr.data();
+ // wait past the double-tap interval, then do it again
+ const auto delay = qApp->styleHints()->mouseDoubleClickInterval() + 10;
+ tappedSpy.clear();
+ singleTapSpy.clear();
+ doubleTapSpy.clear();
- QQuickItem *button = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
- QVERIFY(button);
- QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>("DragThreshold");
- QVERIFY(tapHandler);
- QSignalSpy tappedSpy(button, SIGNAL(tapped()));
- QSignalSpy longPressThresholdChangedSpy(tapHandler, SIGNAL(longPressThresholdChanged()));
- QSignalSpy timeHeldSpy(tapHandler, SIGNAL(timeHeldChanged()));
- QSignalSpy longPressedSpy(tapHandler, SIGNAL(longPressed()));
+ // tap once with delay
+ tap(p1, delay);
+ QCOMPARE(tappedSpy.size(), 1);
+ QCOMPARE(doubleTapSpy.size(), 0);
- // Reduce the threshold so that we can get a long press quickly
- tapHandler->setLongPressThreshold(0.5);
- QCOMPARE(longPressThresholdChangedSpy.size(), 1);
+ // tap again immediately afterwards
+ tap(p1);
+ QTRY_COMPARE(doubleTapSpy.size(), expectedDoubleTapCount);
+ QCOMPARE(tappedSpy.size(), 2);
+ QCOMPARE(singleTapSpy.size(), expectedEndingSingleTapCount);
+}
- // Press and hold
- QPoint p1 = button->mapToScene(button->clipRect().center()).toPoint();
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
- QQuickTouchUtils::flush(window);
- QTRY_VERIFY(button->property("pressed").toBool());
- QTRY_COMPARE(longPressedSpy.size(), 1);
- timeHeldSpy.wait(); // the longer we hold it, the more this will occur
- qDebug() << "held" << tapHandler->timeHeld() << "secs; timeHeld updated" << timeHeldSpy.size() << "times";
- QVERIFY(timeHeldSpy.size() > 0);
- QVERIFY(tapHandler->timeHeld() > 0.4); // Should be > 0.5 but slow CI and timer granularity can interfere
+void tst_TapHandler::longPress_data()
+{
+ QTest::addColumn<const QPointingDevice *>("device");
+ QTest::addColumn<QString>("buttonName");
+ QTest::addColumn<qreal>("longPressThreshold");
+ QTest::addColumn<QPoint>("releaseOffset");
+ QTest::addColumn<bool>("expectLongPress");
+ QTest::addColumn<bool>("expectTapped");
- // Release and verify that tapped was not emitted
- QTest::touchEvent(window, touchDevice).release(1, p1, window);
- QQuickTouchUtils::flush(window);
- QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.size(), 0);
+ const QPointingDevice *constTouchDevice = touchDevice;
+
+ // Reduce the threshold so that we can get a long press quickly (faster in CI)
+ const qreal longPressThreshold = 0.3;
+ QTest::newRow("mouse, lpt longPressThreshold: DragThreshold")
+ << QPointingDevice::primaryPointingDevice() << "DragThreshold"
+ << longPressThreshold << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt longPressThreshold: DragThreshold")
+ << constTouchDevice << "DragThreshold" << longPressThreshold
+ << QPoint(0, 0) << true << false;
+ QTest::newRow("mouse, lpt longPressThreshold: DragThreshold, drag")
+ << QPointingDevice::primaryPointingDevice() << "DragThreshold"
+ << longPressThreshold << QPoint(50, 0) << false << false;
+ QTest::newRow("touch, lpt longPressThreshold: DragThreshold, drag")
+ << constTouchDevice << "DragThreshold"
+ << longPressThreshold << QPoint(50, 0) << false << false;
+
+ QTest::newRow("mouse, lpt longPressThreshold: WithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "WithinBounds"
+ << longPressThreshold << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt longPressThreshold: WithinBounds")
+ << constTouchDevice << "WithinBounds"
+ << longPressThreshold << QPoint(0, 0) << true << false;
+ QTest::newRow("mouse, lpt longPressThreshold: WithinBounds, drag")
+ << QPointingDevice::primaryPointingDevice() << "WithinBounds"
+ << longPressThreshold << QPoint(50, 0) << true << false;
+ QTest::newRow("touch, lpt longPressThreshold: WithinBounds, drag")
+ << constTouchDevice << "WithinBounds"
+ << longPressThreshold << QPoint(50, 0) << true << false;
+ QTest::newRow("mouse, lpt longPressThreshold: WithinBounds, drag out")
+ << QPointingDevice::primaryPointingDevice() << "WithinBounds"
+ << longPressThreshold << QPoint(155, 0) << false << false;
+ QTest::newRow("touch, lpt longPressThreshold: WithinBounds, drag out")
+ << constTouchDevice << "WithinBounds"
+ << longPressThreshold << QPoint(155, 0) << false << false;
+
+ QTest::newRow("mouse, lpt longPressThreshold: ReleaseWithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds"
+ << longPressThreshold << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt longPressThreshold: ReleaseWithinBounds")
+ << constTouchDevice << "ReleaseWithinBounds"
+ << longPressThreshold << QPoint(0, 0) << true << false;
+ QTest::newRow("mouse, lpt longPressThreshold: ReleaseWithinBounds, drag")
+ << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds"
+ << longPressThreshold << QPoint(50, 0) << true << false;
+ QTest::newRow("touch, lpt longPressThreshold: ReleaseWithinBounds, drag")
+ << constTouchDevice << "ReleaseWithinBounds"
+ << longPressThreshold << QPoint(50, 0) << true << false;
+ QTest::newRow("mouse, lpt longPressThreshold: ReleaseWithinBounds, drag out")
+ << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds"
+ << longPressThreshold << QPoint(155, 0) << false << false;
+ QTest::newRow("touch, lpt longPressThreshold: ReleaseWithinBounds, drag out")
+ << constTouchDevice << "ReleaseWithinBounds"
+ << longPressThreshold << QPoint(155, 0) << false << false;
+
+ QTest::newRow("mouse, lpt longPressThreshold: DragWithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "DragWithinBounds"
+ << longPressThreshold << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt longPressThreshold: DragWithinBounds")
+ << constTouchDevice << "DragWithinBounds"
+ << longPressThreshold << QPoint(0, 0) << true << false;
+ QTest::newRow("mouse, lpt longPressThreshold: DragWithinBounds, drag")
+ << QPointingDevice::primaryPointingDevice() << "DragWithinBounds"
+ << longPressThreshold << QPoint(50, 0) << true << false;
+ QTest::newRow("touch, lpt longPressThreshold: DragWithinBounds, drag")
+ << constTouchDevice << "DragWithinBounds"
+ << longPressThreshold << QPoint(50, 0) << true << false;
+ QTest::newRow("mouse, lpt longPressThreshold: DragWithinBounds, drag out")
+ << QPointingDevice::primaryPointingDevice() << "DragWithinBounds"
+ << longPressThreshold << QPoint(155, 0) << false << false;
+ QTest::newRow("touch, lpt longPressThreshold: DragWithinBounds, drag out")
+ << constTouchDevice << "DragWithinBounds"
+ << longPressThreshold << QPoint(155, 0) << false << false;
+
+ // Zero or negative threshold means long press is disabled
+ QTest::newRow("mouse, lpt 0: DragThreshold")
+ << QPointingDevice::primaryPointingDevice() << "DragThreshold"
+ << qreal(0) << QPoint(0, 0) << false << true;
+ QTest::newRow("mouse, lpt -1: DragThreshold")
+ << QPointingDevice::primaryPointingDevice() << "DragThreshold"
+ << qreal(-1) << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt 0: DragThreshold")
+ << constTouchDevice << "DragThreshold"
+ << qreal(0) << QPoint(0, 0) << false << true;
+
+ QTest::newRow("mouse, lpt 0: WithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "WithinBounds"
+ << qreal(0) << QPoint(0, 0) << false << true;
+ QTest::newRow("mouse, lpt -1: WithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "WithinBounds"
+ << qreal(-1) << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt 0: WithinBounds")
+ << constTouchDevice << "WithinBounds"
+ << qreal(0) << QPoint(0, 0) << false << true;
+
+ QTest::newRow("mouse, lpt 0: ReleaseWithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds"
+ << qreal(0) << QPoint(0, 0) << false << true;
+ QTest::newRow("mouse, lpt -1: ReleaseWithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds"
+ << qreal(-1) << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt 0: ReleaseWithinBounds")
+ << constTouchDevice << "ReleaseWithinBounds"
+ << qreal(0) << QPoint(0, 0) << false << true;
+
+ QTest::newRow("mouse, lpt 0: DragWithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "DragWithinBounds"
+ << qreal(0) << QPoint(0, 0) << false << true;
+ QTest::newRow("mouse, lpt -1: DragWithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "DragWithinBounds"
+ << qreal(-1) << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt 0: DragWithinBounds")
+ << constTouchDevice << "DragWithinBounds"
+ << qreal(0) << QPoint(0, 0) << false << true;
}
-void tst_TapHandler::mouseLongPress()
+void tst_TapHandler::longPress()
{
- QScopedPointer<QQuickView> windowPtr;
- createView(windowPtr, "buttons.qml");
- QQuickView * window = windowPtr.data();
+ QFETCH(const QPointingDevice *, device);
+ QFETCH(QString, buttonName);
+ QFETCH(qreal, longPressThreshold);
+ QFETCH(QPoint, releaseOffset);
+ QFETCH(bool, expectLongPress);
+ QFETCH(bool, expectTapped);
- QQuickItem *button = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("buttons.qml")));
+
+ QQuickItem *button = window.rootObject()->findChild<QQuickItem*>(buttonName);
QVERIFY(button);
- QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>("DragThreshold");
+ QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>(buttonName);
QVERIFY(tapHandler);
QSignalSpy tappedSpy(button, SIGNAL(tapped()));
QSignalSpy longPressThresholdChangedSpy(tapHandler, SIGNAL(longPressThresholdChanged()));
QSignalSpy timeHeldSpy(tapHandler, SIGNAL(timeHeldChanged()));
QSignalSpy longPressedSpy(tapHandler, SIGNAL(longPressed()));
- // Reduce the threshold so that we can get a long press quickly
- tapHandler->setLongPressThreshold(0.5);
- QCOMPARE(longPressThresholdChangedSpy.size(), 1);
+ const qreal defaultThreshold = tapHandler->longPressThreshold();
+ qsizetype changedCount = 0;
+ QCOMPARE_GT(defaultThreshold, 0);
+ tapHandler->setLongPressThreshold(longPressThreshold);
+ if (longPressThreshold > 0)
+ QCOMPARE(longPressThresholdChangedSpy.size(), ++changedCount);
+ QVERIFY(QMetaObject::invokeMethod(button, "assignUndefinedLongPressThreshold"));
+ if (longPressThreshold > 0)
+ QCOMPARE(longPressThresholdChangedSpy.size(), ++changedCount);
+ QCOMPARE(tapHandler->longPressThreshold(), defaultThreshold);
+ tapHandler->setLongPressThreshold(longPressThreshold);
// Press and hold
QPoint p1 = button->mapToScene(button->clipRect().center()).toPoint();
- QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QQuickTest::pointerPress(device, &window, 1, p1);
QTRY_VERIFY(button->property("pressed").toBool());
- QTRY_COMPARE(longPressedSpy.size(), 1);
+ QTRY_COMPARE(longPressedSpy.size(), expectLongPress ? 1 : 0);
timeHeldSpy.wait(); // the longer we hold it, the more this will occur
qDebug() << "held" << tapHandler->timeHeld() << "secs; timeHeld updated" << timeHeldSpy.size() << "times";
- QVERIFY(timeHeldSpy.size() > 0);
- QVERIFY(tapHandler->timeHeld() > 0.4); // Should be > 0.5 but slow CI and timer granularity can interfere
+ QCOMPARE_GT(timeHeldSpy.size(), 0);
+ if (expectLongPress) {
+ // Should be > longPressThreshold but slow CI and timer granularity can interfere
+ QCOMPARE_GT(tapHandler->timeHeld(), longPressThreshold - 0.1);
+ } else {
+ // Should be quite small, but event delivery is not instantaneous
+ QCOMPARE_LT(tapHandler->timeHeld(), 0.3);
+ }
+
+ // If we have an offset, we need a move between press and release for realistic simulation
+ if (!releaseOffset.isNull())
+ QQuickTest::pointerMove(device, &window, 1, p1 + releaseOffset);
- // Release and verify that tapped was not emitted
- QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1, 500);
+ // Release (optionally at an offset) and check whether tapped was emitted
+ QQuickTest::pointerRelease(device, &window, 1, p1 + releaseOffset);
QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.size(), 0);
+ if (expectLongPress)
+ QCOMPARE_GT(button->property("timeHeldWhenLongPressed").toReal(), longPressThreshold - 0.1);
+ QCOMPARE(tapHandler->timeHeld(), -1);
+ QCOMPARE(tappedSpy.size(), expectTapped ? 1 : 0);
+ QCOMPARE(longPressedSpy.size(), expectLongPress ? 1 : 0);
}
void tst_TapHandler::buttonsMultiTouch()
@@ -866,8 +1081,8 @@ void tst_TapHandler::componentUserBehavioralOverride()
QQuickTapHandler *userTapHandler = button->findChild<QQuickTapHandler*>("override");
QVERIFY(userTapHandler);
QSignalSpy tappedSpy(button, SIGNAL(tapped()));
- QSignalSpy innerGrabChangedSpy(innerTapHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition, QEventPoint)));
- QSignalSpy userGrabChangedSpy(userTapHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition, QEventPoint)));
+ QSignalSpy innerGrabChangedSpy(innerTapHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition,QEventPoint)));
+ QSignalSpy userGrabChangedSpy(userTapHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition,QEventPoint)));
QSignalSpy innerPressedChangedSpy(innerTapHandler, SIGNAL(pressedChanged()));
QSignalSpy userPressedChangedSpy(userTapHandler, SIGNAL(pressedChanged()));
@@ -1019,6 +1234,61 @@ void tst_TapHandler::nestedDoubleTap() // QTBUG-102625
childGesturePolicy == QQuickTapHandler::GesturePolicy::DragThreshold ? 4 : 2);
}
+void tst_TapHandler::nestedAndSiblingPropagation_data()
+{
+ QTest::addColumn<const QPointingDevice *>("device");
+ QTest::addColumn<QQuickTapHandler::GesturePolicy>("gesturePolicy");
+ QTest::addColumn<bool>("expectPropagation");
+
+ const QPointingDevice *constTouchDevice = touchDevice;
+
+ QTest::newRow("primary, DragThreshold") << QPointingDevice::primaryPointingDevice()
+ << QQuickTapHandler::GesturePolicy::DragThreshold << true;
+ QTest::newRow("primary, WithinBounds") << QPointingDevice::primaryPointingDevice()
+ << QQuickTapHandler::GesturePolicy::WithinBounds << false;
+ QTest::newRow("primary, ReleaseWithinBounds") << QPointingDevice::primaryPointingDevice()
+ << QQuickTapHandler::GesturePolicy::ReleaseWithinBounds << false;
+ QTest::newRow("primary, DragWithinBounds") << QPointingDevice::primaryPointingDevice()
+ << QQuickTapHandler::GesturePolicy::DragWithinBounds << false;
+
+ QTest::newRow("touch, DragThreshold") << constTouchDevice
+ << QQuickTapHandler::GesturePolicy::DragThreshold << true;
+ QTest::newRow("touch, WithinBounds") << constTouchDevice
+ << QQuickTapHandler::GesturePolicy::WithinBounds << false;
+ QTest::newRow("touch, ReleaseWithinBounds") << constTouchDevice
+ << QQuickTapHandler::GesturePolicy::ReleaseWithinBounds << false;
+ QTest::newRow("touch, DragWithinBounds") << constTouchDevice
+ << QQuickTapHandler::GesturePolicy::DragWithinBounds << false;
+}
+
+void tst_TapHandler::nestedAndSiblingPropagation() // QTBUG-117387
+{
+ QFETCH(const QPointingDevice *, device);
+ QFETCH(QQuickTapHandler::GesturePolicy, gesturePolicy);
+ QFETCH(bool, expectPropagation);
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("nestedAndSibling.qml")));
+ QQuickItem *root = window.rootObject();
+ QQuickTapHandler *th1 = root->findChild<QQuickTapHandler*>("th1");
+ QVERIFY(th1);
+ th1->setGesturePolicy(gesturePolicy);
+ QQuickTapHandler *th2 = root->findChild<QQuickTapHandler*>("th2");
+ QVERIFY(th2);
+ th2->setGesturePolicy(gesturePolicy);
+ QQuickTapHandler *th3 = root->findChild<QQuickTapHandler*>("th3");
+ QVERIFY(th3);
+ th3->setGesturePolicy(gesturePolicy);
+
+ QPoint middle(180, 140);
+ QQuickTest::pointerPress(device, &window, 0, middle);
+ QVERIFY(th3->isPressed()); // it's on top
+ QCOMPARE(th2->isPressed(), expectPropagation);
+ QCOMPARE(th1->isPressed(), expectPropagation);
+
+ QQuickTest::pointerRelease(device, &window, 0, middle);
+}
+
QTEST_MAIN(tst_TapHandler)
#include "tst_qquicktaphandler.moc"
diff --git a/tests/auto/quick/pointerhandlers/qquickwheelhandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquickwheelhandler/CMakeLists.txt
index b5cfe1fa5a..d50181dfe4 100644
--- a/tests/auto/quick/pointerhandlers/qquickwheelhandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquickwheelhandler/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickwheelhandler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickwheelhandler LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/nested.qml b/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/nested.qml
index d50f6ac005..9c43df46da 100644
--- a/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/nested.qml
+++ b/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/nested.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.14
diff --git a/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/rectWheel.qml b/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/rectWheel.qml
index c0c5e776e9..ca6053ebcf 100644
--- a/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/rectWheel.qml
+++ b/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/rectWheel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.14
@@ -14,7 +14,23 @@ Rectangle {
}
}
+ Rectangle {
+ color: "red"
+ width: 6; height: 6; radius: 3
+ x: wheelHandler.point.position.x - radius
+ y: wheelHandler.point.position.y - radius
+ }
+
+ Text {
+ anchors.centerIn: parent
+ anchors.verticalCenterOffset: 20
+ color: "white"
+ font.pixelSize: 18
+ text: parent.x.toFixed(2) + ", " + parent.y.toFixed(2)
+ }
+
WheelHandler {
+ id: wheelHandler
activeTimeout: 0.5
}
}
diff --git a/tests/auto/quick/pointerhandlers/qquickwheelhandler/tst_qquickwheelhandler.cpp b/tests/auto/quick/pointerhandlers/qquickwheelhandler/tst_qquickwheelhandler.cpp
index d87acc3200..c88b1af2ea 100644
--- a/tests/auto/quick/pointerhandlers/qquickwheelhandler/tst_qquickwheelhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickwheelhandler/tst_qquickwheelhandler.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
diff --git a/tests/auto/quick/propertyrequirements/CMakeLists.txt b/tests/auto/quick/propertyrequirements/CMakeLists.txt
index 0685170946..cab8e3904c 100644
--- a/tests/auto/quick/propertyrequirements/CMakeLists.txt
+++ b/tests/auto/quick/propertyrequirements/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_propertyrequirements Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_propertyrequirements LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_propertyrequirements
SOURCES
tst_propertyrequirements.cpp
diff --git a/tests/auto/quick/propertyrequirements/tst_propertyrequirements.cpp b/tests/auto/quick/propertyrequirements/tst_propertyrequirements.cpp
index b8de922777..c8efaab4b1 100644
--- a/tests/auto/quick/propertyrequirements/tst_propertyrequirements.cpp
+++ b/tests/auto/quick/propertyrequirements/tst_propertyrequirements.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Kevin Krammer <kevin.krammer@kdab.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlengine.h>
@@ -67,8 +67,9 @@ void tst_PropertyRequirements::constantOrNotifyableMain()
}
messages.sort();
- qWarning() << "\nThe following QML Types have properties which are neither CONSTANT nor NOTIFYable:\n"
- << qPrintable(messages.join("\n"));
+ qWarning() << "\nThe following QML Types have properties which are"
+ << "neither CONSTANT nor NOTIFYable nor BINDABLE:\n"
+ << qPrintable(messages.join("\n"));
// TODO enable once technical debt is fixes
// QCOMPARE(failuresByProperty.count(), 0);
@@ -94,7 +95,9 @@ void tst_PropertyRequirements::constantOrNotifyableFull()
}
- static const QString messagePattern("\nProperty %1 neither CONSTANT nor NOTIFYable. Affected types:\n\t%2");
+ static const QLatin1String messagePattern(
+ "\nProperty %1 neither CONSTANT nor NOTIFYable nor BINDABLE. "
+ "Affected types:\n\t%2");
QStringList occurrencesList = occurrences.values();
occurrencesList.sort();
messages.append(messagePattern.arg(it.key(), occurrencesList.join("\n\t")));
@@ -165,7 +168,7 @@ void tst_PropertyRequirements::testQmlType(TestDepth testDepth, const QQmlType &
const QMetaProperty property = metaClass->property(idx);
// needs to be either CONSTANT or have a NOTIFY signal
- if (!property.isConstant() && !property.hasNotifySignal()) {
+ if (!property.isConstant() && !property.hasNotifySignal() && !property.isBindable()) {
static const QString fullNamePattern("%1::%2");
const QString fullPropertyName = fullNamePattern.arg(metaClass->className(), property.name());
diff --git a/tests/auto/quick/qquickaccessible/CMakeLists.txt b/tests/auto/quick/qquickaccessible/CMakeLists.txt
index ddf890d1dc..517e910f73 100644
--- a/tests/auto/quick/qquickaccessible/CMakeLists.txt
+++ b/tests/auto/quick/qquickaccessible/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickaccessible Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickaccessible LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickaccessible/data/hittest.qml b/tests/auto/quick/qquickaccessible/data/hittest.qml
index 825f454b2c..09d60d8f07 100644
--- a/tests/auto/quick/qquickaccessible/data/hittest.qml
+++ b/tests/auto/quick/qquickaccessible/data/hittest.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickaccessible/data/ignored.qml b/tests/auto/quick/qquickaccessible/data/ignored.qml
index a4218cc627..150a2bd8ef 100644
--- a/tests/auto/quick/qquickaccessible/data/ignored.qml
+++ b/tests/auto/quick/qquickaccessible/data/ignored.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
index e7da38a5ce..d2a9ea9997 100644
--- a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
+++ b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -19,6 +19,7 @@
#include <QtQuick/private/qquickaccessibleattached_p.h>
#include <QtQuick/private/qquicklistview_p.h>
#include <QtQuick/private/qquicktext_p.h>
+#include <QtQuick/private/qquicktextinput_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
@@ -56,10 +57,13 @@ private slots:
void commonTests();
void quickAttachedProperties();
+ void attachedWins();
void basicPropertiesTest();
void hitTest();
void checkableTest();
void ignoredTest();
+ void passwordTest();
+ void announceTest();
};
tst_QQuickAccessible::tst_QQuickAccessible()
@@ -158,7 +162,7 @@ void tst_QQuickAccessible::quickAttachedProperties()
// Attaching to non-item
{
QObject parent;
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML QtObject: Accessible must be attached to an Item");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML QtObject: Accessible must be attached to an Item or an Action");
QQuickAccessibleAttached *attachedObj = new QQuickAccessibleAttached(&parent);
QCOMPARE(attachedObj->ignored(), false);
@@ -322,6 +326,31 @@ void tst_QQuickAccessible::quickAttachedProperties()
QTestAccessibility::clearEvents();
}
+// Verify that a role can be explicitly set, and that the values from the
+// attached object are used even if the item has a default role - QTBUG-110114
+void tst_QQuickAccessible::attachedWins()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(R"(
+ import QtQuick
+ import QtQuick.Controls
+ Button {
+ text: "Button"
+ objectName: "button"
+ Accessible.role: Accessible.RadioButton
+ Accessible.description: "Radio Button"
+ })", QUrl());
+ auto button = std::unique_ptr<QObject>(component.create());
+ QVERIFY(button);
+
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(button.get());
+ QVERIFY(iface);
+
+ QCOMPARE(iface->role(), QAccessible::RadioButton);
+ QTestAccessibility::clearEvents();
+}
+
void tst_QQuickAccessible::basicPropertiesTest()
{
@@ -643,6 +672,53 @@ void tst_QQuickAccessible::ignoredTest()
QTestAccessibility::clearEvents();
}
+void tst_QQuickAccessible::passwordTest()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick\nTextInput {\n"
+ "Accessible.role: Accessible.EditableText\n"
+ "Accessible.name: \"Password\"\n"
+ "Accessible.passwordEdit: true\n"
+ "echoMode: TextInput.Password\n"
+ "text: \"Green\"\n"
+ "}", QUrl());
+ auto object = std::unique_ptr<QObject>(component.create());
+ QVERIFY(object != nullptr);
+
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput *>(object.get());
+ QVERIFY(textInput != nullptr);
+
+ const auto passwordCharacter = textInput->passwordCharacter();
+ const auto passwordLength = textInput->text().length();
+ const auto password = passwordCharacter.repeated(passwordLength);
+
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(object.get());
+ QVERIFY(iface);
+ QCOMPARE(iface->text(QAccessible::Value), password);
+
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QQuickAccessible::announceTest()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick\nItem {\n"
+ "Component.onCompleted: Accessible.announce('I am complete!')"
+ "}",
+ QUrl());
+ auto object = std::unique_ptr<QObject>(component.create());
+ QVERIFY(object != nullptr);
+
+ QAccessibleEvent createdEvent(object.get(), QAccessible::ObjectCreated);
+ QVERIFY_EVENT(&createdEvent);
+ QAccessibleAnnouncementEvent event(object.get(), QStringLiteral("I am complete!"));
+ QVERIFY_EVENT(&event);
+
+ QTestAccessibility::clearEvents();
+}
+
QTEST_MAIN(tst_QQuickAccessible)
#include "tst_qquickaccessible.moc"
diff --git a/tests/auto/quick/qquickanchors/CMakeLists.txt b/tests/auto/quick/qquickanchors/CMakeLists.txt
index af46206a7c..9bc4d5203b 100644
--- a/tests/auto/quick/qquickanchors/CMakeLists.txt
+++ b/tests/auto/quick/qquickanchors/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickanchors Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickanchors LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickanchors/data/centerin.qml b/tests/auto/quick/qquickanchors/data/centerin.qml
index b880219f0f..94c344b4e8 100644
--- a/tests/auto/quick/qquickanchors/data/centerin.qml
+++ b/tests/auto/quick/qquickanchors/data/centerin.qml
@@ -22,4 +22,11 @@ Rectangle {
anchors.centerIn: parent;
anchors.alignWhenCentered: false
}
+
+ Rectangle {
+ objectName: "centered4"
+ width: 0.9; height: 0.9; color: "plum"
+ anchors.centerIn: parent;
+ anchors.alignWhenCentered: false
+ }
}
diff --git a/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp b/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp
index 7dd3eaece0..508a3906fc 100644
--- a/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp
+++ b/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <QSignalSpy>
#include <private/qquickitem_p.h>
@@ -143,15 +144,16 @@ void tst_qquickanchors::basicAnchorsRTL()
qApp->processEvents();
QQuickItem* rootItem = qobject_cast<QQuickItem*>(view->rootObject());
- foreach (QObject *child, rootItem->children()) {
+ const QObjectList children = rootItem->children();
+ for (QObject *child : children) {
bool mirrored = QQuickItemPrivate::get(qobject_cast<QQuickItem*>(child))->anchors()->mirrored();
QCOMPARE(mirrored, false);
}
- foreach (QObject *child, rootItem->children())
+ for (QObject *child : children)
mirrorAnchors(qobject_cast<QQuickItem*>(child));
- foreach (QObject *child, rootItem->children()) {
+ for (QObject *child : children) {
bool mirrored = QQuickItemPrivate::get(qobject_cast<QQuickItem*>(child))->anchors()->mirrored();
QCOMPARE(mirrored, true);
}
@@ -273,7 +275,8 @@ void tst_qquickanchors::illegalSets_data()
<< "Rectangle { id: rect; Rectangle { anchors.left: rect.left; anchors.right: rect.right; anchors.horizontalCenter: rect.horizontalCenter } }"
<< "<Unknown File>:2:23: QML Rectangle: Cannot specify left, right, and horizontalCenter anchors at the same time.";
- foreach (const QString &side, QStringList() << "left" << "right") {
+ const QStringList leftRight = {"left", "right"};
+ for (const QString &side : leftRight) {
QTest::newRow("H - anchor to V")
<< QString("Rectangle { Rectangle { anchors.%1: parent.top } }").arg(side)
<< "<Unknown File>:2:13: QML Rectangle: Cannot anchor a horizontal edge to a vertical edge.";
@@ -296,7 +299,8 @@ void tst_qquickanchors::illegalSets_data()
<< "Rectangle { Text { id: text1; text: \"Hello\" } Text { anchors.baseline: text1.baseline; anchors.top: text1.top; } }"
<< "<Unknown File>:2:47: QML Text: Baseline anchor cannot be used in conjunction with top, bottom, or verticalCenter anchors.";
- foreach (const QString &side, QStringList() << "top" << "bottom" << "baseline") {
+ const QStringList topBottomBaseline = {"top", "bottom", "baseline"};
+ for (const QString &side : topBottomBaseline) {
QTest::newRow("V - anchor to H")
<< QString("Rectangle { Rectangle { anchors.%1: parent.left } }").arg(side)
@@ -516,6 +520,15 @@ void tst_qquickanchors::centerIn()
QCOMPARE(rect3->x(), 94.5);
QCOMPARE(rect3->y(), 94.5);
+ //QTBUG-95224 (fractional positions are not center-rounded correctly)
+ // The center anchor lines on the parent will be rounded from 41.2 / 2 == 20.6 to 21
+ // rect4 has anchors.alignWhenCentered: false, so no rounding will be done on that items position.
+ // As a result, the expected position of rect4 will be 21 - 0.9/2 = 20.55
+ QQuickRectangle* rect4 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("centered4"));
+ view->rootObject()->setWidth(41.2);
+ view->rootObject()->setHeight(41.2);
+ QCOMPARE(rect4->x(), 20.55);
+ QCOMPARE(rect4->y(), 20.55);
delete view;
}
diff --git a/tests/auto/quick/qquickanimatedimage/CMakeLists.txt b/tests/auto/quick/qquickanimatedimage/CMakeLists.txt
index 2d58301f15..109e84cc14 100644
--- a/tests/auto/quick/qquickanimatedimage/CMakeLists.txt
+++ b/tests/auto/quick/qquickanimatedimage/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickanimatedimage Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickanimatedimage LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickanimatedimage/data/currentframe.qml b/tests/auto/quick/qquickanimatedimage/data/currentframe.qml
index b679da2a99..3c58bdaa4b 100644
--- a/tests/auto/quick/qquickanimatedimage/data/currentframe.qml
+++ b/tests/auto/quick/qquickanimatedimage/data/currentframe.qml
@@ -4,6 +4,7 @@ AnimatedImage {
property int currentFrameChangeCount: 0
property int frameChangeCount: 0
source: "stickman.gif"
+ paused: true
onCurrentFrameChanged: if (currentFrame > 0) ++currentFrameChangeCount;
onFrameChanged: if (currentFrame > 0) ++frameChangeCount;
function scriptedSetCurrentFrame(frame) {
diff --git a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
index cb81ec8a07..efea42de34 100644
--- a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
+++ b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlexpression.h>
@@ -62,6 +62,7 @@ private slots:
void noCaching();
void sourceChangesOnFrameChanged();
void currentFrame();
+ void qtbug_120555();
};
void tst_qquickanimatedimage::cleanup()
@@ -646,6 +647,36 @@ void tst_qquickanimatedimage::currentFrame()
QCOMPARE(anim->property("frameChangeCount"), 2);
}
+void tst_qquickanimatedimage::qtbug_120555()
+{
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ server.serveDirectory(dataDirectory());
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\nAnimatedImage {}", {});
+
+ QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage*>(component.create());
+ QVERIFY(anim);
+
+ anim->setSource(server.url("/stickman.gif"));
+ QTRY_COMPARE(anim->status(), QQuickImage::Loading);
+
+ anim->setFillMode(QQuickImage::PreserveAspectFit);
+ QCOMPARE(anim->fillMode(), QQuickImage::PreserveAspectFit);
+ anim->setMipmap(true);
+ QCOMPARE(anim->mipmap(), true);
+ anim->setCache(false);
+ QCOMPARE(anim->cache(), false);
+ anim->setSourceSize(QSize(200, 200));
+ QCOMPARE(anim->sourceSize(), QSize(200, 200));
+
+ QTRY_COMPARE(anim->status(), QQuickImage::Ready);
+
+ delete anim;
+}
+
QTEST_MAIN(tst_qquickanimatedimage)
#include "tst_qquickanimatedimage.moc"
diff --git a/tests/auto/quick/qquickanimatedsprite/CMakeLists.txt b/tests/auto/quick/qquickanimatedsprite/CMakeLists.txt
index bb789eab09..36117df988 100644
--- a/tests/auto/quick/qquickanimatedsprite/CMakeLists.txt
+++ b/tests/auto/quick/qquickanimatedsprite/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickanimatedsprite Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickanimatedsprite LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickanimatedsprite/data/basic.qml b/tests/auto/quick/qquickanimatedsprite/data/basic.qml
index 2985db31ec..a6564a8983 100644
--- a/tests/auto/quick/qquickanimatedsprite/data/basic.qml
+++ b/tests/auto/quick/qquickanimatedsprite/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickanimatedsprite/data/frameChange.qml b/tests/auto/quick/qquickanimatedsprite/data/frameChange.qml
index e5cbcb98d3..dbbbc222b3 100644
--- a/tests/auto/quick/qquickanimatedsprite/data/frameChange.qml
+++ b/tests/auto/quick/qquickanimatedsprite/data/frameChange.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickanimatedsprite/data/infiniteLoops.qml b/tests/auto/quick/qquickanimatedsprite/data/infiniteLoops.qml
index 3e02ad2648..2771716774 100644
--- a/tests/auto/quick/qquickanimatedsprite/data/infiniteLoops.qml
+++ b/tests/auto/quick/qquickanimatedsprite/data/infiniteLoops.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickanimatedsprite/data/largeAnimation.qml b/tests/auto/quick/qquickanimatedsprite/data/largeAnimation.qml
index 6618b45ae0..bfff9c9d29 100644
--- a/tests/auto/quick/qquickanimatedsprite/data/largeAnimation.qml
+++ b/tests/auto/quick/qquickanimatedsprite/data/largeAnimation.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickanimatedsprite/data/runningChange.qml b/tests/auto/quick/qquickanimatedsprite/data/runningChange.qml
index ba64269eb7..7c746cae91 100644
--- a/tests/auto/quick/qquickanimatedsprite/data/runningChange.qml
+++ b/tests/auto/quick/qquickanimatedsprite/data/runningChange.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Tasuku Suzuki <stasuku@gmail.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickanimatedsprite/data/sourceSwitch.qml b/tests/auto/quick/qquickanimatedsprite/data/sourceSwitch.qml
index 3ba335b152..319579d2e1 100644
--- a/tests/auto/quick/qquickanimatedsprite/data/sourceSwitch.qml
+++ b/tests/auto/quick/qquickanimatedsprite/data/sourceSwitch.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
diff --git a/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp b/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
index 72c807bdf8..f7ed660f88 100644
--- a/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
+++ b/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuick/qquickview.h>
diff --git a/tests/auto/quick/qquickanimationcontroller/CMakeLists.txt b/tests/auto/quick/qquickanimationcontroller/CMakeLists.txt
index 42c219afea..44c3e4d797 100644
--- a/tests/auto/quick/qquickanimationcontroller/CMakeLists.txt
+++ b/tests/auto/quick/qquickanimationcontroller/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickanimationcontroller Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickanimationcontroller LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickanimationcontroller/tst_qquickanimationcontroller.cpp b/tests/auto/quick/qquickanimationcontroller/tst_qquickanimationcontroller.cpp
index b231f121e6..41b3ae2ac7 100644
--- a/tests/auto/quick/qquickanimationcontroller/tst_qquickanimationcontroller.cpp
+++ b/tests/auto/quick/qquickanimationcontroller/tst_qquickanimationcontroller.cpp
@@ -1,4 +1,4 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
QUICK_TEST_MAIN(qquickanimationcontroller)
diff --git a/tests/auto/quick/qquickanimations/CMakeLists.txt b/tests/auto/quick/qquickanimations/CMakeLists.txt
index 5e7623afd1..1b6b0b84a5 100644
--- a/tests/auto/quick/qquickanimations/CMakeLists.txt
+++ b/tests/auto/quick/qquickanimations/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickanimations Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickanimations LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickanimations/data/animationJobSelfDestructionBug.qml b/tests/auto/quick/qquickanimations/data/animationJobSelfDestructionBug.qml
index 93fc498613..a9123427d5 100644
--- a/tests/auto/quick/qquickanimations/data/animationJobSelfDestructionBug.qml
+++ b/tests/auto/quick/qquickanimations/data/animationJobSelfDestructionBug.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.11
import QtQuick.Window 2.11
diff --git a/tests/auto/quick/qquickanimations/data/animatorInvalidTargetCrash.qml b/tests/auto/quick/qquickanimations/data/animatorInvalidTargetCrash.qml
index c575ce33ab..c69dc2a065 100644
--- a/tests/auto/quick/qquickanimations/data/animatorInvalidTargetCrash.qml
+++ b/tests/auto/quick/qquickanimations/data/animatorInvalidTargetCrash.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.3
import QtQuick.Window 2.2
diff --git a/tests/auto/quick/qquickanimations/data/changePropertiesDuringAnimation.qml b/tests/auto/quick/qquickanimations/data/changePropertiesDuringAnimation.qml
index c82fe4bb52..322bd9c0e4 100644
--- a/tests/auto/quick/qquickanimations/data/changePropertiesDuringAnimation.qml
+++ b/tests/auto/quick/qquickanimations/data/changePropertiesDuringAnimation.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window 2.2
diff --git a/tests/auto/quick/qquickanimations/data/fastFlickingBug.qml b/tests/auto/quick/qquickanimations/data/fastFlickingBug.qml
index 68bb618aca..1c653f59d2 100644
--- a/tests/auto/quick/qquickanimations/data/fastFlickingBug.qml
+++ b/tests/auto/quick/qquickanimations/data/fastFlickingBug.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.11
import QtQuick.Window 2.11
diff --git a/tests/auto/quick/qquickanimations/data/finished.qml b/tests/auto/quick/qquickanimations/data/finished.qml
index f5b19b037e..ba74a77ce4 100644
--- a/tests/auto/quick/qquickanimations/data/finished.qml
+++ b/tests/auto/quick/qquickanimations/data/finished.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/qquickanimations/data/frameAnimation.qml b/tests/auto/quick/qquickanimations/data/frameAnimation.qml
index 2b0cd7f3a7..6ed305db60 100644
--- a/tests/auto/quick/qquickanimations/data/frameAnimation.qml
+++ b/tests/auto/quick/qquickanimations/data/frameAnimation.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/qquickanimations/data/infiniteAnimationWithoutFrom.qml b/tests/auto/quick/qquickanimations/data/infiniteAnimationWithoutFrom.qml
index 6ae45ce9d9..21051e030e 100644
--- a/tests/auto/quick/qquickanimations/data/infiniteAnimationWithoutFrom.qml
+++ b/tests/auto/quick/qquickanimations/data/infiniteAnimationWithoutFrom.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickanimations/data/restartAnimationGroupWhenDirty.qml b/tests/auto/quick/qquickanimations/data/restartAnimationGroupWhenDirty.qml
new file mode 100644
index 0000000000..aec1cec432
--- /dev/null
+++ b/tests/auto/quick/qquickanimations/data/restartAnimationGroupWhenDirty.qml
@@ -0,0 +1,92 @@
+import QtQuick
+
+Rectangle {
+ width: 300
+ height: 300
+
+ // test SequentialAnimation
+ Rectangle {
+ id: line0
+ y: 100
+ width: parent.width
+ height: 2
+ color: "blue"
+ }
+ Rectangle {
+ id: target0
+ objectName: "target0"
+ y: 100
+ anchors.verticalCenter: line0.verticalCenter
+ height: line0.height * 5
+ width: height
+ color: "red"
+ radius: height/2
+
+ property bool onFinishedCalled : false;
+
+ SequentialAnimation {
+ id: seqAnim0
+ objectName: "seqAnim0"
+ loops: 2
+ running: true
+ NumberAnimation {
+ id: anim0
+ target: target0
+ property: "x"
+ from: 0
+ to: 50
+ duration: 500
+ }
+ Component.onCompleted: anim0.to = 290
+ onFinished: target0.onFinishedCalled = true
+ }
+ }
+
+ // test ParallelAnimation
+ Rectangle {
+ id: line1
+ y: 200
+ width: parent.width
+ height: 2
+ color: "blue"
+ }
+ Rectangle {
+ id: target1
+ objectName: "target1"
+ anchors.verticalCenter: line1.verticalCenter
+ height: line1.height * 5
+ width: height
+ color: "yellow"
+ radius: height/2
+
+ property bool onFinishedCalled : false;
+
+ ParallelAnimation {
+ id: parAnim0
+ objectName: "parAnim0"
+ loops: 2
+ running: true
+ NumberAnimation {
+ id: anim1
+ target: target1
+ property: "x"
+ from: 0
+ to: 50
+ duration: 500
+ }
+ Component.onCompleted: anim1.to = 290
+ onFinished: target1.onFinishedCalled = true
+ }
+ }
+
+ Timer {
+ interval: 400
+ running: true
+ onTriggered: {
+ seqAnim0.pause()
+ parAnim0.pause()
+ anim0.to = 140
+ anim1.to = 140
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimations/data/restartNestedAnimationGroupWhenDirty.qml b/tests/auto/quick/qquickanimations/data/restartNestedAnimationGroupWhenDirty.qml
new file mode 100644
index 0000000000..da0de96448
--- /dev/null
+++ b/tests/auto/quick/qquickanimations/data/restartNestedAnimationGroupWhenDirty.qml
@@ -0,0 +1,96 @@
+import QtQuick
+
+Rectangle {
+ width: 300
+ height: 300
+
+ // test ParallelAnimation in SequentialAnimation
+ Rectangle {
+ id: line0
+ y: 100
+ width: parent.width
+ height: 2
+ color: "blue"
+ }
+ Rectangle {
+ id: target0
+ objectName: "target0"
+ y: 100
+ anchors.verticalCenter: line0.verticalCenter
+ height: line0.height * 5
+ width: height
+ color: "red"
+ radius: height/2
+
+ property bool onFinishedCalled : false;
+
+ SequentialAnimation {
+ id: seqAnim0
+ objectName: "seqAnim0"
+ loops: 2
+ running: true
+ ParallelAnimation {
+ NumberAnimation {
+ id: anim0
+ target: target0
+ property: "x"
+ from: 0
+ to: 50
+ duration: 500
+ }
+ }
+ Component.onCompleted: anim0.to = 290
+ onFinished: target0.onFinishedCalled = true
+ }
+ }
+
+ // test SequentialAnimation in ParallelAnimation
+ Rectangle {
+ id: line1
+ y: 200
+ width: parent.width
+ height: 2
+ color: "blue"
+ }
+ Rectangle {
+ id: target1
+ objectName: "target1"
+ anchors.verticalCenter: line1.verticalCenter
+ height: line1.height * 5
+ width: height
+ color: "yellow"
+ radius: height/2
+
+ property bool onFinishedCalled : false;
+
+ ParallelAnimation {
+ id: parAnim0
+ objectName: "parAnim0"
+ loops: 2
+ running: true
+ SequentialAnimation {
+ NumberAnimation {
+ id: anim1
+ target: target1
+ property: "x"
+ from: 0
+ to: 50
+ duration: 500
+ }
+ }
+ Component.onCompleted: anim1.to = 290
+ onFinished: target1.onFinishedCalled = true
+ }
+ }
+
+ Timer {
+ interval: 400
+ running: true
+ onTriggered: {
+ seqAnim0.pause()
+ parAnim0.pause()
+ anim0.to = 140
+ anim1.to = 140
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimations/data/scriptActionCrash.qml b/tests/auto/quick/qquickanimations/data/scriptActionCrash.qml
index b2e98550c0..ace63918d8 100644
--- a/tests/auto/quick/qquickanimations/data/scriptActionCrash.qml
+++ b/tests/auto/quick/qquickanimations/data/scriptActionCrash.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickanimations/data/targetsDeletedWithoutRemoval.qml b/tests/auto/quick/qquickanimations/data/targetsDeletedWithoutRemoval.qml
new file mode 100644
index 0000000000..e31caa1905
--- /dev/null
+++ b/tests/auto/quick/qquickanimations/data/targetsDeletedWithoutRemoval.qml
@@ -0,0 +1,29 @@
+import QtQuick
+
+Item {
+ id: root
+
+ property list<Translate> targets
+ property alias animTargets: animation.targets
+
+ Component {
+ id: trComponent
+ Translate {}
+ }
+
+ Component.onCompleted: {
+ const target = trComponent.createObject(this);
+ targets.push(target);
+ target.destroy();
+ // give event loop some time to actually stop the animation and destroy the target
+ Qt.callLater(animation.start);
+ }
+
+ NumberAnimation {
+ id: animation
+ targets: root.targets
+ property: "x"
+ running: false
+ to: 100
+ }
+}
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index f7a84ca979..5ae25f7dfb 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -1,28 +1,31 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <QtTest/QtTest>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <private/qanimationgroupjob_p.h>
+#include <private/qmlutils_p.h>
+
+#include <private/qqmllistmodel_p.h>
+#include <private/qqmltimer_p.h>
+
+#include <private/qquickanimation_p_p.h>
+#include <private/qquickanimatorjob_p.h>
+#include <private/qquickflickable_p.h>
+#include <private/qquickframeanimation_p.h>
+#include <private/qquickitem_p.h>
+#include <private/qquickitemanimation_p.h>
+#include <private/qquickpathinterpolator_p.h>
+#include <private/qquickrectangle_p.h>
+#include <private/qquicktransition_p.h>
+
+#include <QtQuick/qquickview.h>
+
+#include <QtTest/qtest.h>
+#include <QtTest/qsignalspy.h>
+
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
-#include <QtQuick/qquickview.h>
-#include <QtQml/private/qqmltimer_p.h>
-#include <QtQmlModels/private/qqmllistmodel_p.h>
-#include <QtQml/private/qanimationgroupjob_p.h>
-#include <QtQuick/private/qquickrectangle_p.h>
-#include <QtQuick/private/qquickitemanimation_p.h>
-#include <QtQuick/private/qquickitemanimation_p_p.h>
-#include <QtQuick/private/qquicktransition_p.h>
-#include <QtQuick/private/qquickanimation_p.h>
-#include <QtQuick/private/qquickanimatorjob_p.h>
-#include <QtQuick/private/qquickpathinterpolator_p.h>
-#include <QtQuick/private/qquickitem_p.h>
-#include <QtQuick/private/qquicklistview_p.h>
-#include <QtQuick/private/qquickframeanimation_p.h>
-#include <QEasingCurve>
-
-#include <limits.h>
-#include <math.h>
-
-#include <QtQuickTestUtils/private/qmlutils_p.h>
+
+#include <QtCore/qeasingcurve.h>
class tst_qquickanimations : public QQmlDataTest
{
@@ -98,6 +101,10 @@ private slots:
void infiniteLoopsWithoutFrom();
void frameAnimation1();
void frameAnimation2();
+ void restartAnimationGroupWhenDirty();
+ void restartNestedAnimationGroupWhenDirty();
+ void targetsDeletedNotRemoved();
+ void alwaysRunToEndSetFalseRestartBug();
};
#define QTIMED_COMPARE(lhs, rhs) do { \
@@ -2212,6 +2219,121 @@ void tst_qquickanimations::frameAnimation2()
QVERIFY(frameAnimation->currentFrame() > 3);
}
+//QTBUG-110589
+void tst_qquickanimations::restartAnimationGroupWhenDirty()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("restartAnimationGroupWhenDirty.qml"));
+ QScopedPointer<QObject> obj(c.create());
+ auto *root = qobject_cast<QQuickRectangle*>(obj.data());
+ QVERIFY2(root, qPrintable(c.errorString()));
+
+ QQuickSequentialAnimation *seqAnim0 = root->findChild<QQuickSequentialAnimation*>("seqAnim0");
+ QVERIFY(seqAnim0);
+ QQuickRectangle *target0 = root->findChild<QQuickRectangle*>("target0");
+ QVERIFY(target0);
+ QQuickParallelAnimation *parAnim0 = root->findChild<QQuickParallelAnimation*>("parAnim0");
+ QVERIFY(parAnim0);
+ QQuickRectangle *target1 = root->findChild<QQuickRectangle*>("target1");
+ QVERIFY(target1);
+
+ QTRY_VERIFY(seqAnim0->isPaused());
+ QTRY_VERIFY(parAnim0->isPaused());
+ QTRY_VERIFY(target0->x() > 140);
+ QTRY_VERIFY(target1->x() > 140);
+ seqAnim0->resume();
+ parAnim0->resume();
+ QTRY_VERIFY(target0->property("onFinishedCalled").value<bool>());
+ QTRY_VERIFY(target1->property("onFinishedCalled").value<bool>());
+ QTRY_COMPARE(target0->x(), 140);
+ QTRY_COMPARE(target1->x(), 140);
+}
+
+//QTBUG-95840
+void tst_qquickanimations::restartNestedAnimationGroupWhenDirty()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("restartNestedAnimationGroupWhenDirty.qml"));
+ QScopedPointer<QObject> obj(c.create());
+ auto *root = qobject_cast<QQuickRectangle*>(obj.data());
+ QVERIFY2(root, qPrintable(c.errorString()));
+
+ QQuickSequentialAnimation *seqAnim0 = root->findChild<QQuickSequentialAnimation*>("seqAnim0");
+ QVERIFY(seqAnim0);
+ QQuickRectangle *target0 = root->findChild<QQuickRectangle*>("target0");
+ QVERIFY(target0);
+ QQuickParallelAnimation *parAnim0 = root->findChild<QQuickParallelAnimation*>("parAnim0");
+ QVERIFY(parAnim0);
+ QQuickRectangle *target1 = root->findChild<QQuickRectangle*>("target1");
+ QVERIFY(target1);
+
+ QTRY_VERIFY(seqAnim0->isPaused());
+ QTRY_VERIFY(parAnim0->isPaused());
+ QTRY_VERIFY(target0->x() > 140);
+ QTRY_VERIFY(target1->x() > 140);
+ seqAnim0->resume();
+ parAnim0->resume();
+ QTRY_VERIFY(target0->property("onFinishedCalled").value<bool>());
+ QTRY_VERIFY(target1->property("onFinishedCalled").value<bool>());
+ QTRY_COMPARE(target0->x(), 140);
+ QTRY_COMPARE(target1->x(), 140);
+}
+
+void tst_qquickanimations::targetsDeletedNotRemoved()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("targetsDeletedWithoutRemoval.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj.get(), qPrintable(component.errorString()));
+ {
+ QQmlListReference ref(obj.get(), "targets");
+ QVERIFY(ref.isValid());
+ QCOMPARE(ref.size(), 1);
+ QTRY_COMPARE(ref.at(0), nullptr);
+ }
+ {
+ QQmlListReference ref(obj.get(), "animTargets");
+ QVERIFY(ref.isValid());
+ QCOMPARE(ref.size(), 1);
+ QCOMPARE(ref.at(0), nullptr);
+ }
+}
+
+//QTBUG-125224
+void tst_qquickanimations::alwaysRunToEndSetFalseRestartBug()
+{
+ QQuickRectangle rect;
+ QQuickSequentialAnimation sequential;
+ QQuickPropertyAnimation beginAnim;
+ QQuickPropertyAnimation endAnim;
+
+ beginAnim.setTargetObject(&rect);
+ beginAnim.setProperty("x");
+ beginAnim.setTo(200);
+ beginAnim.setDuration(1000);
+
+ endAnim.setTargetObject(&rect);
+ endAnim.setProperty("x");
+ endAnim.setFrom(200);
+ endAnim.setDuration(1000);
+
+ beginAnim.setGroup(&sequential);
+ endAnim.setGroup(&sequential);
+
+ sequential.setLoops(-1);
+ sequential.setAlwaysRunToEnd(true);
+
+ QCOMPARE(sequential.loops(), -1);
+ QVERIFY(sequential.alwaysRunToEnd());
+ sequential.start();
+ sequential.stop();
+ sequential.setAlwaysRunToEnd(false);
+ sequential.start();
+ QCOMPARE(sequential.isRunning(), true);
+ sequential.stop();
+ QCOMPARE(sequential.isRunning(), false);
+}
+
QTEST_MAIN(tst_qquickanimations)
#include "tst_qquickanimations.moc"
diff --git a/tests/auto/quick/qquickanimators/BLACKLIST b/tests/auto/quick/qquickanimators/BLACKLIST
index 019bf71d5e..f0da331c9f 100644
--- a/tests/auto/quick/qquickanimators/BLACKLIST
+++ b/tests/auto/quick/qquickanimators/BLACKLIST
@@ -1,4 +1,4 @@
# QTBUG-89023
[testTransitionsWithImplicitFrom]
-ubuntu-20.04
+ubuntu-22.04
opensuse-leap
diff --git a/tests/auto/quick/qquickanimators/CMakeLists.txt b/tests/auto/quick/qquickanimators/CMakeLists.txt
index c8f1f9819e..4865baa4cf 100644
--- a/tests/auto/quick/qquickanimators/CMakeLists.txt
+++ b/tests/auto/quick/qquickanimators/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickanimators Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickanimators LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickanimators/data/animatorImplicitFrom.qml b/tests/auto/quick/qquickanimators/data/animatorImplicitFrom.qml
index 1893fdc800..c291fcfd95 100644
--- a/tests/auto/quick/qquickanimators/data/animatorImplicitFrom.qml
+++ b/tests/auto/quick/qquickanimators/data/animatorImplicitFrom.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/qquickanimators/data/positionerWithAnimator.qml b/tests/auto/quick/qquickanimators/data/positionerWithAnimator.qml
index f1bdea3b9d..979d7df1d5 100644
--- a/tests/auto/quick/qquickanimators/data/positionerWithAnimator.qml
+++ b/tests/auto/quick/qquickanimators/data/positionerWithAnimator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/qquickanimators/data/windowWithAnimator.qml b/tests/auto/quick/qquickanimators/data/windowWithAnimator.qml
index 61a8b86a95..95b22c3a20 100644
--- a/tests/auto/quick/qquickanimators/data/windowWithAnimator.qml
+++ b/tests/auto/quick/qquickanimators/data/windowWithAnimator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtQuick.Window 2.0
diff --git a/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp b/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp
index 92f75620bd..f6bc136422 100644
--- a/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp
+++ b/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuickTest/quicktest.h>
diff --git a/tests/auto/quick/qquickapplication/BLACKLIST b/tests/auto/quick/qquickapplication/BLACKLIST
index 1b7464e7c4..d643caebdd 100644
--- a/tests/auto/quick/qquickapplication/BLACKLIST
+++ b/tests/auto/quick/qquickapplication/BLACKLIST
@@ -1,3 +1,4 @@
+[state]
+opensuse-leap # QTBUG-122031
[active]
-opensuse-42.3
-opensuse-leap
+opensuse-leap # QTBUG-75215
diff --git a/tests/auto/quick/qquickapplication/CMakeLists.txt b/tests/auto/quick/qquickapplication/CMakeLists.txt
index 74f7075d33..25dd31046a 100644
--- a/tests/auto/quick/qquickapplication/CMakeLists.txt
+++ b/tests/auto/quick/qquickapplication/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickapplication Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickapplication LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
index a440c0c2f8..48b9b833d5 100644
--- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
+++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQml/qqmlcomponent.h>
@@ -93,13 +93,13 @@ void tst_qquickapplication::active()
window.show();
window.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&window));
- QCOMPARE(QGuiApplication::focusWindow(), &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QVERIFY(item->property("active").toBool());
QVERIFY(item->property("active2").toBool());
// not active again
- QWindowSystemInterface::handleWindowActivated(nullptr);
- QTRY_VERIFY(QGuiApplication::focusWindow() != &window);
+ QWindowSystemInterface::handleFocusWindowChanged(nullptr);
+ QTRY_COMPARE_NE(QGuiApplication::focusWindow(), &window);
QVERIFY(!item->property("active").toBool());
QVERIFY(!item->property("active2").toBool());
}
@@ -166,13 +166,13 @@ void tst_qquickapplication::state()
window.show();
window.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&window));
- QCOMPARE(QGuiApplication::focusWindow(), &window);
+ QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationActive);
QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationActive);
// not active again
- QWindowSystemInterface::handleWindowActivated(nullptr);
- QTRY_VERIFY(QGuiApplication::focusWindow() != &window);
+ QWindowSystemInterface::handleFocusWindowChanged(nullptr);
+ QTRY_COMPARE_NE(QGuiApplication::focusWindow(), &window);
QCOMPARE(Qt::ApplicationState(item->property("state").toInt()),
Qt::ApplicationInactive);
QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()),
diff --git a/tests/auto/quick/qquickbehaviors/CMakeLists.txt b/tests/auto/quick/qquickbehaviors/CMakeLists.txt
index b66226776a..4c79b376a8 100644
--- a/tests/auto/quick/qquickbehaviors/CMakeLists.txt
+++ b/tests/auto/quick/qquickbehaviors/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickbehaviors Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickbehaviors LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickbehaviors/bindable.h b/tests/auto/quick/qquickbehaviors/bindable.h
index aa6acc6615..0eeed6f87a 100644
--- a/tests/auto/quick/qquickbehaviors/bindable.h
+++ b/tests/auto/quick/qquickbehaviors/bindable.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef BINDABLE_H
#define BINDABLE_H
diff --git a/tests/auto/quick/qquickbehaviors/data/duplicated.qml b/tests/auto/quick/qquickbehaviors/data/duplicated.qml
new file mode 100644
index 0000000000..15518a05cf
--- /dev/null
+++ b/tests/auto/quick/qquickbehaviors/data/duplicated.qml
@@ -0,0 +1,31 @@
+import QtQuick 2.0
+Rectangle {
+ id: main
+
+ width: 400
+ height: 400
+
+ property bool behavior1Triggered
+ property bool behavior2Triggered
+
+ Behavior on x {
+ ScriptAction { script: behavior1Triggered = true }
+ }
+ Behavior on x {
+ ScriptAction { script: behavior2Triggered = true }
+ }
+
+ MouseArea {
+ id: clicker
+ anchors.fill: parent
+ }
+
+ states: State {
+ name: "moved"
+ when: clicker.pressed
+ PropertyChanges {
+ target: main
+ x: 200
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickbehaviors/data/qtbug21549-2.qml b/tests/auto/quick/qquickbehaviors/data/qtbug21549-2.qml
index 23804af711..4c3d4a0d26 100644
--- a/tests/auto/quick/qquickbehaviors/data/qtbug21549-2.qml
+++ b/tests/auto/quick/qquickbehaviors/data/qtbug21549-2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
index 5ea11729d8..e9720130f2 100644
--- a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
+++ b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <qsignalspy.h>
#include <QtQml/qqmlengine.h>
@@ -33,6 +33,7 @@ private slots:
void group();
void valueType();
void emptyBehavior();
+ void duplicatedBehavior();
void explicitSelection();
void nonSelectingBehavior();
void reassignedAnimation();
@@ -223,6 +224,20 @@ void tst_qquickbehaviors::emptyBehavior()
QCOMPARE(x, qreal(200)); //should change immediately
}
+void tst_qquickbehaviors::duplicatedBehavior()
+{
+ QTest::failOnWarning(QRegularExpression(".*"));
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg,
+ QRegularExpression("Attempting to set another interceptor on.*"));
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("duplicated.qml"));
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle *>(c.create()));
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
+
+ // Expecting no crash
+ QQuickItemPrivate::get(rect.data())->setState("moved");
+}
+
void tst_qquickbehaviors::explicitSelection()
{
QQmlEngine engine;
diff --git a/tests/auto/quick/qquickborderimage/CMakeLists.txt b/tests/auto/quick/qquickborderimage/CMakeLists.txt
index 1585177a0a..5d88680367 100644
--- a/tests/auto/quick/qquickborderimage/CMakeLists.txt
+++ b/tests/auto/quick/qquickborderimage/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickborderimage Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickborderimage LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
index c1b9818a00..83396c6944 100644
--- a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
+++ b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QTextDocument>
#include <QTcpServer>
@@ -45,6 +45,7 @@ private slots:
void sciSource();
void sciSource_data();
void invalidSciFile();
+ void nonExistingSciFile();
void validSciFiles_data();
void validSciFiles();
void pendingRemoteRequest();
@@ -335,6 +336,21 @@ void tst_qquickborderimage::invalidSciFile()
delete obj;
}
+void tst_qquickborderimage::nonExistingSciFile()
+{
+ const QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + testFileUrl("this_file_does_not_exist.sci").toString() +"\"; width: 300; height: 300 }";
+ QQmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ std::unique_ptr<QObject> obj(component.create());
+ auto bimage = qobject_cast<QQuickBorderImage *>(obj.get());
+ QVERIFY(bimage != nullptr);
+ QCOMPARE(bimage->width(), 300.);
+ QCOMPARE(bimage->height(), 300.);
+ QCOMPARE(bimage->status(), QQuickImageBase::Error);
+ QCOMPARE(bimage->horizontalTileMode(), QQuickBorderImage::Stretch);
+ QCOMPARE(bimage->verticalTileMode(), QQuickBorderImage::Stretch);
+}
+
void tst_qquickborderimage::validSciFiles_data()
{
QTest::addColumn<QString>("source");
diff --git a/tests/auto/quick/qquickboundaryrule/CMakeLists.txt b/tests/auto/quick/qquickboundaryrule/CMakeLists.txt
index 563102911c..c969657c3e 100644
--- a/tests/auto/quick/qquickboundaryrule/CMakeLists.txt
+++ b/tests/auto/quick/qquickboundaryrule/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickboundaryrule Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickboundaryrule LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp b/tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp
index 2964238849..c301848b1e 100644
--- a/tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp
+++ b/tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <qsignalspy.h>
#include <QtQml/qqmlengine.h>
diff --git a/tests/auto/quick/qquickcanvasitem/BLACKLIST b/tests/auto/quick/qquickcanvasitem/BLACKLIST
index ec70b00e36..c7245e7633 100644
--- a/tests/auto/quick/qquickcanvasitem/BLACKLIST
+++ b/tests/auto/quick/qquickcanvasitem/BLACKLIST
@@ -6,6 +6,7 @@ macos
windows
macos
# QTBUG-41043
+android
[canvas::test_toDataURL]
*
[fillRect::test_fillRect]
diff --git a/tests/auto/quick/qquickcanvasitem/CMakeLists.txt b/tests/auto/quick/qquickcanvasitem/CMakeLists.txt
index f4fe685b83..fdc1416a32 100644
--- a/tests/auto/quick/qquickcanvasitem/CMakeLists.txt
+++ b/tests/auto/quick/qquickcanvasitem/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickcanvasitem Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickcanvasitem LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml b/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml
index 33fffd4cb1..00d13f31f4 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml
@@ -6,6 +6,7 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_angle_1(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -21,6 +22,7 @@ CanvasTestCase {
}
function test_angle_2(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -36,6 +38,7 @@ CanvasTestCase {
}
function test_angle_3(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#0f0';
@@ -53,6 +56,7 @@ CanvasTestCase {
}
function test_angle_4(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -71,6 +75,7 @@ CanvasTestCase {
}
function test_angle_5(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -90,6 +95,7 @@ CanvasTestCase {
function test_angle_6(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -110,6 +116,7 @@ CanvasTestCase {
function test_empty(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -125,6 +132,7 @@ CanvasTestCase {
}
function test_nonempty(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -141,6 +149,7 @@ CanvasTestCase {
}
function test_nonfinite(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -199,6 +208,7 @@ CanvasTestCase {
}
function test_end(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -216,6 +226,7 @@ CanvasTestCase {
}
function test_negative(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -234,6 +245,7 @@ CanvasTestCase {
function test_scale_1(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -270,6 +282,7 @@ CanvasTestCase {
function test_scale_2(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -296,6 +309,7 @@ CanvasTestCase {
function test_selfintersect_1(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -316,6 +330,7 @@ CanvasTestCase {
function test_selfintersect_2(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -340,6 +355,7 @@ CanvasTestCase {
function test_shape_1(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -361,6 +377,7 @@ CanvasTestCase {
function test_shape_2(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -381,6 +398,7 @@ CanvasTestCase {
}
function test_shape_3(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -401,6 +419,7 @@ CanvasTestCase {
function test_shape_4(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -421,6 +440,7 @@ CanvasTestCase {
function test_shape_5(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -441,6 +461,7 @@ CanvasTestCase {
function test_twopie(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -488,6 +509,7 @@ CanvasTestCase {
function test_zero(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml b/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml
index ef1b7a7b2a..81412d98c9 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml
@@ -7,6 +7,7 @@ CanvasTestCase {
function test_coincide(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -44,6 +45,7 @@ CanvasTestCase {
}
function test_collinear(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -109,6 +111,7 @@ CanvasTestCase {
}
function test_subpath(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -135,6 +138,7 @@ CanvasTestCase {
function test_negative(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -152,6 +156,7 @@ CanvasTestCase {
function test_nonfinite(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -208,6 +213,7 @@ CanvasTestCase {
}
function test_scale(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -237,6 +243,7 @@ CanvasTestCase {
function test_shape(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -348,6 +355,7 @@ CanvasTestCase {
function test_transform(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -374,6 +382,7 @@ CanvasTestCase {
}
function test_zero(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_composite.qml b/tests/auto/quick/qquickcanvasitem/data/tst_composite.qml
index 8a5a52cf1e..4ee24ad437 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_composite.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_composite.qml
@@ -6,6 +6,7 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_clearRect(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -17,6 +18,7 @@ CanvasTestCase {
function test_clip(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
var composites = [ {compsite:"copy"},
{compsite:"destination-atop"},
@@ -47,6 +49,7 @@ CanvasTestCase {
function test_globalAlpha(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
compare(ctx.globalAlpha, 1.0);
@@ -83,6 +86,7 @@ CanvasTestCase {
function test_operation(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.globalCompositeOperation = 'xor';
@@ -137,6 +141,7 @@ CanvasTestCase {
function test_solid(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = Qt.rgba(0, 1, 1, 1.0);
@@ -233,6 +238,7 @@ CanvasTestCase {
}
function test_transparent(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
@@ -330,6 +336,7 @@ CanvasTestCase {
function test_uncovered(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_fillStyle.qml b/tests/auto/quick/qquickcanvasitem/data/tst_fillStyle.qml
index 58ea6d7f59..9e8c0785c3 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_fillStyle.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_fillStyle.qml
@@ -6,6 +6,7 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_default(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
verify(ctx.fillStyle, "#000000");
@@ -14,6 +15,7 @@ CanvasTestCase {
}
function test_get(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#fa0';
@@ -23,6 +25,7 @@ CanvasTestCase {
}
function test_hex(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -37,6 +40,7 @@ CanvasTestCase {
}
function test_invalid(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#fa0';
@@ -60,6 +64,7 @@ CanvasTestCase {
}
function test_saverestore(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
var old = ctx.fillStyle;
ctx.save();
@@ -75,6 +80,7 @@ CanvasTestCase {
}
function test_namedColor(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = "red";
@@ -91,6 +97,7 @@ CanvasTestCase {
}
function test_rgba(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = "rgb(-100, 300, 255)";
@@ -108,6 +115,7 @@ CanvasTestCase {
function test_hsla(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = "hsla(120, 100%, 50%, 0.499)";
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_fillrect.qml b/tests/auto/quick/qquickcanvasitem/data/tst_fillrect.qml
index ce1c27c6bc..213abdd622 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_fillrect.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_fillrect.qml
@@ -6,6 +6,7 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_fillRect(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.fillStyle = "red";
ctx.fillRect(0, 0, canvas.width, canvas.height);
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml b/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml
index 7c87d896fb..70e77c8760 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml
@@ -6,6 +6,7 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_basic(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#0f0';
@@ -18,6 +19,7 @@ CanvasTestCase {
function test_interpolate(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -166,6 +168,7 @@ CanvasTestCase {
}
function test_radial(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#0f0';
@@ -788,6 +791,7 @@ CanvasTestCase {
}
function test_linear(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
try { var err = false;
@@ -907,6 +911,7 @@ CanvasTestCase {
}
function test_object(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
var g1 = ctx.createLinearGradient(0, 0, 100, 0);
@@ -978,6 +983,7 @@ CanvasTestCase {
function test_conical(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
var g = ctx.createConicalGradient(10, 10, 50);
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_image.qml b/tests/auto/quick/qquickcanvasitem/data/tst_image.qml
index 1f695d7080..a1eb272cd0 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_image.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_image.qml
@@ -11,12 +11,12 @@ CanvasTestCase {
canvas.loadImage('rgrg-256x256.png');
canvas.loadImage('ggrr-256x256.png');
canvas.loadImage('broken.png');
- while (!canvas.isImageLoaded('green.png'))
- wait(200);
+ tryVerify(function() { return canvas.isImageLoaded('green.png'); })
}
function test_3args(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
ctx.reset();
@@ -35,6 +35,7 @@ CanvasTestCase {
}
function test_5args(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -54,6 +55,7 @@ CanvasTestCase {
}
function test_9args(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -118,6 +120,7 @@ CanvasTestCase {
}
function test_animated(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -125,6 +128,7 @@ CanvasTestCase {
}
function test_clip(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -139,6 +143,7 @@ CanvasTestCase {
}
function test_self(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -170,6 +175,7 @@ CanvasTestCase {
function test_outsidesource(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -207,6 +213,7 @@ CanvasTestCase {
function test_null(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -220,15 +227,18 @@ CanvasTestCase {
function test_url(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
canvas.loadImage(testCase.green);
+ tryVerify(function() { return canvas.isImageLoaded(testCase.green); })
ctx.drawImage(testCase.green, 0, 0);
comparePixel(ctx, 0,0, 0,255,0,255,2);
}
function test_composite(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -241,12 +251,14 @@ CanvasTestCase {
}
function test_path(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
}
function test_transform(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -260,6 +272,7 @@ CanvasTestCase {
function test_imageitem(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -268,6 +281,7 @@ CanvasTestCase {
function test_imageData(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -276,6 +290,7 @@ CanvasTestCase {
function test_wrongtype(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -293,6 +308,7 @@ CanvasTestCase {
function test_nonfinite(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -606,6 +622,7 @@ CanvasTestCase {
function test_negative(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -661,6 +678,7 @@ CanvasTestCase {
function test_canvas(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -684,6 +702,7 @@ CanvasTestCase {
function test_broken(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -694,6 +713,7 @@ CanvasTestCase {
function test_alpha(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
@@ -706,6 +726,7 @@ CanvasTestCase {
}
function test_multiple_painting(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
loadImages(canvas);
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml b/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml
index 76b99a765e..aab7a95589 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml
@@ -11,6 +11,7 @@ CanvasTestCase {
skip("ctx.getImageData crashes on offscreen/minimal platforms");
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
var size = 17
ctx.reset();
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_invalidContext.qml b/tests/auto/quick/qquickcanvasitem/data/tst_invalidContext.qml
index 0df536cc02..904b0a3405 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_invalidContext.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_invalidContext.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
import QtTest 1.1
@@ -28,16 +28,16 @@ Item {
anchors.fill: parent
property var paintContext: null
- function paint() {
+ function doPaint() {
paintContext.fillStyle = Qt.rgba(1, 0, 0, 1);
paintContext.fillRect(0, 0, width, height);
- requestAnimationFrame(paint);
+ requestAnimationFrame(doPaint);
}
onAvailableChanged: {
if (available) {
paintContext = getContext("2d")
- requestAnimationFrame(paint);
+ requestAnimationFrame(doPaint);
}
}
}
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_line.qml b/tests/auto/quick/qquickcanvasitem/data/tst_line.qml
index ba7ff09728..e5d03e5db7 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_line.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_line.qml
@@ -6,6 +6,7 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_default(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
compare(ctx.lineWidth, 1);
@@ -16,6 +17,7 @@ CanvasTestCase {
function test_cross(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#0f0';
@@ -43,6 +45,7 @@ CanvasTestCase {
function test_join(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -306,6 +309,7 @@ CanvasTestCase {
}
function test_miter(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -481,6 +485,7 @@ CanvasTestCase {
}
function test_width(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#0f0';
@@ -625,6 +630,7 @@ CanvasTestCase {
skip("line::test_cap crashes on Android, QTBUG-103257")
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -841,6 +847,7 @@ CanvasTestCase {
function test_lineDash(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.strokeStyle = "#fff";
@@ -899,6 +906,7 @@ CanvasTestCase {
function test_lineDashReset(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.strokeStyle = "#ff0000";
@@ -930,6 +938,7 @@ CanvasTestCase {
function test_lineDashOffset(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.strokeStyle = "#fff";
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_path.qml b/tests/auto/quick/qquickcanvasitem/data/tst_path.qml
index 60c782c8fa..ae08b58519 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_path.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_path.qml
@@ -6,6 +6,7 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_basic(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#0f0';
@@ -36,6 +37,7 @@ CanvasTestCase {
}
function test_beginPath(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#0f0';
ctx.fillRect(0, 0, 100, 50);
@@ -48,6 +50,7 @@ CanvasTestCase {
}
function test_closePath(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#0f0';
@@ -86,6 +89,7 @@ CanvasTestCase {
function test_isPointInPath(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.arc(50, 25, 10, 0, Math.PI, false);
@@ -256,6 +260,7 @@ CanvasTestCase {
function test_fill(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -378,6 +383,7 @@ CanvasTestCase {
}
function test_stroke(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#0f0';
@@ -662,6 +668,7 @@ CanvasTestCase {
}
function test_clip(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -784,6 +791,7 @@ CanvasTestCase {
function test_moveTo(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -839,6 +847,7 @@ CanvasTestCase {
}
function test_lineTo(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -904,6 +913,7 @@ CanvasTestCase {
}
function test_bezierCurveTo(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -1072,6 +1082,7 @@ CanvasTestCase {
}
function test_quadraticCurveTo(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -1173,6 +1184,7 @@ CanvasTestCase {
}
function test_rect(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -1371,6 +1383,7 @@ CanvasTestCase {
function test_clearRect(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#0f0';
@@ -1383,6 +1396,7 @@ CanvasTestCase {
}
function test_fillRect(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.beginPath();
@@ -1397,6 +1411,7 @@ CanvasTestCase {
function test_strokeRect(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.beginPath();
@@ -1412,6 +1427,7 @@ CanvasTestCase {
}
function test_transform(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_pattern.qml b/tests/auto/quick/qquickcanvasitem/data/tst_pattern.qml
index 1d7fd2c12f..e0a4d7ad23 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_pattern.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_pattern.qml
@@ -6,36 +6,42 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_basic(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_animated(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_image(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_modified(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_paint(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_repeat(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_pixel.qml b/tests/auto/quick/qquickcanvasitem/data/tst_pixel.qml
index 281264ba92..ef908db92a 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_pixel.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_pixel.qml
@@ -7,6 +7,7 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_createImageData(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
var imageData = ctx.createImageData(1, 1);
var imageDataValues = imageData.data;
@@ -20,24 +21,28 @@ CanvasTestCase {
}
function test_getImageData(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_object(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_putImageData(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_filters(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_shadow.qml b/tests/auto/quick/qquickcanvasitem/data/tst_shadow.qml
index 2baaa072d0..14318b3f56 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_shadow.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_shadow.qml
@@ -6,12 +6,14 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_basic(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_blur(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
@@ -19,6 +21,7 @@ CanvasTestCase {
function test_clip(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
@@ -26,6 +29,7 @@ CanvasTestCase {
function test_composite(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
@@ -33,6 +37,7 @@ CanvasTestCase {
function test_enable(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
@@ -40,36 +45,42 @@ CanvasTestCase {
function test_gradient(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_image(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_offset(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_pattern(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_stroke(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_tranform(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_state.qml b/tests/auto/quick/qquickcanvasitem/data/tst_state.qml
index 18464def7c..ce02f9d7f7 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_state.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_state.qml
@@ -6,6 +6,7 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_bitmap(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -19,6 +20,7 @@ CanvasTestCase {
}
function test_clip(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -35,6 +37,7 @@ CanvasTestCase {
}
function test_fillStyle(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
// Test that restore() undoes any modifications
@@ -56,6 +59,7 @@ CanvasTestCase {
}
function test_font(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -78,6 +82,7 @@ CanvasTestCase {
}
function test_globalAlpha(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -100,6 +105,7 @@ CanvasTestCase {
}
function test_globalCompositeOperation(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -122,6 +128,7 @@ CanvasTestCase {
}
function test_lineCap(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -144,6 +151,7 @@ CanvasTestCase {
}
function test_lineJoin(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -166,6 +174,7 @@ CanvasTestCase {
}
function test_lineWidth(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -188,6 +197,7 @@ CanvasTestCase {
}
function test_miterLimit(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -210,6 +220,7 @@ CanvasTestCase {
}
function test_path(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -225,6 +236,7 @@ CanvasTestCase {
}
function test_shadow(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -295,6 +307,7 @@ CanvasTestCase {
}
function test_stack(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -330,6 +343,7 @@ CanvasTestCase {
}
function test_strokeStyle(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -353,6 +367,7 @@ CanvasTestCase {
function test_text(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -392,6 +407,7 @@ CanvasTestCase {
function test_transform(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml b/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml
index a3f1ab0a9b..0dc39b8b4c 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml
@@ -8,6 +8,7 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_default(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
compare(ctx.strokeStyle, "#000000")
@@ -17,6 +18,7 @@ CanvasTestCase {
}
function test_saverestore(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
var old = ctx.strokeStyle;
ctx.save();
@@ -33,6 +35,7 @@ CanvasTestCase {
}
function test_namedColor(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.strokeStyle = "red";
@@ -50,6 +53,7 @@ CanvasTestCase {
}
function test_colorFromObjectToString(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -68,6 +72,7 @@ CanvasTestCase {
}
function test_withInvalidColor(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_svgpath.qml b/tests/auto/quick/qquickcanvasitem/data/tst_svgpath.qml
index 2b39357bed..011fbd497b 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_svgpath.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_svgpath.qml
@@ -6,6 +6,7 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_svgpath(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
var svgs = [
// Absolute coordinates, explicit commands.
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_text.qml b/tests/auto/quick/qquickcanvasitem/data/tst_text.qml
index bfc4067040..f7cd66890b 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_text.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_text.qml
@@ -6,36 +6,42 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_baseLine(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_align(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_stroke(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_fill(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_font(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
}
function test_measure(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
canvas.destroy()
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_transform.qml b/tests/auto/quick/qquickcanvasitem/data/tst_transform.qml
index b2f5b51fa5..bbfec6a106 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_transform.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_transform.qml
@@ -6,6 +6,7 @@ CanvasTestCase {
function init_data() { return testData("2d"); }
function test_order(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -20,6 +21,7 @@ CanvasTestCase {
}
function test_rotate(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -90,6 +92,7 @@ CanvasTestCase {
}
function test_scale(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -182,6 +185,7 @@ CanvasTestCase {
}
function test_setTransform(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -325,6 +329,7 @@ CanvasTestCase {
}
function test_transform(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
@@ -460,6 +465,7 @@ CanvasTestCase {
}
function test_translate(row) {
var canvas = createCanvasObject(row);
+ tryVerify(function() { return canvas.available; });
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = '#f00';
diff --git a/tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp b/tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp
index 0215191d78..7e65b2a9d4 100644
--- a/tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp
+++ b/tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcontext.h>
diff --git a/tests/auto/quick/qquickcolorgroup/CMakeLists.txt b/tests/auto/quick/qquickcolorgroup/CMakeLists.txt
index 1d051476ff..0ced7947fd 100644
--- a/tests/auto/quick/qquickcolorgroup/CMakeLists.txt
+++ b/tests/auto/quick/qquickcolorgroup/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickcolorgroup Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickcolorgroup LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qquickcolorgroup
SOURCES
tst_qquickcolorgroup.cpp
diff --git a/tests/auto/quick/qquickcolorgroup/tst_qquickcolorgroup.cpp b/tests/auto/quick/qquickcolorgroup/tst_qquickcolorgroup.cpp
index 046cd5a14c..acf2849188 100644
--- a/tests/auto/quick/qquickcolorgroup/tst_qquickcolorgroup.cpp
+++ b/tests/auto/quick/qquickcolorgroup/tst_qquickcolorgroup.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/QSignalSpy>
diff --git a/tests/auto/quick/qquickdeliveryagent/CMakeLists.txt b/tests/auto/quick/qquickdeliveryagent/CMakeLists.txt
index 431ce4aaeb..f893d4372b 100644
--- a/tests/auto/quick/qquickdeliveryagent/CMakeLists.txt
+++ b/tests/auto/quick/qquickdeliveryagent/CMakeLists.txt
@@ -5,6 +5,12 @@
## tst_qquickdeliveryagent Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickdeliveryagent LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickdeliveryagent/data/clearItemsOnHoverLeave.qml b/tests/auto/quick/qquickdeliveryagent/data/clearItemsOnHoverLeave.qml
new file mode 100644
index 0000000000..7b37b44050
--- /dev/null
+++ b/tests/auto/quick/qquickdeliveryagent/data/clearItemsOnHoverLeave.qml
@@ -0,0 +1,32 @@
+import QtQuick
+
+Rectangle{
+ id: mainWindow
+
+ visible: true
+ width: 800
+ height: 600
+
+ Column {
+ anchors.fill: parent
+ MouseArea {
+ width: parent.width
+ height: parent.height/3
+ hoverEnabled: true
+ }
+ MouseArea {
+ id: mouseArea
+ width: parent.width
+ height: parent.height/3
+ hoverEnabled: true
+ onExited: {
+ Window.window.close();
+ }
+ }
+ MouseArea {
+ width: parent.width
+ height: parent.height / 3
+ hoverEnabled: true
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickdeliveryagent/data/compoundControl.qml b/tests/auto/quick/qquickdeliveryagent/data/compoundControl.qml
new file mode 100644
index 0000000000..8ed05fc8d2
--- /dev/null
+++ b/tests/auto/quick/qquickdeliveryagent/data/compoundControl.qml
@@ -0,0 +1,28 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Controls.Basic
+
+Item {
+ id: root
+ objectName: "root"
+ width: 320
+ height: 240
+
+ FocusScope {
+ id: spinboxFocusScope
+ objectName: "spinboxFocusScope"
+ width: spinbox.width
+ height: spinbox.height
+ SpinBox {
+ id: spinbox
+ objectName: "spinbox"
+ editable: true
+ contentItem: TextField {
+ objectName: "spinboxContentItem"
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/auto/quick/qquickdeliveryagent/data/flickableTextEdit.qml b/tests/auto/quick/qquickdeliveryagent/data/flickableTextEdit.qml
index 5286def525..79d91a25d4 100644
--- a/tests/auto/quick/qquickdeliveryagent/data/flickableTextEdit.qml
+++ b/tests/auto/quick/qquickdeliveryagent/data/flickableTextEdit.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/qquickdeliveryagent/data/listViewDelegate.qml b/tests/auto/quick/qquickdeliveryagent/data/listViewDelegate.qml
index bdb7246450..c5207e2a5d 100644
--- a/tests/auto/quick/qquickdeliveryagent/data/listViewDelegate.qml
+++ b/tests/auto/quick/qquickdeliveryagent/data/listViewDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp b/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp
index 7e6416b8e2..c9bce0c0b4 100644
--- a/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp
+++ b/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QSignalSpy>
@@ -19,9 +19,12 @@
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
+#include <QtQuick/private/qquickmousearea_p.h>
#include <QtGui/private/qeventpoint_p.h>
+#include <QtCore/qpointer.h>
+
Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
// On one hand, uncommenting this will make troubleshooting easier (avoid the 60FPS hover events).
@@ -138,6 +141,11 @@ private slots:
void hoverPropagation_nested_data();
void hoverPropagation_nested();
void hoverPropagation_siblings();
+ void hoverEnterOnItemMove();
+ void hoverEnterOnItemMoveAfterHide();
+ void clearItemsOnHoverLeave();
+ void deleteTargetOnPress();
+ void compoundControlsFocusInSubscene();
private:
QScopedPointer<QPointingDevice> touchDevice = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
@@ -175,7 +183,8 @@ void tst_qquickdeliveryagent::passiveGrabberOrder()
QPoint pos(75, 75);
QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, pos);
- QTest::qWait(1000);
+ QTRY_VERIFY(rootTap->isPressed());
+ QTRY_VERIFY(subsceneTap->isPressed());
auto devPriv = QPointingDevicePrivate::get(QPointingDevice::primaryPointingDevice());
const auto &persistentPoint = devPriv->activePoints.values().first();
qCDebug(lcTests) << "passive grabbers" << persistentPoint.passiveGrabbers << "contexts" << persistentPoint.passiveGrabbersContext;
@@ -185,7 +194,8 @@ void tst_qquickdeliveryagent::passiveGrabberOrder()
QCOMPARE(persistentPoint.passiveGrabbers.last(), rootTap);
QTest::mouseRelease(&view, Qt::LeftButton);
- QTest::qWait(100);
+ QTRY_COMPARE(rootTap->isPressed(), false);
+ QTRY_COMPARE(subsceneTap->isPressed(), false);
// QQuickWindow::event() has failsafe: clear all grabbers after release
QCOMPARE(persistentPoint.passiveGrabbers.size(), 0);
@@ -390,7 +400,7 @@ void tst_qquickdeliveryagent::undoDelegationWhenSubsceneFocusCleared() // QTBUG-
SubsceneRootItem subscene(listView, listView->boundingRect(), window.rootObject());
window.show();
- QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(QTest::qWaitForWindowFocused(&window));
// populate a delegate in ListView
listView->setModel(1);
@@ -521,6 +531,151 @@ void tst_qquickdeliveryagent::hoverPropagation_siblings()
QCOMPARE(sibling2.hoverEnter, true);
}
+void tst_qquickdeliveryagent::hoverEnterOnItemMove()
+{
+ QQuickWindow window;
+ auto deliveryAgent = QQuickWindowPrivate::get(&window)->deliveryAgentPrivate();
+ window.resize(200, 200);
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ // start with the mouse in the bottom right
+ QTest::mouseMove(&window, QPoint(150, 150));
+
+ HoverItem hoverItem(window.contentItem());
+ hoverItem.setAcceptHoverEvents(true);
+ hoverItem.setWidth(100);
+ hoverItem.setHeight(100);
+
+ deliveryAgent->flushFrameSynchronousEvents(&window);
+
+ QCOMPARE(hoverItem.hoverEnter, false);
+
+ // move the item so the mouse is now inside where the mouse was
+ hoverItem.setX(100);
+ hoverItem.setY(100);
+ deliveryAgent->flushFrameSynchronousEvents(&window);
+ QCOMPARE(hoverItem.hoverEnter, true);
+}
+
+void tst_qquickdeliveryagent::hoverEnterOnItemMoveAfterHide()
+{
+ QQuickWindow window;
+ auto deliveryAgent = QQuickWindowPrivate::get(&window)->deliveryAgentPrivate();
+ window.resize(200, 200);
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ // start with the mouse in the bottom right
+ QTest::mouseMove(&window, QPoint(149, 149));
+
+ HoverItem hoverItem(window.contentItem());
+ hoverItem.setAcceptHoverEvents(true);
+ hoverItem.setWidth(100);
+ hoverItem.setHeight(100);
+
+ deliveryAgent->flushFrameSynchronousEvents(&window);
+ QCOMPARE(hoverItem.hoverEnter, false);
+
+ window.hide();
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ QCOMPARE(hoverItem.hoverEnter, false);
+
+ // move the item so the mouse is now inside where the mouse was
+ hoverItem.setX(100);
+ hoverItem.setY(100);
+ deliveryAgent->flushFrameSynchronousEvents(&window);
+ QCOMPARE(hoverItem.hoverEnter, false);
+}
+
+void tst_qquickdeliveryagent::clearItemsOnHoverLeave()
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("clearItemsOnHoverLeave.qml")));
+
+ QTest::mouseMove(&window, QPoint(10, 205)); // Move to MouseArea that triggers close
+ QTest::mouseMove(&window, QPoint(10, 405)); // Exit MouseArea that triggers close.
+}
+
+// QTBUG-91272
+void tst_qquickdeliveryagent::deleteTargetOnPress()
+{
+ QQuickWindow window;
+ auto deliveryAgent = QQuickWindowPrivate::get(&window)->deliveryAgentPrivate();
+ window.resize(200, 200);
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ QQuickMouseArea *lowerArea = new QQuickMouseArea(window.contentItem());
+ lowerArea->setWidth(200);
+ lowerArea->setHeight(200);
+
+ QQuickMouseArea *upperArea = new QQuickMouseArea(window.contentItem());
+ upperArea->setWidth(180);
+ upperArea->setHeight(180);
+ bool pressed = false;
+ connect(upperArea, &QQuickMouseArea::pressed, this, [&]() {
+ pressed = true;
+ delete lowerArea;
+ lowerArea = nullptr;
+ });
+ QTest::mouseMove(&window, QPoint(100, 100));
+ QTest::mousePress(&window, Qt::MouseButton::LeftButton, {}, {100, 100});
+ deliveryAgent->flushFrameSynchronousEvents(&window);
+ QVERIFY(pressed);
+ QVERIFY(upperArea->isPressed());
+ QTest::mouseRelease(&window, Qt::MouseButton::LeftButton, {}, {100, 100});
+ deliveryAgent->flushFrameSynchronousEvents(&window);
+ QVERIFY(!upperArea->isPressed());
+}
+
+void tst_qquickdeliveryagent::compoundControlsFocusInSubscene()
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::initView(window, testFileUrl("compoundControl.qml")));
+ QQuickItem *spinboxFocusScope = window.rootObject()->findChild<QQuickItem *>("spinboxFocusScope");
+ QVERIFY(spinboxFocusScope);
+ QQuickItem *spinbox = window.rootObject()->findChild<QQuickItem *>("spinbox");
+ QVERIFY(spinbox);
+ QQuickItem *textField = window.rootObject()->findChild<QQuickItem *>("spinboxContentItem");
+ QVERIFY(textField);
+
+ // put the items into a SubsceneRootItem
+ SubsceneRootItem subscene(spinboxFocusScope, spinboxFocusScope->boundingRect().translated(0, spinboxFocusScope->height() + 20), window.rootObject());
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowFocused(&window));
+
+ QVERIFY(!textField->hasActiveFocus());
+ QVERIFY(!textField->hasFocus());
+ QVERIFY(!spinbox->hasActiveFocus());
+ QVERIFY(!spinbox->hasFocus());
+ QVERIFY(!spinbox->scopedFocusItem());
+ QVERIFY(!spinboxFocusScope->hasActiveFocus());
+ QVERIFY(!spinboxFocusScope->hasFocus());
+ QVERIFY(!spinbox->scopedFocusItem());
+
+ auto clickPos = spinboxFocusScope->boundingRect().translated(0, spinboxFocusScope->height() + 20).center().toPoint();
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, clickPos);
+
+ QVERIFY(textField->hasActiveFocus());
+ QVERIFY(textField->hasFocus());
+ QTRY_VERIFY(spinbox->hasActiveFocus());
+ QVERIFY(spinbox->hasFocus());
+ QCOMPARE(spinbox->scopedFocusItem(), textField);
+ QVERIFY(spinboxFocusScope->hasActiveFocus());
+ QVERIFY(spinboxFocusScope->hasFocus());
+ QCOMPARE(spinboxFocusScope->scopedFocusItem(), spinbox);
+
+ QQuickDeliveryAgentPrivate *daPriv = static_cast<QQuickDeliveryAgentPrivate *>(QQuickDeliveryAgentPrivate::get(subscene.deliveryAgent));
+ QVERIFY(daPriv->rootItem->hasActiveFocus());
+ QCOMPARE(daPriv->activeFocusItem, textField);
+ QCOMPARE(QQuickWindowPrivate::get(&window)->deliveryAgentPrivate()->activeFocusItem, textField);
+ QCOMPARE(QQuickWindowPrivate::get(&window)->deliveryAgentPrivate()->rootItem->scopedFocusItem(), spinboxFocusScope);
+}
+
QTEST_MAIN(tst_qquickdeliveryagent)
#include "tst_qquickdeliveryagent.moc"
diff --git a/tests/auto/quick/qquickdesignersupport/CMakeLists.txt b/tests/auto/quick/qquickdesignersupport/CMakeLists.txt
index 9fbd69137a..985233f5f3 100644
--- a/tests/auto/quick/qquickdesignersupport/CMakeLists.txt
+++ b/tests/auto/quick/qquickdesignersupport/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickdesignersupport Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickdesignersupport LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickdesignersupport/data/RegTestComponent.qml b/tests/auto/quick/qquickdesignersupport/data/RegTestComponent.qml
new file mode 100644
index 0000000000..8bb8480daf
--- /dev/null
+++ b/tests/auto/quick/qquickdesignersupport/data/RegTestComponent.qml
@@ -0,0 +1,20 @@
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+
+QtObject {
+ id: root
+
+ property int currentCategory: 0
+
+
+
+ property var materialsNames: [[qsTr("Car Paint"), qsTr("Glittery Car Paint"), qsTr("Aluminium"), qsTr("Chrome"), qsTr("Steel"), qsTr("Brushed Steel"), qsTr("Steel Floor"), qsTr("Copper"), qsTr("Silver"), qsTr("Gold"), qsTr("Mirror")],
+ [qsTr("Asphalt"), qsTr("Brick"), qsTr("Ceramic"), qsTr("Concrete"), qsTr("Glass"), qsTr("Darkened Glass"), qsTr("Wood"), qsTr("Wood - Planks"), qsTr("Wood - Parquet"), qsTr("Stone")],
+ [qsTr("Acrylic Paint"), qsTr("Carbon Fiber"), qsTr("Shiny Plastic"), qsTr("Matte Plastic"), qsTr("Textured Plastic"), qsTr("Rubber"), qsTr("Wax")],
+ [qsTr("Fabric"), qsTr("Fabric: Rough"), qsTr("Fabric: Satin"), qsTr("Leather"), qsTr("Paper")]]
+
+
+
+ property var model: root.materialsNames[root.currentCategory]
+
+} \ No newline at end of file
diff --git a/tests/auto/quick/qquickdesignersupport/data/regTestProperties.qml b/tests/auto/quick/qquickdesignersupport/data/regTestProperties.qml
new file mode 100644
index 0000000000..5ea3f58aff
--- /dev/null
+++ b/tests/auto/quick/qquickdesignersupport/data/regTestProperties.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.11
+
+Rectangle {
+ objectName: "rootItem"
+ color: "white"
+ width: 800
+ height: 600
+
+ RegTestComponent {
+ objectName: "testComponent"
+
+ }
+}
diff --git a/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp b/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp
index c35f31b8f2..bdc8f97d3a 100644
--- a/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp
+++ b/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -41,6 +42,7 @@ private slots:
void testDotProperties();
void testItemReparenting();
void testPropertyNames();
+ void regressionTestAllProperties();
};
@@ -557,14 +559,15 @@ void doComponentCompleteRecursive(QObject *object)
QList<QObject*> childList = object->children();
if (item) {
- foreach (QQuickItem *childItem, item->childItems()) {
+ const auto childItems = item->childItems();
+ for (QQuickItem *childItem : childItems) {
if (!childList.contains(childItem))
childList.append(childItem);
}
}
- foreach (QObject *child, childList)
- doComponentCompleteRecursive(child);
+ for (QObject *child : std::as_const(childList))
+ doComponentCompleteRecursive(child);
if (item) {
static_cast<QQmlParserStatus*>(item)->componentComplete();
@@ -781,6 +784,37 @@ void tst_qquickdesignersupport::testPropertyNames()
QVERIFY(!names.contains("testProperty"));
}
+void tst_qquickdesignersupport::regressionTestAllProperties()
+{
+ QScopedPointer<QQuickView> view(new QQuickView);
+ view->engine()->setOutputWarningsToStandardError(false);
+ view->setSource(testFileUrl("regTestProperties.qml"));
+
+ QVERIFY(view->errors().isEmpty());
+ QQuickItem *rootItem = view->rootObject();
+ QVERIFY(rootItem);
+
+ QObject *component = rootItem->findChild<QObject*>("testComponent");
+
+ QVERIFY(component);
+ QCOMPARE(component->objectName(), QLatin1String("testComponent"));
+
+ QVERIFY(component);
+
+ QQuickDesignerSupport::PropertyNameList names
+ = QQuickDesignerSupportProperties::allPropertyNames(component);
+ QVERIFY(!names.isEmpty());
+
+ const QByteArrayList expectedNames = QByteArrayList {
+ "objectName", "currentCategory", "materialsNames", "model"
+ };
+
+ QCOMPARE(names, expectedNames);
+ names = QQuickDesignerSupportProperties::propertyNameListForWritableProperties(component);
+ QVERIFY(!names.isEmpty());
+ QCOMPARE(names, expectedNames);
+}
+
QTEST_MAIN(tst_qquickdesignersupport)
#include "tst_qquickdesignersupport.moc"
diff --git a/tests/auto/quick/qquickdrag/CMakeLists.txt b/tests/auto/quick/qquickdrag/CMakeLists.txt
index afd184dfd9..73e8c64bb7 100644
--- a/tests/auto/quick/qquickdrag/CMakeLists.txt
+++ b/tests/auto/quick/qquickdrag/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickdrag Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickdrag LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qquickdrag
SOURCES
tst_qquickdrag.cpp
diff --git a/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp b/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
index d805bc19a1..b17b16b429 100644
--- a/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
+++ b/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
diff --git a/tests/auto/quick/qquickdragattached/CMakeLists.txt b/tests/auto/quick/qquickdragattached/CMakeLists.txt
index 7145b4bac7..822e38861e 100644
--- a/tests/auto/quick/qquickdragattached/CMakeLists.txt
+++ b/tests/auto/quick/qquickdragattached/CMakeLists.txt
@@ -1,3 +1,15 @@
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickdragattached LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+# Collect test data
+file(GLOB_RECURSE test_data_glob
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ data/*)
+list(APPEND test_data ${test_data_glob})
+
qt_internal_add_test(tst_qquickdragattached
SOURCES
tst_qquickdragattached.cpp
@@ -8,4 +20,19 @@ qt_internal_add_test(tst_qquickdragattached
Qt::Network
Qt::QmlPrivate
Qt::QuickPrivate
+ Qt::QuickTestUtilsPrivate
+ TESTDATA ${test_data}
+)
+
+## Scopes:
+#####################################################################
+
+qt_internal_extend_target(tst_qquickdragattached CONDITION ANDROID OR IOS
+ DEFINES
+ QT_QMLTEST_DATADIR=":/data"
+)
+
+qt_internal_extend_target(tst_qquickdragattached CONDITION NOT ANDROID AND NOT IOS
+ DEFINES
+ QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
)
diff --git a/tests/auto/quick/qquickdragattached/data/qt_logo.svg b/tests/auto/quick/qquickdragattached/data/qt_logo.svg
new file mode 100644
index 0000000000..062daff3e9
--- /dev/null
+++ b/tests/auto/quick/qquickdragattached/data/qt_logo.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ width="462pt"
+ height="339pt"
+ viewBox="0 0 462 339"
+ version="1.1"
+ id="svg2"
+>
+ <path
+ fill="#41cd52"
+ d=" M 63.50 0.00 L 462.00 0.00 L 462.00 274.79 C 440.60 296.26 419.13 317.66 397.61 339.00 L 0.00 339.00 L 0.00 63.39 C 21.08 42.18 42.34 21.13 63.50 0.00 Z"
+ id="path6"/>
+ <path
+ d=" M 122.37 71.33 C 137.50 61.32 156.21 58.79 174.00 58.95 C 190.94 59.16 208.72 62.13 222.76 72.24 C 232.96 79.41 239.59 90.48 244.01 101.93 C 251.16 120.73 253.26 141.03 253.50 161.01 C 253.53 181.13 252.62 201.69 245.96 220.86 C 241.50 233.90 233.01 245.48 221.81 253.52 C 229.87 266.58 238.09 279.54 246.15 292.60 C 236.02 297.27 225.92 301.97 215.78 306.62 C 207.15 292.38 198.56 278.11 189.90 263.89 C 178.19 265.81 166.21 265.66 154.44 264.36 C 140.34 262.67 125.97 258.37 115.09 248.88 C 106.73 241.64 101.48 231.51 97.89 221.21 C 92.01 203.79 90.43 185.25 90.16 166.97 C 90.02 147.21 91.28 127.14 97.24 108.18 C 101.85 93.92 109.48 79.69 122.37 71.33 Z"
+ id="path8"
+ fill="#ffffff"/>
+ <path
+ d=" M 294.13 70.69 C 304.73 70.68 315.33 70.68 325.93 70.69 C 325.96 84.71 325.92 98.72 325.95 112.74 C 339.50 112.76 353.05 112.74 366.60 112.75 C 366.37 121.85 366.12 130.95 365.86 140.05 C 352.32 140.08 338.79 140.04 325.25 140.07 C 325.28 163.05 325.18 186.03 325.30 209.01 C 325.56 215.30 325.42 221.94 328.19 227.75 C 330.21 232.23 335.65 233.38 340.08 233.53 C 348.43 233.50 356.77 233.01 365.12 232.86 C 365.63 241.22 366.12 249.59 366.60 257.95 C 349.99 260.74 332.56 264.08 316.06 258.86 C 309.11 256.80 302.63 252.19 299.81 245.32 C 294.76 233.63 294.35 220.62 294.13 208.07 C 294.11 185.40 294.13 162.74 294.12 140.07 C 286.73 140.05 279.34 140.08 271.95 140.05 C 271.93 130.96 271.93 121.86 271.95 112.76 C 279.34 112.73 286.72 112.77 294.11 112.74 C 294.14 98.72 294.10 84.71 294.13 70.69 Z"
+ id="path10"
+ fill="#ffffff"/>
+ <path
+ fill="#41cd52"
+ d=" M 160.51 87.70 C 170.80 86.36 181.60 86.72 191.34 90.61 C 199.23 93.73 205.93 99.84 209.47 107.58 C 214.90 119.31 216.98 132.26 218.03 145.05 C 219.17 162.07 219.01 179.25 216.66 196.17 C 215.01 206.24 212.66 216.85 205.84 224.79 C 198.92 232.76 188.25 236.18 178.01 236.98 C 167.21 237.77 155.82 236.98 146.07 231.87 C 140.38 228.84 135.55 224.09 132.73 218.27 C 129.31 211.30 127.43 203.69 126.11 196.07 C 122.13 171.91 121.17 146.91 126.61 122.89 C 128.85 113.83 132.11 104.53 138.73 97.70 C 144.49 91.85 152.51 88.83 160.51 87.70 Z"
+ id="path12"/>
+</svg>
diff --git a/tests/auto/quick/qquickdragattached/tst_qquickdragattached.cpp b/tests/auto/quick/qquickdragattached/tst_qquickdragattached.cpp
index 19e35703fd..243d767c80 100644
--- a/tests/auto/quick/qquickdragattached/tst_qquickdragattached.cpp
+++ b/tests/auto/quick/qquickdragattached/tst_qquickdragattached.cpp
@@ -1,22 +1,35 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
#include <QtQuick/qquickwindow.h>
#include <QtQuick/private/qquickdrag_p_p.h>
-class tst_QQuickDragAttached: public QObject
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+
+class tst_QQuickDragAttached: public QQmlDataTest
{
Q_OBJECT
+public:
+ tst_QQuickDragAttached();
+
private slots:
void setMimeData_data();
void setMimeData();
+ void imageSourceSize_data();
+ void imageSourceSize();
+
void startDrag_data();
void startDrag();
};
+tst_QQuickDragAttached::tst_QQuickDragAttached()
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
+{
+}
+
void tst_QQuickDragAttached::setMimeData_data()
{
QTest::addColumn<QVariantMap>("mimeData");
@@ -53,9 +66,9 @@ void tst_QQuickDragAttached::setMimeData_data()
QTest::addRow("text/uri-list, variant")
<< makeMap("text/uri-list", QVariantList{QVariant("file://foo")})
<< QStringList{"text/uri-list"};
- QTest::addRow("mismatch image")
- << makeMap("image/png", "not an image")
- << QStringList{};
+ QTest::addRow("application/json")
+ << makeMap("application/json", "{}")
+ << QStringList{"application/json"};
QTest::addRow("missing charset")
<< makeMap("text/plain;charset=", QString("foo"))
<< QStringList{};
@@ -91,6 +104,45 @@ void tst_QQuickDragAttached::setMimeData()
QCOMPARE(spy.count(), expectedCount);
}
+void tst_QQuickDragAttached::imageSourceSize_data()
+{
+ QTest::addColumn<bool>("sizeFirst");
+ QTest::addColumn<QSize>("imageSourceSize");
+ QTest::addColumn<QSize>("expectedSourceSize");
+ QTest::addColumn<QSize>("expectedImageSize");
+
+ QTest::addRow("default size") << false << QSize() << QSize(462, 339) << QSize(462, 339);
+ QTest::addRow("shrunken elongated") << false << QSize(214, 114) << QSize(214, 114) << QSize(214, 114);
+ QTest::addRow("width, neg height") << false << QSize(154, -1) << QSize(154, 339) << QSize(154, 339);
+ QTest::addRow("width, zero height") << false << QSize(154, 0) << QSize(154, 0) << QSize(154, 113);
+
+ QTest::addRow("size first: default size") << true << QSize() << QSize(462, 339) << QSize(462, 339);
+ QTest::addRow("size first: shrunken elongated") << true << QSize(214, 114) << QSize(214, 114) << QSize(214, 114);
+ QTest::addRow("size first: width, neg height") << true << QSize(154, -1) << QSize(154, 113) << QSize(154, 113);
+ QTest::addRow("size first: width, zero height") << true << QSize(154, 0) << QSize(154, 0) << QSize(154, 113);
+}
+
+void tst_QQuickDragAttached::imageSourceSize()
+{
+ QFETCH(bool, sizeFirst);
+ QFETCH(QSize, imageSourceSize);
+ QFETCH(QSize, expectedSourceSize);
+ QFETCH(QSize, expectedImageSize);
+
+ QQuickDragAttached attached(nullptr);
+ QSignalSpy spy(&attached, &QQuickDragAttached::imageSourceSizeChanged);
+
+ if (sizeFirst)
+ attached.setImageSourceSize(imageSourceSize);
+ attached.setImageSource(testFileUrl("qt_logo.svg"));
+ attached.setImageSourceSize(imageSourceSize);
+
+ const int expectedCount = imageSourceSize.width() >= 0 || imageSourceSize.height() >= 0 ? 1 : 0;
+ QCOMPARE(spy.count(), expectedCount);
+ QCOMPARE(attached.imageSourceSize(), expectedSourceSize);
+ QCOMPARE(QQuickDragAttachedPrivate::get(&attached)->pixmapLoader.image().size(), expectedImageSize);
+}
+
void tst_QQuickDragAttached::startDrag_data()
{
setMimeData_data();
@@ -116,7 +168,11 @@ void tst_QQuickDragAttached::startDrag()
std::unique_ptr<QMimeData> data(d->createMimeData());
QVERIFY(data);
+ auto debugHelper = qScopeGuard([&data]{
+ qWarning() << data->formats();
+ });
QCOMPARE(data->formats(), formats);
+ debugHelper.dismiss();
#else
QSKIP("This test relies on private APIs that are only exported in developer-builds");
#endif
diff --git a/tests/auto/quick/qquickdroparea/CMakeLists.txt b/tests/auto/quick/qquickdroparea/CMakeLists.txt
index b39eb08010..32d631f08c 100644
--- a/tests/auto/quick/qquickdroparea/CMakeLists.txt
+++ b/tests/auto/quick/qquickdroparea/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickdroparea Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickdroparea LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickdroparea/data/nested1.qml b/tests/auto/quick/qquickdroparea/data/nested1.qml
index 28a21ab4c0..430421d27b 100644
--- a/tests/auto/quick/qquickdroparea/data/nested1.qml
+++ b/tests/auto/quick/qquickdroparea/data/nested1.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
Item {
diff --git a/tests/auto/quick/qquickdroparea/data/nested2.qml b/tests/auto/quick/qquickdroparea/data/nested2.qml
index 7585792ff6..c7261ef1d5 100644
--- a/tests/auto/quick/qquickdroparea/data/nested2.qml
+++ b/tests/auto/quick/qquickdroparea/data/nested2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
Item {
diff --git a/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp b/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
index fb036b6fad..f861eb37f2 100644
--- a/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
+++ b/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
diff --git a/tests/auto/quick/qquickdynamicpropertyanimation/CMakeLists.txt b/tests/auto/quick/qquickdynamicpropertyanimation/CMakeLists.txt
index d7db4ff504..b9834a7a72 100644
--- a/tests/auto/quick/qquickdynamicpropertyanimation/CMakeLists.txt
+++ b/tests/auto/quick/qquickdynamicpropertyanimation/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickdynamicpropertyanimation Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickdynamicpropertyanimation LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickdynamicpropertyanimation/tst_qquickdynamicpropertyanimation.cpp b/tests/auto/quick/qquickdynamicpropertyanimation/tst_qquickdynamicpropertyanimation.cpp
index 7c875fb853..85ff58fd4d 100644
--- a/tests/auto/quick/qquickdynamicpropertyanimation/tst_qquickdynamicpropertyanimation.cpp
+++ b/tests/auto/quick/qquickdynamicpropertyanimation/tst_qquickdynamicpropertyanimation.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQml/QQmlEngine>
#include <QtQml/QQmlProperty>
diff --git a/tests/auto/quick/qquickflickable/BLACKLIST b/tests/auto/quick/qquickflickable/BLACKLIST
index 2430735613..a481b96db5 100644
--- a/tests/auto/quick/qquickflickable/BLACKLIST
+++ b/tests/auto/quick/qquickflickable/BLACKLIST
@@ -1,5 +1,10 @@
[movingAndFlicking]
macos-11
+opensuse-leap # QTBUG-118060
[flickVelocity]
macos-11
+
+# QTBUG-118060
+[ignoreNonLeftMouseButtons]
+opensuse-leap
diff --git a/tests/auto/quick/qquickflickable/CMakeLists.txt b/tests/auto/quick/qquickflickable/CMakeLists.txt
index 44860d32bc..e46378188d 100644
--- a/tests/auto/quick/qquickflickable/CMakeLists.txt
+++ b/tests/auto/quick/qquickflickable/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickflickable Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickflickable LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickflickable/data/endpoints.qml b/tests/auto/quick/qquickflickable/data/endpoints.qml
new file mode 100644
index 0000000000..80caa32da5
--- /dev/null
+++ b/tests/auto/quick/qquickflickable/data/endpoints.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+Flickable {
+ width: 100; height: 100
+ contentWidth: row.width; contentHeight: row.height
+
+ Row {
+ id: row
+ Repeater {
+ model: 4
+ Rectangle { width: 200; height: 300; color: "blue" }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickflickable/data/flickableWithTapHandler.qml b/tests/auto/quick/qquickflickable/data/flickableWithTapHandler.qml
new file mode 100644
index 0000000000..91b81059ab
--- /dev/null
+++ b/tests/auto/quick/qquickflickable/data/flickableWithTapHandler.qml
@@ -0,0 +1,24 @@
+import QtQuick
+
+Item {
+ width: 300
+ height: 300
+
+ Flickable {
+ anchors.fill: parent
+ anchors.topMargin: 100
+ contentWidth: 1000
+ contentHeight: 1000
+
+ Rectangle {
+ objectName: "childItem"
+ x: 20
+ y: 50
+ width: 20
+ height: 20
+ color: "red"
+ TapHandler {
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickflickable/data/nested.qml b/tests/auto/quick/qquickflickable/data/nested.qml
index 7fa331c46c..0cbeb5cef3 100644
--- a/tests/auto/quick/qquickflickable/data/nested.qml
+++ b/tests/auto/quick/qquickflickable/data/nested.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
Flickable {
diff --git a/tests/auto/quick/qquickflickable/data/overshoot.qml b/tests/auto/quick/qquickflickable/data/overshoot.qml
index be908584f1..baa1bfea01 100644
--- a/tests/auto/quick/qquickflickable/data/overshoot.qml
+++ b/tests/auto/quick/qquickflickable/data/overshoot.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.9
diff --git a/tests/auto/quick/qquickflickable/data/overshoot_reentrant.qml b/tests/auto/quick/qquickflickable/data/overshoot_reentrant.qml
index 2fa80a7d18..7bbe45907c 100644
--- a/tests/auto/quick/qquickflickable/data/overshoot_reentrant.qml
+++ b/tests/auto/quick/qquickflickable/data/overshoot_reentrant.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.9
diff --git a/tests/auto/quick/qquickflickable/data/parallel.qml b/tests/auto/quick/qquickflickable/data/parallel.qml
index bef8af3b37..8e7f64a84e 100644
--- a/tests/auto/quick/qquickflickable/data/parallel.qml
+++ b/tests/auto/quick/qquickflickable/data/parallel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickflickable/data/pressDelay.qml b/tests/auto/quick/qquickflickable/data/pressDelay.qml
index a69c4af6de..97bc6b794f 100644
--- a/tests/auto/quick/qquickflickable/data/pressDelay.qml
+++ b/tests/auto/quick/qquickflickable/data/pressDelay.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick
Flickable {
flickableDirection: Flickable.VerticalFlick
@@ -15,7 +15,6 @@ Flickable {
MouseArea {
id: ma
- objectName: "mouseArea"
y: 100
anchors.horizontalCenter: parent.horizontalCenter
width: 240
@@ -32,14 +31,7 @@ Flickable {
Rectangle {
anchors.fill: parent
- color: parent.pressed ? 'blue' : 'green'
-
- Text {
- anchors.fill: parent
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- text: 'Hello'
- }
+ color: parent.pressed ? 'blue' : 'lightsteelblue'
}
}
}
diff --git a/tests/auto/quick/qquickflickable/data/ratios.qml b/tests/auto/quick/qquickflickable/data/ratios.qml
index a7e927cce1..7983b797fe 100644
--- a/tests/auto/quick/qquickflickable/data/ratios.qml
+++ b/tests/auto/quick/qquickflickable/data/ratios.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickflickable/data/visibleAreaBinding.qml b/tests/auto/quick/qquickflickable/data/visibleAreaBinding.qml
index 8a091f0906..a52f612af7 100644
--- a/tests/auto/quick/qquickflickable/data/visibleAreaBinding.qml
+++ b/tests/auto/quick/qquickflickable/data/visibleAreaBinding.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.14
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index ab21415235..e13a818cf8 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
@@ -8,6 +8,7 @@
#include <QtGui/QStyleHints>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
+#include <private/qguiapplication_p.h>
#include <private/qquickflickable_p.h>
#include <private/qquickflickable_p_p.h>
#include <private/qquickmousearea_p.h>
@@ -15,6 +16,7 @@
#include <private/qqmlvaluetype_p.h>
#include <private/qquicktaphandler_p.h>
#include <math.h>
+#include <QtGui/qpa/qplatformintegration.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/geometrytestutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
@@ -165,6 +167,7 @@ private slots:
void rebound();
void maximumFlickVelocity();
void flickDeceleration();
+ void pressDelay_data();
void pressDelay();
void nestedPressDelay();
void filterReplayedPress();
@@ -174,6 +177,7 @@ private slots:
void returnToBounds();
void returnToBounds_data();
void wheel();
+ void wheelBackwards();
void trackpad();
void nestedTrackpad();
void movingAndFlicking();
@@ -217,14 +221,24 @@ private slots:
void receiveTapOutsideContentItem();
void flickWhenRotated_data();
void flickWhenRotated();
+ void flickAndReleaseOutsideBounds();
void scrollingWithFractionalExtentSize_data();
void scrollingWithFractionalExtentSize();
void setContentPositionWhileDragging_data();
void setContentPositionWhileDragging();
+ void coalescedMove();
+ void onlyOneMove();
+ void proportionalWheelScrolling();
+ void touchCancel();
+ void pixelAlignedEndPoints();
private:
void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to);
QPointingDevice *touchDevice = QTest::createTouchDevice();
+ const QPointingDevice *mouseDevice = new QPointingDevice(
+ "test mouse", 1000, QInputDevice::DeviceType::Mouse, QPointingDevice::PointerType::Generic,
+ QInputDevice::Capability::Position | QInputDevice::Capability::Hover | QInputDevice::Capability::Scroll,
+ 1, 5, QString(), QPointingDeviceUniqueId(), this);
};
void tst_qquickflickable::initTestCase()
@@ -234,6 +248,8 @@ void tst_qquickflickable::initTestCase()
#endif
QQmlDataTest::initTestCase();
qmlRegisterType<TouchDragArea>("Test",1,0,"TouchDragArea");
+ touchDevice->setParent(this); // avoid leak
+ QWindowSystemInterface::registerInputDevice(mouseDevice);
}
void tst_qquickflickable::cleanup()
@@ -519,45 +535,54 @@ void tst_qquickflickable::flickDeceleration()
delete flickable;
}
+void tst_qquickflickable::pressDelay_data()
+{
+ QTest::addColumn<const QPointingDevice *>("device");
+ const QPointingDevice *constTouchDevice = touchDevice;
+
+ QTest::newRow("mouse") << mouseDevice;
+ QTest::newRow("touch") << constTouchDevice;
+}
+
void tst_qquickflickable::pressDelay()
{
- QScopedPointer<QQuickView> window(new QQuickView);
- window->setSource(testFileUrl("pressDelay.qml"));
- QTRY_COMPARE(window->status(), QQuickView::Ready);
- QQuickViewTestUtils::centerOnScreen(window.data());
- QQuickViewTestUtils::moveMouseAway(window.data());
- window->show();
- QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != nullptr);
+ QFETCH(const QPointingDevice *, device);
- QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
- QSignalSpy spy(flickable, SIGNAL(pressDelayChanged()));
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("pressDelay.qml")));
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window.rootObject());
QVERIFY(flickable);
- QCOMPARE(flickable->pressDelay(), 100);
+ QQuickMouseArea *mouseArea = flickable->findChild<QQuickMouseArea*>();
+ QSignalSpy clickedSpy(mouseArea, &QQuickMouseArea::clicked);
+ // Test the pressDelay property itself
+ QSignalSpy pressDelayChangedSpy(flickable, &QQuickFlickable::pressDelayChanged);
+ QCOMPARE(flickable->pressDelay(), 100);
flickable->setPressDelay(200);
QCOMPARE(flickable->pressDelay(), 200);
- QCOMPARE(spy.size(),1);
+ QCOMPARE(pressDelayChangedSpy.size(), 1);
flickable->setPressDelay(200);
- QCOMPARE(spy.size(),1);
+ QCOMPARE(pressDelayChangedSpy.size(), 1);
- QQuickItem *mouseArea = window->rootObject()->findChild<QQuickItem*>("mouseArea");
- QSignalSpy clickedSpy(mouseArea, SIGNAL(clicked(QQuickMouseEvent*)));
- moveAndPress(window.data(), QPoint(150, 150));
+ // Test the press delay
+ QPoint p(150, 150);
+ if (device->type() == QInputDevice::DeviceType::Mouse)
+ QQuickTest::pointerMove(device, &window, 0, p);
+ QQuickTest::pointerPress(device, &window, 0, p);
// The press should not occur immediately
- QVERIFY(!mouseArea->property("pressed").toBool());
+ QCOMPARE(mouseArea->isPressed(), false);
// But, it should occur eventually
- QTRY_VERIFY(mouseArea->property("pressed").toBool());
+ QTRY_VERIFY(mouseArea->isPressed());
- QCOMPARE(clickedSpy.size(),0);
+ QCOMPARE(clickedSpy.size(), 0);
// On release the clicked signal should be emitted
- QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(150, 150));
- QCOMPARE(clickedSpy.size(),1);
+ QQuickTest::pointerRelease(device, &window, 0, p);
+ QCOMPARE(clickedSpy.size(), 1);
// Press and release position should match
QCOMPARE(flickable->property("pressX").toReal(), flickable->property("releaseX").toReal());
@@ -565,38 +590,44 @@ void tst_qquickflickable::pressDelay()
// Test a quick tap within the pressDelay timeout
+ p = QPoint(180, 180);
clickedSpy.clear();
- moveAndPress(window.data(), QPoint(180, 180));
+ if (device->type() == QInputDevice::DeviceType::Mouse)
+ QQuickTest::pointerMove(device, &window, 0, p);
+ QQuickTest::pointerPress(device, &window, 0, p);
// The press should not occur immediately
- QVERIFY(!mouseArea->property("pressed").toBool());
+ QCOMPARE(mouseArea->isPressed(), false);
+ QCOMPARE(clickedSpy.size(), 0);
- QCOMPARE(clickedSpy.size(),0);
-
- // On release the press, release and clicked signal should be emitted
- QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(180, 180));
- QCOMPARE(clickedSpy.size(),1);
+ // On release, the press, release and clicked signal should be emitted
+ QQuickTest::pointerRelease(device, &window, 0, p);
+ QCOMPARE(clickedSpy.size(), 1);
// Press and release position should match
QCOMPARE(flickable->property("pressX").toReal(), flickable->property("releaseX").toReal());
QCOMPARE(flickable->property("pressY").toReal(), flickable->property("releaseY").toReal());
- // QTBUG-31168
- moveAndPress(window.data(), QPoint(150, 110));
+ // Test flick after press (QTBUG-31168)
+ QPoint startPosition(150, 110);
+ p = QPoint(150, 190);
+ clickedSpy.clear();
+ if (device->type() == QInputDevice::DeviceType::Mouse)
+ QQuickTest::pointerMove(device, &window, 0, startPosition);
+ QQuickTest::pointerPress(device, &window, 0, startPosition);
// The press should not occur immediately
- QVERIFY(!mouseArea->property("pressed").toBool());
-
- QTest::mouseMove(window.data(), QPoint(150, 190));
+ QCOMPARE(mouseArea->isPressed(), false);
+ QQuickTest::pointerMove(device, &window, 0, p);
- // As we moved pass the drag threshold, we should never receive the press
- QVERIFY(!mouseArea->property("pressed").toBool());
- QTRY_VERIFY(!mouseArea->property("pressed").toBool());
+ // Since we moved past the drag threshold, we should never receive the press
+ QCOMPARE(mouseArea->isPressed(), false);
+ QTRY_COMPARE(mouseArea->isPressed(), false);
- // On release the clicked signal should *not* be emitted
- QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(150, 190));
- QCOMPARE(clickedSpy.size(),1);
+ // On release, the clicked signal should *not* be emitted
+ QQuickTest::pointerRelease(device, &window, 0, p);
+ QCOMPARE(clickedSpy.size(), 0);
}
// QTBUG-17361
@@ -935,6 +966,47 @@ void tst_qquickflickable::wheel()
QCOMPARE(flick->property("movementsAfterEnd").value<int>(), 0); // QTBUG-55886
}
+void tst_qquickflickable::wheelBackwards() // (QTBUG-121349)
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("wheel.qml")));
+ QQuickFlickable *flick = window.rootObject()->findChild<QQuickFlickable*>("flick");
+ QVERIFY(flick);
+ QSignalSpy moveEndSpy(flick, SIGNAL(movementEnded()));
+ quint64 timestamp = 10;
+ const QPoint pos(200, 200);
+
+ // attempting to scroll vertically "backwards" beyond extents does not initiate overshoot
+ {
+ QWheelEvent event(pos, window.mapToGlobal(pos), QPoint(), QPoint(0, 120),
+ Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
+ event.setAccepted(false);
+ event.setTimestamp(timestamp++);
+ QGuiApplication::sendEvent(&window, &event);
+ }
+ QCOMPARE(flick->contentY(), qreal(0));
+ QCOMPARE(flick->isMoving(), false);
+ QCOMPARE(moveEndSpy.size(), 0);
+
+ // get ready to test horizontal wheel
+ flick->setContentY(0); // which triggers movementEnded again
+ flick->setProperty("movementsAfterEnd", 0);
+ flick->setProperty("ended", false);
+ QCOMPARE(flick->contentY(), qreal(0));
+
+ // attempting to scroll horizontally "backwards" beyond extents does not initiate overshoot
+ {
+ QWheelEvent event(pos, window.mapToGlobal(pos), QPoint(), QPoint(120, 0),
+ Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
+ event.setAccepted(false);
+ event.setTimestamp(timestamp);
+ QGuiApplication::sendEvent(&window, &event);
+ }
+ QCOMPARE(flick->contentX(), qreal(0));
+ QCOMPARE(flick->isMoving(), false);
+ QCOMPARE(moveEndSpy.size(), 0);
+}
+
void tst_qquickflickable::trackpad()
{
QScopedPointer<QQuickView> window(new QQuickView);
@@ -1621,7 +1693,7 @@ void tst_qquickflickable::flickVelocity()
QTRY_VERIFY(flickable->verticalVelocity() < 0.0);
QTRY_COMPARE(flickable->verticalVelocity(), 0.0);
-#ifdef Q_OS_MAC
+#ifdef Q_OS_MACOS
QSKIP("boost doesn't work on OS X");
return;
#endif
@@ -2872,7 +2944,7 @@ void tst_qquickflickable::receiveTapOutsideContentItem()
QVERIFY(QTest::qWaitForWindowActive(&window));
QQuickTapHandler tapHandler(&flickable);
- QSignalSpy clickedSpy(&tapHandler, SIGNAL(tapped(QEventPoint, Qt::MouseButton)));
+ QSignalSpy clickedSpy(&tapHandler, SIGNAL(tapped(QEventPoint,Qt::MouseButton)));
// Tap outside the content item in the top-left corner
QTest::mouseClick(&window, Qt::LeftButton, {}, QPoint(5, 5));
@@ -2935,6 +3007,42 @@ void tst_qquickflickable::flickWhenRotated() // QTBUG-99639
QVERIFY(!flickable->isAtYBeginning());
}
+void tst_qquickflickable::flickAndReleaseOutsideBounds() // QTBUG-104987
+{
+ // Check that flicking works when the mouse release happens
+ // outside the bounds of the flickable (and the flick started on top
+ // of a TapHandler that has a passive grab).
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("flickableWithTapHandler.qml")));
+ QQuickItem *rootItem = window.rootObject();
+ QVERIFY(rootItem);
+ QQuickFlickable *flickable = rootItem->findChild<QQuickFlickable*>();
+ QVERIFY(flickable);
+ QQuickItem *childItem = flickable->findChild<QQuickItem*>("childItem");
+ QVERIFY(childItem);
+
+ QVERIFY(flickable->isAtYBeginning());
+
+ // Startpoint is on top of the tapHandler, while the endpoint is outside the flickable
+ const QPointF startPos = childItem->mapToGlobal(QPoint(10, 10));
+ const QPointF endPos = flickable->mapToGlobal(QPoint(10, -10));
+ const QPoint globalStartPos = window.mapFromGlobal(startPos).toPoint();
+ const QPoint globalEndPos = window.mapFromGlobal(endPos).toPoint();
+ const qreal dragDistance = 20;
+
+ // Note: here we need to initiate a flick using raw events, rather than
+ // flickable.flick(), since we're testing if the mouse events takes the
+ // correct path to starts a flick (among passive and exclusive grabbers, combined
+ // with childMouseEventFilter()).
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, globalStartPos);
+ QTest::mouseMove(&window, globalStartPos - QPoint(0, dragDistance / 2));
+ QTest::mouseMove(&window, globalStartPos - QPoint(0, dragDistance));
+ QTest::mouseMove(&window, globalEndPos);
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, globalEndPos);
+
+ // Ensure that the content item ends up being moved more than what we dragged
+ QTRY_VERIFY(flickable->contentY() > dragDistance * 2);
+}
void tst_qquickflickable::scrollingWithFractionalExtentSize_data()
{
@@ -3123,6 +3231,207 @@ void tst_qquickflickable::setContentPositionWhileDragging() // QTBUG-104966
QVERIFY(!flickable->isDragging());
}
+void tst_qquickflickable::coalescedMove()
+{
+ QQuickView *window = new QQuickView;
+ QScopedPointer<QQuickView> windowPtr(window);
+ windowPtr->setSource(testFileUrl("flickable03.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickVisualTestUtils::centerOnScreen(window);
+ QQuickVisualTestUtils::moveMouseAway(window);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+ QVERIFY(window->rootObject() != nullptr);
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
+ QVERIFY(flickable != nullptr);
+
+ QSignalSpy movementStartedSpy(flickable, SIGNAL(movementStarted()));
+ QSignalSpy movementEndedSpy(flickable, SIGNAL(movementEnded()));
+ QSignalSpy flickStartedSpy(flickable, SIGNAL(flickStarted()));
+ QSignalSpy flickEndedSpy(flickable, SIGNAL(flickEnded()));
+
+ QTest::touchEvent(window, touchDevice).press(0, {10, 10}).commit();
+
+ QTest::touchEvent(window, touchDevice).move(0, {10, 40}).commit();
+
+ QTest::touchEvent(window, touchDevice).move(0, {10, 100}).commit();
+
+ QTest::touchEvent(window, touchDevice).release(0, {10, 150}).commit();
+ QQuickTouchUtils::flush(window);
+
+ QTRY_VERIFY(!flickable->isMoving());
+
+ QCOMPARE(movementStartedSpy.size(), 1);
+ QCOMPARE(flickStartedSpy.size(), 1);
+ QCOMPARE(movementEndedSpy.size(), 1);
+ QCOMPARE(flickEndedSpy.size(), 1);
+}
+
+void tst_qquickflickable::onlyOneMove()
+{
+ QQuickView *window = new QQuickView;
+ QScopedPointer<QQuickView> windowPtr(window);
+ windowPtr->setSource(testFileUrl("flickable03.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickVisualTestUtils::centerOnScreen(window);
+ QQuickVisualTestUtils::moveMouseAway(window);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+ QVERIFY(window->rootObject() != nullptr);
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
+ QVERIFY(flickable != nullptr);
+
+ QSignalSpy movementStartedSpy(flickable, SIGNAL(movementStarted()));
+ QSignalSpy movementEndedSpy(flickable, SIGNAL(movementEnded()));
+ QSignalSpy flickStartedSpy(flickable, SIGNAL(flickStarted()));
+ QSignalSpy flickEndedSpy(flickable, SIGNAL(flickEnded()));
+
+ QTest::touchEvent(window, touchDevice).press(0, {10, 10}).commit();
+ QQuickTouchUtils::flush(window);
+
+ QTest::touchEvent(window, touchDevice).move(0, {10, 100}).commit();
+ QQuickTouchUtils::flush(window);
+
+ QTest::touchEvent(window, touchDevice).release(0, {10, 200}).commit();
+ QQuickTouchUtils::flush(window);
+
+ QTRY_VERIFY(!flickable->isMoving());
+
+ QCOMPARE(movementStartedSpy.size(), 1);
+ QCOMPARE(flickStartedSpy.size(), 1);
+ QCOMPARE(movementEndedSpy.size(), 1);
+ QCOMPARE(flickEndedSpy.size(), 1);
+}
+
+void tst_qquickflickable::proportionalWheelScrolling() // QTBUG-106338 etc.
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("wheel.qml")));
+ QQuickViewTestUtils::centerOnScreen(&window);
+ QVERIFY(window.isVisible());
+ QQuickItem *rootItem = window.rootObject();
+ QVERIFY(rootItem);
+ QQuickFlickable *flickable = rootItem->findChild<QQuickFlickable *>();
+ QVERIFY(flickable);
+
+ QVERIFY(!flickable->property("ended").value<bool>());
+
+ QPointF pos(flickable->x() + flickable->width() / 2, flickable->y() + flickable->height() / 2);
+ QPoint angleDelta(0, -120);
+ QWheelEvent wheelEvent(pos, window.mapToGlobal(pos), QPoint(), angleDelta,
+ Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
+
+ QGuiApplication::sendEvent(&window, &wheelEvent);
+ qApp->processEvents();
+
+ // Verify that scrolling is proportional to the wheel delta
+ QVERIFY(flickable->isMovingVertically());
+ QTRY_VERIFY(!flickable->isMovingVertically());
+
+ // The current movement formula being used is: delta / 120 * wheelScrollLines * 24
+ const int defaultWheelDecel = 15000;
+ bool wheelDecelerationEnvSet = false;
+ const int wheelDecelerationEnv = qEnvironmentVariableIntValue("QT_QUICK_FLICKABLE_WHEEL_DECELERATION", &wheelDecelerationEnvSet);
+ const qreal wheelDecel = wheelDecelerationEnvSet ? wheelDecelerationEnv : defaultWheelDecel;
+ const bool proportionalWheel = wheelDecel >= 15000;
+ qCDebug(lcTests) << "platform wheel decel" << defaultWheelDecel
+ << "env wheel decel" << wheelDecelerationEnv
+ << "expect proportional scrolling?" << proportionalWheel;
+ const qreal expectedMovementFromWheelClick = qAbs(angleDelta.y()) / 120 * qApp->styleHints()->wheelScrollLines() * 24;
+
+ if (proportionalWheel)
+ QCOMPARE(flickable->contentY(), expectedMovementFromWheelClick);
+
+ QVERIFY(flickable->property("ended").value<bool>());
+ QCOMPARE(flickable->property("movementsAfterEnd").value<int>(), 0);
+
+ flickable->setProperty("ended", QVariant::fromValue(false));
+ flickable->setContentY(0);
+
+ // Verify that multiple wheel events in a row won't accumulate the scroll distance, before the timeline completes
+ wheelEvent.setTimestamp(wheelEvent.timestamp() + 2000);
+ QGuiApplication::sendEvent(&window, &wheelEvent);
+
+ wheelEvent.setTimestamp(wheelEvent.timestamp() + 10);
+ QGuiApplication::sendEvent(&window, &wheelEvent);
+
+ wheelEvent.setTimestamp(wheelEvent.timestamp() + 10);
+ QGuiApplication::sendEvent(&window, &wheelEvent);
+
+ qApp->processEvents();
+
+ QVERIFY(flickable->isMovingVertically());
+ QTRY_VERIFY(!flickable->isMovingVertically());
+
+ if (proportionalWheel) {
+ QVERIFY2(flickable->contentY() >= expectedMovementFromWheelClick, "The contentItem moved shorter than expected from a wheelEvent");
+ QCOMPARE_LT(flickable->contentY(), expectedMovementFromWheelClick * 3);
+ }
+
+ QVERIFY(flickable->property("ended").value<bool>());
+ QCOMPARE(flickable->property("movementsAfterEnd").value<int>(), 0);
+}
+
+void tst_qquickflickable::touchCancel()
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("flickable03.qml")));
+ QQuickViewTestUtils::centerOnScreen(&window);
+ QVERIFY(window.isVisible());
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window.rootObject());
+ QVERIFY(flickable != nullptr);
+
+ QSignalSpy movementStartedSpy(flickable, SIGNAL(movementStarted()));
+ QSignalSpy movementEndedSpy(flickable, SIGNAL(movementEnded()));
+
+ int touchPosY = 10;
+ QTest::touchEvent(&window, touchDevice).press(0, {10, touchPosY}).commit();
+ QQuickTouchUtils::flush(&window);
+
+ for (int i = 0; i < 3; ++i) {
+ touchPosY += qApp->styleHints()->startDragDistance();
+ QTest::touchEvent(&window, touchDevice).move(0, {10, touchPosY}).commit();
+ QQuickTouchUtils::flush(&window);
+ }
+
+ QTRY_COMPARE(movementStartedSpy.size(), 1);
+ QWindowSystemInterface::handleTouchCancelEvent(nullptr, touchDevice);
+ QTRY_COMPARE(movementEndedSpy.size(), 1);
+}
+
+void tst_qquickflickable::pixelAlignedEndPoints()
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("endpoints.qml")));
+ QQuickViewTestUtils::centerOnScreen(&window);
+ QVERIFY(window.isVisible());
+ QQuickItem *rootItem = window.rootObject();
+ QVERIFY(rootItem);
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(rootItem);
+ QVERIFY(flickable);
+ flickable->setPixelAligned(true);
+ QVERIFY(flickable->isAtYBeginning());
+
+ QSignalSpy isAtEndSpy(flickable, &QQuickFlickable::atYEndChanged);
+ QSignalSpy isAtBeginningSpy(flickable, &QQuickFlickable::atYBeginningChanged);
+
+ flickable->setContentY(199.99);
+ QCOMPARE(flickable->contentY(), 200);
+ QVERIFY(!flickable->isAtYBeginning());
+ QVERIFY(flickable->isAtYEnd());
+ QCOMPARE(isAtEndSpy.count(), 1);
+ QCOMPARE(isAtBeginningSpy.count(), 1);
+
+ flickable->setContentY(0.01);
+ QCOMPARE(flickable->contentY(), 0);
+ QVERIFY(flickable->isAtYBeginning());
+ QVERIFY(!flickable->isAtYEnd());
+ QCOMPARE(isAtEndSpy.count(), 2);
+ QCOMPARE(isAtBeginningSpy.count(), 2);}
+
QTEST_MAIN(tst_qquickflickable)
#include "tst_qquickflickable.moc"
diff --git a/tests/auto/quick/qquickflipable/CMakeLists.txt b/tests/auto/quick/qquickflipable/CMakeLists.txt
index d764b1cfe4..f73d4f81d1 100644
--- a/tests/auto/quick/qquickflipable/CMakeLists.txt
+++ b/tests/auto/quick/qquickflipable/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickflipable Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickflipable LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickflipable/data/flip-y-axis-flipable.qml b/tests/auto/quick/qquickflipable/data/flip-y-axis-flipable.qml
new file mode 100644
index 0000000000..a52e1fd942
--- /dev/null
+++ b/tests/auto/quick/qquickflipable/data/flip-y-axis-flipable.qml
@@ -0,0 +1,32 @@
+// Copyright (C) 2023 UnionTech Software Technology Co., Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Flipable {
+ id: flipable
+
+ property real angle: 0
+ width: 3840 // wider than 1024 * 2: part of it goes behind the camera while flipping
+ height: 2160
+
+ front: Rectangle {
+ width: parent.width
+ height: parent.height
+ color: "red"
+ anchors.centerIn: parent
+ }
+ back: Rectangle {
+ color: "yellow"
+ anchors.centerIn: parent
+ width: parent.width
+ height: parent.height
+ }
+ transform: Rotation {
+ id: rotation
+ origin.x: flipable.width / 2
+ origin.y: flipable.height / 2
+ axis.x: 0; axis.y: 1; axis.z: 0
+ angle: flipable.angle
+ }
+}
diff --git a/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp b/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp
index c1eab29759..5941f32832 100644
--- a/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp
+++ b/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -27,6 +27,9 @@ private slots:
void QTBUG_9161_crash();
void QTBUG_8474_qgv_abort();
+ void flipRotationAngle_data();
+ void flipRotationAngle();
+
private:
QQmlEngine engine;
};
@@ -112,6 +115,31 @@ void tst_qquickflipable::QTBUG_8474_qgv_abort()
delete window;
}
+void tst_qquickflipable::flipRotationAngle_data()
+{
+ QTest::addColumn<int>("angle");
+ QTest::addColumn<QQuickFlipable::Side>("side");
+
+ QTest::newRow("89") << 89 << QQuickFlipable::Front;
+ QTest::newRow("91") << 91 << QQuickFlipable::Back;
+ QTest::newRow("-89") << -89 << QQuickFlipable::Front;
+ QTest::newRow("-91") << -91 << QQuickFlipable::Back;
+}
+
+void tst_qquickflipable::flipRotationAngle() // QTBUG-75954
+{
+ QFETCH(int, angle);
+ QFETCH(QQuickFlipable::Side, side);
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("flip-y-axis-flipable.qml"));
+ QQuickFlipable *obj = qobject_cast<QQuickFlipable*>(c.create());
+ QVERIFY(obj != nullptr);
+ obj->setProperty("angle", angle);
+ QCOMPARE(obj->side(), side);
+ delete obj;
+}
+
QTEST_MAIN(tst_qquickflipable)
#include "tst_qquickflipable.moc"
diff --git a/tests/auto/quick/qquickfocusscope/CMakeLists.txt b/tests/auto/quick/qquickfocusscope/CMakeLists.txt
index a9ea5022e0..755612121e 100644
--- a/tests/auto/quick/qquickfocusscope/CMakeLists.txt
+++ b/tests/auto/quick/qquickfocusscope/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickfocusscope Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickfocusscope LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp b/tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp
index 4dcbcc4884..70e5f227d3 100644
--- a/tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp
+++ b/tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QSignalSpy>
#include <QtQml/qqmlengine.h>
diff --git a/tests/auto/quick/qquickfontloader/CMakeLists.txt b/tests/auto/quick/qquickfontloader/CMakeLists.txt
index e13bf4e2e3..22f98b36d5 100644
--- a/tests/auto/quick/qquickfontloader/CMakeLists.txt
+++ b/tests/auto/quick/qquickfontloader/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickfontloader Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickfontloader LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
index c34edbcdde..a94d9fdd21 100644
--- a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
+++ b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtTest/QSignalSpy>
#include <QtQml/qqmlengine.h>
diff --git a/tests/auto/quick/qquickfontloader_static/CMakeLists.txt b/tests/auto/quick/qquickfontloader_static/CMakeLists.txt
index 48e1459b64..3d1fe63d6b 100644
--- a/tests/auto/quick/qquickfontloader_static/CMakeLists.txt
+++ b/tests/auto/quick/qquickfontloader_static/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickfontloader_static Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickfontloader_static LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickfontloader_static/tst_qquickfontloader_static.cpp b/tests/auto/quick/qquickfontloader_static/tst_qquickfontloader_static.cpp
index aee924dd50..ed692fcdd0 100644
--- a/tests/auto/quick/qquickfontloader_static/tst_qquickfontloader_static.cpp
+++ b/tests/auto/quick/qquickfontloader_static/tst_qquickfontloader_static.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtGui/QGuiApplication>
#include <QtQuick/QQuickView>
diff --git a/tests/auto/quick/qquickfontmetrics/CMakeLists.txt b/tests/auto/quick/qquickfontmetrics/CMakeLists.txt
index da375bcbed..02a23f988e 100644
--- a/tests/auto/quick/qquickfontmetrics/CMakeLists.txt
+++ b/tests/auto/quick/qquickfontmetrics/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_quickfontmetrics Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_quickfontmetrics LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_quickfontmetrics
SOURCES
tst_quickfontmetrics.cpp
diff --git a/tests/auto/quick/qquickfontmetrics/tst_quickfontmetrics.cpp b/tests/auto/quick/qquickfontmetrics/tst_quickfontmetrics.cpp
index f34bdc2059..090d47d652 100644
--- a/tests/auto/quick/qquickfontmetrics/tst_quickfontmetrics.cpp
+++ b/tests/auto/quick/qquickfontmetrics/tst_quickfontmetrics.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QFont>
#include <QFontDatabase>
@@ -30,10 +30,10 @@ tst_QuickFontMetrics::tst_QuickFontMetrics()
void tst_QuickFontMetrics::properties()
{
- QStringList families = QFontDatabase::families().mid(0, 10);
+ const QStringList families = QFontDatabase::families().mid(0, 10);
QQuickFontMetrics metrics;
- foreach (const QString &family, families) {
+ for (const QString &family : families) {
QFont font(family);
QFontMetricsF expected(font);
diff --git a/tests/auto/quick/qquickframebufferobject/CMakeLists.txt b/tests/auto/quick/qquickframebufferobject/CMakeLists.txt
index 7c02a2da42..9d87a5703d 100644
--- a/tests/auto/quick/qquickframebufferobject/CMakeLists.txt
+++ b/tests/auto/quick/qquickframebufferobject/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickframebufferobject Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickframebufferobject LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickframebufferobject/data/testStuff.qml b/tests/auto/quick/qquickframebufferobject/data/testStuff.qml
index b702b6c64b..fbde7ecc93 100644
--- a/tests/auto/quick/qquickframebufferobject/data/testStuff.qml
+++ b/tests/auto/quick/qquickframebufferobject/data/testStuff.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import FBOItem 1.0
diff --git a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
index e6f74fb287..ffd6478f9c 100644
--- a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
+++ b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
diff --git a/tests/auto/quick/qquickgraphicsinfo/CMakeLists.txt b/tests/auto/quick/qquickgraphicsinfo/CMakeLists.txt
index bfca6770af..13759ea9e3 100644
--- a/tests/auto/quick/qquickgraphicsinfo/CMakeLists.txt
+++ b/tests/auto/quick/qquickgraphicsinfo/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickgraphicsinfo Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickgraphicsinfo LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp b/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp
index 9ffe3c0aca..e142cbaad6 100644
--- a/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp
+++ b/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
diff --git a/tests/auto/quick/qquickgridview/CMakeLists.txt b/tests/auto/quick/qquickgridview/CMakeLists.txt
index b16f37a93f..38dfc4f1f6 100644
--- a/tests/auto/quick/qquickgridview/CMakeLists.txt
+++ b/tests/auto/quick/qquickgridview/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickgridview Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickgridview LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickgridview/data/attachedProperties.qml b/tests/auto/quick/qquickgridview/data/attachedProperties.qml
index e00c566f47..f5fb173b89 100644
--- a/tests/auto/quick/qquickgridview/data/attachedProperties.qml
+++ b/tests/auto/quick/qquickgridview/data/attachedProperties.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickgridview/data/displayMargin.qml b/tests/auto/quick/qquickgridview/data/displayMargin.qml
index 749deb5926..9bfdafbe61 100644
--- a/tests/auto/quick/qquickgridview/data/displayMargin.qml
+++ b/tests/auto/quick/qquickgridview/data/displayMargin.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.3
diff --git a/tests/auto/quick/qquickgridview/data/margins2.qml b/tests/auto/quick/qquickgridview/data/margins2.qml
index 6af4f5ca20..7735fc5362 100644
--- a/tests/auto/quick/qquickgridview/data/margins2.qml
+++ b/tests/auto/quick/qquickgridview/data/margins2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.7
diff --git a/tests/auto/quick/qquickgridview/data/negativeDisplayMargin.qml b/tests/auto/quick/qquickgridview/data/negativeDisplayMargin.qml
index d6a45e1a2a..3d5c8494a6 100644
--- a/tests/auto/quick/qquickgridview/data/negativeDisplayMargin.qml
+++ b/tests/auto/quick/qquickgridview/data/negativeDisplayMargin.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.3
diff --git a/tests/auto/quick/qquickgridview/data/qtbug49218.qml b/tests/auto/quick/qquickgridview/data/qtbug49218.qml
index 353157cf2a..3689c45b0e 100644
--- a/tests/auto/quick/qquickgridview/data/qtbug49218.qml
+++ b/tests/auto/quick/qquickgridview/data/qtbug49218.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
Item {
diff --git a/tests/auto/quick/qquickgridview/data/qtbug91461.qml b/tests/auto/quick/qquickgridview/data/qtbug91461.qml
index e547dc6184..4a13984b80 100644
--- a/tests/auto/quick/qquickgridview/data/qtbug91461.qml
+++ b/tests/auto/quick/qquickgridview/data/qtbug91461.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
Item {
diff --git a/tests/auto/quick/qquickgridview/data/removeAccessibleChildrenEvenIfReusingItems.qml b/tests/auto/quick/qquickgridview/data/removeAccessibleChildrenEvenIfReusingItems.qml
new file mode 100644
index 0000000000..a1d00bfbdf
--- /dev/null
+++ b/tests/auto/quick/qquickgridview/data/removeAccessibleChildrenEvenIfReusingItems.qml
@@ -0,0 +1,48 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.15
+
+Rectangle {
+ id: page
+ width: 640
+ height: 480
+
+ Accessible.role : Accessible.Client
+
+ GridView {
+ id: grid
+
+ width: 640
+ height: 480
+ model: listModel
+
+ cellWidth: 180
+ cellHeight: 30
+
+ delegate: Text {
+ id: textDelegate
+ text: name
+ Accessible.role: Accessible.Button
+ Accessible.name: name
+ }
+ reuseItems: true
+ Accessible.role : Accessible.Client
+ }
+
+ ListModel {
+ id: listModel
+ ListElement { name: "item11"}
+ ListElement { name: "item12"}
+ ListElement { name: "item13"}
+ ListElement { name: "item14"}
+ }
+
+ function replaceItems() {
+ listModel.clear()
+ listModel.insert(0, {"name" : "item21"})
+ listModel.insert(1, {"name" : "item22"})
+ listModel.insert(2, {"name" : "item23"})
+ listModel.insert(3, {"name" : "item24"})
+ }
+}
diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
index 9e42e0f4e4..3eb96e2bb4 100644
--- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtCore/qstringlistmodel.h>
@@ -194,6 +194,7 @@ private slots:
void keyNavigationEnabled();
void releaseItems();
+ void removeAccessibleChildrenEvenIfReusingItems();
private:
QList<int> toIntList(const QVariantList &list);
@@ -541,7 +542,7 @@ void tst_QQuickGridView::inserted_defaultLayout(QQuickGridView::Flow flow,
int firstVisibleIndex = -1;
for (int i=0; i<items.size(); i++) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (item && delegateVisible(item)) {
+ if (item && isDelegateVisible(item)) {
firstVisibleIndex = i;
break;
}
@@ -963,7 +964,7 @@ void tst_QQuickGridView::removed_defaultLayout(QQuickGridView::Flow flow,
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (item) {
QRectF itemRect(item->x(), item->y(), item->width(), item->height());
- if (delegateVisible(item) && viewRect.intersects(itemRect)) {
+ if (isDelegateVisible(item) && viewRect.intersects(itemRect)) {
firstVisibleIndex = i;
QQmlExpression en(qmlContext(item), item, "name");
firstName = en.evaluate().toString();
@@ -1311,7 +1312,7 @@ void tst_QQuickGridView::moved_defaultLayout(QQuickGridView::Flow flow,
int firstVisibleIndex = -1;
for (int i=0; i<items.size(); i++) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (item && delegateVisible(item)) {
+ if (item && isDelegateVisible(item)) {
firstVisibleIndex = i;
break;
}
@@ -1891,9 +1892,9 @@ void tst_QQuickGridView::currentIndex()
// moving currentItem out of view should make it invisible
gridview->setCurrentIndex(0);
- QTRY_VERIFY(delegateVisible(gridview->currentItem()));
+ QTRY_VERIFY(isDelegateVisible(gridview->currentItem()));
gridview->setContentY(200);
- QTRY_VERIFY(!delegateVisible(gridview->currentItem()));
+ QTRY_VERIFY(!isDelegateVisible(gridview->currentItem()));
delete window;
}
@@ -2715,14 +2716,14 @@ void tst_QQuickGridView::mirroring()
QCOMPARE(gridviewA->layoutDirection(), gridviewA->effectiveLayoutDirection());
// LTR != RTL
- foreach (const QString objectName, objectNames)
+ for (const QString &objectName : std::as_const(objectNames))
QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
gridviewB->setProperty("layoutDirection", Qt::LeftToRight);
// LTR == LTR
- foreach (const QString objectName, objectNames)
+ for (const QString &objectName : std::as_const(objectNames))
QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
QCOMPARE(gridviewB->layoutDirection(), gridviewB->effectiveLayoutDirection());
@@ -2730,25 +2731,25 @@ void tst_QQuickGridView::mirroring()
QVERIFY(gridviewB->layoutDirection() != gridviewB->effectiveLayoutDirection());
// LTR != LTR+mirror
- foreach (const QString objectName, objectNames)
+ for (const QString &objectName : std::as_const(objectNames))
QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
gridviewA->setProperty("layoutDirection", Qt::RightToLeft);
// RTL == LTR+mirror
- foreach (const QString objectName, objectNames)
+ for (const QString &objectName : std::as_const(objectNames))
QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
// RTL != RTL+mirror
- foreach (const QString objectName, objectNames)
+ for (const QString &objectName : std::as_const(objectNames))
QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
// LTR == RTL+mirror
- foreach (const QString objectName, objectNames)
+ for (const QString &objectName : std::as_const(objectNames))
QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
delete windowA;
@@ -3662,7 +3663,7 @@ void tst_QQuickGridView::resizeViewAndRepaint()
QTRY_VERIFY(item);
QTRY_COMPARE(item->x(), qreal((i%3)*80));
QTRY_COMPARE(item->y(), qreal((i/3)*60));
- QCOMPARE(delegateVisible(item), i < 9); // inside view visible, outside not visible
+ QCOMPARE(isDelegateVisible(item), i < 9); // inside view visible, outside not visible
}
// ensure items outside view become invisible
@@ -3676,7 +3677,7 @@ void tst_QQuickGridView::resizeViewAndRepaint()
QTRY_VERIFY(item);
QTRY_COMPARE(item->x(), qreal((i%3)*80));
QTRY_COMPARE(item->y(), qreal((i/3)*60));
- QCOMPARE(delegateVisible(item), i < 6); // inside view visible, outside not visible
+ QCOMPARE(isDelegateVisible(item), i < 6); // inside view visible, outside not visible
}
delete window;
@@ -5790,7 +5791,8 @@ void tst_QQuickGridView::multipleDisplaced()
QTRY_VERIFY(gridview->property("displaceTransitionsDone").toBool());
QVariantMap transitionsStarted = gridview->property("displaceTransitionsStarted").toMap();
- foreach (const QString &name, transitionsStarted.keys()) {
+ const QStringList keys = transitionsStarted.keys();
+ for (const QString &name : keys) {
QVERIFY2(transitionsStarted[name] == 1,
QTest::toString(QString("%1 was displaced %2 times").arg(name).arg(transitionsStarted[name].toInt())));
}
@@ -6048,23 +6050,23 @@ void tst_QQuickGridView::unrequestedVisibility()
QQuickItem *item;
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 9));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 10));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 3));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 4));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
rightview->setCurrentIndex(0);
@@ -6072,9 +6074,9 @@ void tst_QQuickGridView::unrequestedVisibility()
QTRY_COMPARE(rightview->contentY(), 0.0);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
- QTRY_COMPARE(delegateVisible(item), true);
+ QTRY_COMPARE(isDelegateVisible(item), true);
QVERIFY(!findItem<QQuickItem>(leftContent, "wrapper", 11));
QVERIFY(!findItem<QQuickItem>(rightContent, "wrapper", 11));
@@ -6085,98 +6087,98 @@ void tst_QQuickGridView::unrequestedVisibility()
QTRY_COMPARE(rightview->contentY(), 0.0);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
- QTRY_COMPARE(delegateVisible(item), false);
+ QTRY_COMPARE(isDelegateVisible(item), false);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
// move a non-visible item into view
model.moveItems(10, 9, 1);
QVERIFY(QQuickTest::qWaitForPolish(leftview));
QTRY_VERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
// move a visible item out of view
model.moveItems(5, 3, 1);
QVERIFY(QQuickTest::qWaitForPolish(leftview));
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
// move a non-visible item into view
model.moveItems(3, 5, 1);
QVERIFY(QQuickTest::qWaitForPolish(leftview));
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
// move a visible item out of view
model.moveItems(9, 10, 1);
QVERIFY(QQuickTest::qWaitForPolish(leftview));
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
// move a non-visible item into view
model.moveItems(10, 9, 1);
QVERIFY(QQuickTest::qWaitForPolish(leftview));
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
delete window;
}
@@ -6464,22 +6466,22 @@ void tst_QQuickGridView::displayMargin()
QQuickItem *item97;
QVERIFY(item0 = findItem<QQuickItem>(content, "delegate", 0));
- QCOMPARE(delegateVisible(item0), true);
+ QCOMPARE(isDelegateVisible(item0), true);
// the 97th item should be within the end margin
QVERIFY(item97 = findItem<QQuickItem>(content, "delegate", 96));
- QCOMPARE(delegateVisible(item97), true);
+ QCOMPARE(isDelegateVisible(item97), true);
// GridView staggers item creation, so the 118th item should be outside the end margin.
QVERIFY(findItem<QQuickItem>(content, "delegate", 117) == nullptr);
// the first delegate should still be within the begin margin
gridview->positionViewAtIndex(20, QQuickGridView::Beginning);
- QCOMPARE(delegateVisible(item0), true);
+ QCOMPARE(isDelegateVisible(item0), true);
// the first delegate should now be outside the begin margin
gridview->positionViewAtIndex(36, QQuickGridView::Beginning);
- QCOMPARE(delegateVisible(item0), false);
+ QCOMPARE(isDelegateVisible(item0), false);
delete window;
}
@@ -6503,26 +6505,26 @@ void tst_QQuickGridView::negativeDisplayMargin()
QVERIFY(content != nullptr);
QVERIFY(item = findItem<QQuickItem>(content, "delegate", 0));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(content, "delegate", 7));
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
QVERIFY(item = findItem<QQuickItem>(content, "delegate", 8));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
// Flick until contentY means that delegate8 should be visible
listview->setProperty("contentY", 500);
QVERIFY(item = findItem<QQuickItem>(content, "delegate", 8));
- QTRY_COMPARE(delegateVisible(item), true);
+ QTRY_COMPARE(isDelegateVisible(item), true);
listview->setProperty("contentY", 1000);
QTRY_VERIFY(item = findItem<QQuickItem>(content, "delegate", 14));
- QTRY_COMPARE(delegateVisible(item), true);
+ QTRY_COMPARE(isDelegateVisible(item), true);
listview->setProperty("contentY", 0);
QVERIFY(item = findItem<QQuickItem>(content, "delegate", 4));
- QTRY_COMPARE(delegateVisible(item), true);
+ QTRY_COMPARE(isDelegateVisible(item), true);
delete window;
}
@@ -6843,6 +6845,36 @@ void tst_QQuickGridView::releaseItems()
gridview->setModel(123);
}
+void tst_QQuickGridView::removeAccessibleChildrenEvenIfReusingItems()
+{
+ auto window = std::make_unique<QQuickView>();
+ window->setSource(testFileUrl("removeAccessibleChildrenEvenIfReusingItems.qml"));
+ window->show();
+
+ QQuickItem *contentItem = window->contentItem();
+ QVERIFY(contentItem);
+ QQuickItem *rootItem = contentItem->childItems().first();
+ QVERIFY(rootItem);
+
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window.get());
+ QVERIFY(iface);
+ QAccessibleInterface *gridView = iface->child(0)->child(0);
+ QCOMPARE(gridView->childCount(), 4);
+ QCOMPARE(gridView->child(0)->text(QAccessible::Text::Name), "item11");
+ QCOMPARE(gridView->child(1)->text(QAccessible::Text::Name), "item12");
+ QCOMPARE(gridView->child(2)->text(QAccessible::Text::Name), "item13");
+ QCOMPARE(gridView->child(3)->text(QAccessible::Text::Name), "item14");
+
+ QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "replaceItems"));
+
+ QCOMPARE(gridView->childCount(), 4);
+ QTRY_COMPARE(gridView->child(0)->text(QAccessible::Text::Name), "item21");
+ QTRY_COMPARE(gridView->child(1)->text(QAccessible::Text::Name), "item22");
+ QTRY_COMPARE(gridView->child(2)->text(QAccessible::Text::Name), "item23");
+ QTRY_COMPARE(gridView->child(3)->text(QAccessible::Text::Name), "item24");
+}
+
+
QTEST_MAIN(tst_QQuickGridView)
#include "tst_qquickgridview.moc"
diff --git a/tests/auto/quick/qquickimage/BLACKLIST b/tests/auto/quick/qquickimage/BLACKLIST
index 348ae127f3..a5c718c4f0 100644
--- a/tests/auto/quick/qquickimage/BLACKLIST
+++ b/tests/auto/quick/qquickimage/BLACKLIST
@@ -1,6 +1,3 @@
-# QTBUG-98402
-[mirror]
-macos-12 ci
# QTBUG-102721
[hugeImages]
android
diff --git a/tests/auto/quick/qquickimage/CMakeLists.txt b/tests/auto/quick/qquickimage/CMakeLists.txt
index 4e3de0a905..774bdf0dcd 100644
--- a/tests/auto/quick/qquickimage/CMakeLists.txt
+++ b/tests/auto/quick/qquickimage/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickimage Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickimage LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickimage/data/hugeImages.qml b/tests/auto/quick/qquickimage/data/hugeImages.qml
index ee141c9456..00aad415f0 100644
--- a/tests/auto/quick/qquickimage/data/hugeImages.qml
+++ b/tests/auto/quick/qquickimage/data/hugeImages.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickimage/data/multiframeAsyncRetain.qml b/tests/auto/quick/qquickimage/data/multiframeAsyncRetain.qml
new file mode 100644
index 0000000000..fc0f135528
--- /dev/null
+++ b/tests/auto/quick/qquickimage/data/multiframeAsyncRetain.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Image {
+ source: "multi.ico"
+ asynchronous: true
+ retainWhileLoading: true
+}
diff --git a/tests/auto/quick/qquickimage/data/qtbug_32513.qml b/tests/auto/quick/qquickimage/data/qtbug_32513.qml
index 438717155b..6f8adc6ba4 100644
--- a/tests/auto/quick/qquickimage/data/qtbug_32513.qml
+++ b/tests/auto/quick/qquickimage/data/qtbug_32513.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickimage/data/statusChanged.qml b/tests/auto/quick/qquickimage/data/statusChanged.qml
new file mode 100644
index 0000000000..ce4b4c4be9
--- /dev/null
+++ b/tests/auto/quick/qquickimage/data/statusChanged.qml
@@ -0,0 +1,25 @@
+import QtQuick
+
+Image {
+ id: root
+ property var changeSignals: []
+ property var statusChanges: []
+ property size statusChangedFirstImplicitSize: Qt.size(-1,-1)
+
+ source: "heart.png"
+
+ onFrameCountChanged: root.changeSignals.push("frameCount")
+ onCurrentFrameChanged: root.changeSignals.push("currentFrame")
+ onSourceSizeChanged: root.changeSignals.push("sourceSize")
+ onImplicitWidthChanged: root.changeSignals.push("implicitWidth")
+ onImplicitHeightChanged: root.changeSignals.push("implicitHeight")
+ onPaintedWidthChanged: root.changeSignals.push("paintedWidth")
+ onPaintedHeightChanged: root.changeSignals.push("paintedHeight")
+ onProgressChanged: root.changeSignals.push("progress")
+ onStatusChanged: (status) => {
+ root.changeSignals.push("status")
+ root.statusChanges.push(status)
+ if (root.statusChangedFirstImplicitSize.width < 0)
+ root.statusChangedFirstImplicitSize = Qt.size(root.implicitWidth, root.implicitHeight)
+ }
+}
diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
index 89b20c3131..d19c99de82 100644
--- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp
+++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QTextDocument>
#include <QTcpServer>
@@ -24,10 +24,13 @@
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/testhttpserver_p.h>
+#include <QtQuickTestUtils/private/viewtestutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
// #define DEBUG_WRITE_OUTPUT
+Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
+
using namespace QQuickVisualTestUtils;
Q_DECLARE_METATYPE(QQuickImageBase::Status)
@@ -68,6 +71,7 @@ private slots:
void sourceClipRect_data();
void sourceClipRect();
void progressAndStatusChanges();
+ void progressAndChangeSignalOrder();
void sourceSizeChanges();
void correctStatus();
void highdpi();
@@ -131,41 +135,49 @@ void tst_qquickimage::imageSource_data()
QTest::addColumn<bool>("async");
QTest::addColumn<bool>("cache");
QTest::addColumn<QString>("error");
+ QTest::addColumn<bool>("retainWhileLoading");
- QTest::newRow("local") << testFileUrl("colors.png").toString() << 120.0 << 120.0 << false << false << true << "";
- QTest::newRow("local no cache") << testFileUrl("colors.png").toString() << 120.0 << 120.0 << false << false << false << "";
- QTest::newRow("local async") << testFileUrl("colors1.png").toString() << 120.0 << 120.0 << false << true << true << "";
+ QTest::newRow("local") << testFileUrl("colors.png").toString() << 120.0 << 120.0 << false << false << true << "" << false;
+ QTest::newRow("local no cache") << testFileUrl("colors.png").toString() << 120.0 << 120.0 << false << false << false << "" << false;
+ QTest::newRow("local async") << testFileUrl("colors1.png").toString() << 120.0 << 120.0 << false << true << true << "" << false;
+ QTest::newRow("local async retain") << testFileUrl("colors1.png").toString() << 120.0 << 120.0 << false << true << true << "" << true;
QTest::newRow("local not found") << testFileUrl("no-such-file.png").toString() << 0.0 << 0.0 << false
- << false << true << "<Unknown File>:2:1: QML Image: Cannot open: " + testFileUrl("no-such-file.png").toString();
+ << false << true << "<Unknown File>:2:1: QML Image: Cannot open: " + testFileUrl("no-such-file.png").toString() << false;
QTest::newRow("local async not found") << testFileUrl("no-such-file-1.png").toString() << 0.0 << 0.0 << false
- << true << true << "<Unknown File>:2:1: QML Image: Cannot open: " + testFileUrl("no-such-file-1.png").toString();
- QTest::newRow("remote") << "/colors.png" << 120.0 << 120.0 << true << false << true << "";
- QTest::newRow("remote redirected") << "/oldcolors.png" << 120.0 << 120.0 << true << false << false << "";
+ << true << true << "<Unknown File>:2:1: QML Image: Cannot open: " + testFileUrl("no-such-file-1.png").toString() << false;
+ QTest::newRow("local async retain not found") << testFileUrl("no-such-file-1.png").toString() << 0.0 << 0.0 << false
+ << true << true << "<Unknown File>:2:1: QML Image: Cannot open: " + testFileUrl("no-such-file-1.png").toString() << true;
+ QTest::newRow("remote") << "/colors.png" << 120.0 << 120.0 << true << false << true << "" << false;
+ QTest::newRow("remote retain") << "/colors.png" << 120.0 << 120.0 << true << false << true << "" << true;
+ QTest::newRow("remote redirected") << "/oldcolors.png" << 120.0 << 120.0 << true << false << false << "" << false;
if (QImageReader::supportedImageFormats().contains("svg"))
- QTest::newRow("remote svg") << "/heart.svg" << 595.0 << 841.0 << true << false << false << "";
+ QTest::newRow("remote svg") << "/heart.svg" << 595.0 << 841.0 << true << false << false << "" << false;
if (QImageReader::supportedImageFormats().contains("svgz"))
- QTest::newRow("remote svgz") << "/heart.svgz" << 595.0 << 841.0 << true << false << false << "";
+ QTest::newRow("remote svgz") << "/heart.svgz" << 595.0 << 841.0 << true << false << false << "" << false;
if (graphicsApi != QSGRendererInterface::Software) {
- QTest::newRow("texturefile pkm format") << testFileUrl("logo.pkm").toString() << 256.0 << 256.0 << false << false << true << "";
- QTest::newRow("texturefile ktx format") << testFileUrl("car.ktx").toString() << 146.0 << 80.0 << false << false << true << "";
- QTest::newRow("texturefile async") << testFileUrl("logo.pkm").toString() << 256.0 << 256.0 << false << true << true << "";
- QTest::newRow("texturefile remote") << "/logo.pkm" << 256.0 << 256.0 << true << false << true << "";
+ QTest::newRow("texturefile pkm format") << testFileUrl("logo.pkm").toString() << 256.0 << 256.0 << false << false << true << "" << false;
+ QTest::newRow("texturefile ktx format") << testFileUrl("car.ktx").toString() << 146.0 << 80.0 << false << false << true << "" << false;
+ QTest::newRow("texturefile async") << testFileUrl("logo.pkm").toString() << 256.0 << 256.0 << false << true << true << "" << false;
+ QTest::newRow("texturefile async retain") << testFileUrl("logo.pkm").toString() << 256.0 << 256.0 << false << true << true << "" << true;
+ QTest::newRow("texturefile remote") << "/logo.pkm" << 256.0 << 256.0 << true << false << true << "" << false;
+ QTest::newRow("texturefile remote retain") << "/logo.pkm" << 256.0 << 256.0 << true << false << true << "" << true;
}
QTest::newRow("remote not found") << "/no-such-file.png" << 0.0 << 0.0 << true
- << false << true << "<Unknown File>:2:1: QML Image: Error transferring {{ServerBaseUrl}}/no-such-file.png - server replied: Not found";
- QTest::newRow("extless") << testFileUrl("colors").toString() << 120.0 << 120.0 << false << false << true << "";
- QTest::newRow("extless no cache") << testFileUrl("colors").toString() << 120.0 << 120.0 << false << false << false << "";
- QTest::newRow("extless async") << testFileUrl("colors1").toString() << 120.0 << 120.0 << false << true << true << "";
+ << false << true << "<Unknown File>:2:1: QML Image: Error transferring {{ServerBaseUrl}}/no-such-file.png - server replied: Not found" << false;
+ QTest::newRow("extless") << testFileUrl("colors").toString() << 120.0 << 120.0 << false << false << true << "" << false;
+ QTest::newRow("extless no cache") << testFileUrl("colors").toString() << 120.0 << 120.0 << false << false << false << "" << false;
+ QTest::newRow("extless async") << testFileUrl("colors1").toString() << 120.0 << 120.0 << false << true << true << "" << false;
+ QTest::newRow("extless async retain") << testFileUrl("colors1").toString() << 120.0 << 120.0 << false << true << true << "" << true;
QTest::newRow("extless not found") << testFileUrl("no-such-file").toString() << 0.0 << 0.0 << false
- << false << true << "<Unknown File>:2:1: QML Image: Cannot open: " + testFileUrl("no-such-file").toString();
+ << false << true << "<Unknown File>:2:1: QML Image: Cannot open: " + testFileUrl("no-such-file").toString() << false;
// Test that texture file is preferred over image file, when supported.
// Since pattern.pkm has different size than pattern.png, these tests verify that the right file has been loaded
if (graphicsApi != QSGRendererInterface::Software) {
- QTest::newRow("extless prefer-tex") << testFileUrl("pattern").toString() << 64.0 << 64.0 << false << false << true << "";
- QTest::newRow("extless prefer-tex async") << testFileUrl("pattern").toString() << 64.0 << 64.0 << false << true << true << "";
+ QTest::newRow("extless prefer-tex") << testFileUrl("pattern").toString() << 64.0 << 64.0 << false << false << true << "" << false;
+ QTest::newRow("extless prefer-tex async") << testFileUrl("pattern").toString() << 64.0 << 64.0 << false << true << true << "" << false;
} else {
- QTest::newRow("extless ignore-tex") << testFileUrl("pattern").toString() << 200.0 << 200.0 << false << false << true << "";
- QTest::newRow("extless ignore-tex async") << testFileUrl("pattern").toString() << 200.0 << 200.0 << false << true << true << "";
+ QTest::newRow("extless ignore-tex") << testFileUrl("pattern").toString() << 200.0 << 200.0 << false << false << true << "" << false;
+ QTest::newRow("extless ignore-tex async") << testFileUrl("pattern").toString() << 200.0 << 200.0 << false << true << true << "" << false;
}
}
@@ -179,6 +191,7 @@ void tst_qquickimage::imageSource()
QFETCH(bool, async);
QFETCH(bool, cache);
QFETCH(QString, error);
+ QFETCH(bool, retainWhileLoading);
TestHTTPServer server;
if (remote) {
@@ -192,9 +205,10 @@ void tst_qquickimage::imageSource()
if (!error.isEmpty())
QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
- QString componentStr = "import QtQuick 2.0\nImage { source: \"" + source + "\"; asynchronous: "
+ QString componentStr = "import QtQuick\nImage { source: \"" + source + "\"; asynchronous: "
+ (async ? QLatin1String("true") : QLatin1String("false")) + "; cache: "
- + (cache ? QLatin1String("true") : QLatin1String("false")) + " }";
+ + (cache ? QLatin1String("true") : QLatin1String("false")) + "; retainWhileLoading: "
+ + (retainWhileLoading ? QLatin1String("true") : QLatin1String("false")) + " }";
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
@@ -205,6 +219,8 @@ void tst_qquickimage::imageSource()
else
QVERIFY(!obj->asynchronous());
+ QCOMPARE(obj->retainWhileLoading(), retainWhileLoading);
+
if (cache)
QVERIFY(obj->cache());
else
@@ -308,15 +324,19 @@ void tst_qquickimage::mirror()
QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QMap<QQuickImage::FillMode, QImage> screenshots;
- QList<QQuickImage::FillMode> fillModes;
- fillModes << QQuickImage::Stretch << QQuickImage::PreserveAspectFit << QQuickImage::PreserveAspectCrop
- << QQuickImage::Tile << QQuickImage::TileVertically << QQuickImage::TileHorizontally << QQuickImage::Pad;
+ const QList<QQuickImage::FillMode> fillModes{QQuickImage::Stretch,
+ QQuickImage::PreserveAspectFit,
+ QQuickImage::PreserveAspectCrop,
+ QQuickImage::Tile,
+ QQuickImage::TileVertically,
+ QQuickImage::TileHorizontally,
+ QQuickImage::Pad};
qreal width = 300;
qreal height = 250;
qreal devicePixelRatio = 1.0;
- foreach (QQuickImage::FillMode fillMode, fillModes) {
+ for (QQuickImage::FillMode fillMode : fillModes) {
QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("mirror.qml"));
@@ -333,7 +353,7 @@ void tst_qquickimage::mirror()
devicePixelRatio = window->devicePixelRatio();
}
- foreach (QQuickImage::FillMode fillMode, fillModes) {
+ for (QQuickImage::FillMode fillMode : fillModes) {
QPixmap srcPixmap;
QVERIFY(srcPixmap.load(testFile("pattern.png")));
@@ -453,9 +473,8 @@ void tst_qquickimage::geometry_data()
QTest::newRow("PreserveAspectCrop explicit width 300, height 400") << "PreserveAspectCrop" << true << true << 300.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0;
// bounding rect, painted rect and item rect are equal in stretching and tiling images
- QStringList fillModes;
- fillModes << "Stretch" << "Tile" << "TileVertically" << "TileHorizontally";
- foreach (QString fillMode, fillModes) {
+ QStringList fillModes{"Stretch", "Tile", "TileVertically", "TileHorizontally"};
+ for (const auto &fillMode : fillModes) {
QTest::newRow(fillMode.toLatin1()) << fillMode << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
QTest::newRow(QString(fillMode + " explicit width 300").toLatin1()) << fillMode << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 100.0 << 100.0;
QTest::newRow(QString(fillMode + " explicit height 400").toLatin1()) << fillMode << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 400.0 << 400.0;
@@ -975,6 +994,28 @@ void tst_qquickimage::progressAndStatusChanges()
delete obj;
}
+void tst_qquickimage::progressAndChangeSignalOrder()
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("statusChanged.qml")));
+ QQuickImage *image = qmlobject_cast<QQuickImage *>(window.rootObject());
+ QVERIFY(image);
+
+ QTRY_COMPARE(image->status(), QQuickImageBase::Ready);
+ // QTBUG-120205: implicitSize should be correct when status changes to Ready
+ QCOMPARE(image->property("statusChangedFirstImplicitSize").toSize(), QSize(300, 300));
+ QCOMPARE(image->property("statusChanges").toList().size(), 1); // just Ready
+ const QStringList signalOrder = image->property("changeSignals").toStringList();
+ const QStringList expectedOrder = {"progress", "paintedHeight", "paintedWidth",
+ "implicitWidth", "implicitHeight",
+ "paintedHeight", "paintedWidth",
+ "status", "sourceSize", "frameCount"};
+ qCDebug(lcTests) << "signal order" << signalOrder;
+ // exact order may not be critical, and repeated signals may be silly;
+ // but this way we'll find out when it changes
+ QCOMPARE(signalOrder, expectedOrder);
+}
+
class TestQImageProvider : public QQuickImageProvider
{
public:
@@ -1179,6 +1220,7 @@ void tst_qquickimage::multiFrame_data()
QTest::addRow("default") << "multiframe.qml" << false;
QTest::addRow("async") << "multiframeAsync.qml" << true;
+ QTest::addRow("async retain") << "multiframeAsyncRetain.qml" << true;
}
void tst_qquickimage::multiFrame()
diff --git a/tests/auto/quick/qquickimageprovider/CMakeLists.txt b/tests/auto/quick/qquickimageprovider/CMakeLists.txt
index 801d54331b..33ab315873 100644
--- a/tests/auto/quick/qquickimageprovider/CMakeLists.txt
+++ b/tests/auto/quick/qquickimageprovider/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickimageprovider Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickimageprovider LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
index 78727d32a0..ae891c3f2a 100644
--- a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
+++ b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <QtTest/QtTest>
#include <QtQml/qqmlengine.h>
@@ -422,21 +423,19 @@ void tst_qquickimageprovider::threadTest()
QObject *obj = component.create();
//MUST not deadlock
QVERIFY(obj != nullptr);
- QList<QQuickImage *> images = obj->findChildren<QQuickImage *>();
+ const QList<QQuickImage *> images = obj->findChildren<QQuickImage *>();
QCOMPARE(images.size(), 4);
QTest::qWait(100);
- foreach (QQuickImage *img, images) {
+ for (QQuickImage *img : images)
QCOMPARE(img->status(), QQuickImage::Loading);
- }
{
QMutexLocker lock(&provider->mutex);
provider->ok = true;
provider->cond.wakeAll();
}
QTest::qWait(250);
- foreach (QQuickImage *img, images) {
+ for (QQuickImage *img : images)
QTRY_COMPARE(img->status(), QQuickImage::Ready);
- }
}
class TestImageResponseRunner : public QObject, public QRunnable {
@@ -541,21 +540,19 @@ void tst_qquickimageprovider::asyncTextureTest()
QObject *obj = component.create();
//MUST not deadlock
QVERIFY(obj != nullptr);
- QList<QQuickImage *> images = obj->findChildren<QQuickImage *>();
+ const QList<QQuickImage *> images = obj->findChildren<QQuickImage *>();
QCOMPARE(images.size(), 4);
QTRY_COMPARE(provider->pool.activeThreadCount(), 4);
- foreach (QQuickImage *img, images) {
+ for (QQuickImage *img : images)
QTRY_COMPARE(img->status(), QQuickImage::Loading);
- }
{
QMutexLocker lock(&provider->lock);
provider->ok = true;
provider->condition.wakeAll();
}
- foreach (QQuickImage *img, images) {
+ for (QQuickImage *img : images)
QTRY_COMPARE(img->status(), QQuickImage::Ready);
- }
}
class InstantAsyncImageResponse : public QQuickImageResponse
diff --git a/tests/auto/quick/qquickitem/CMakeLists.txt b/tests/auto/quick/qquickitem/CMakeLists.txt
index cf5293c698..82e7482e02 100644
--- a/tests/auto/quick/qquickitem/CMakeLists.txt
+++ b/tests/auto/quick/qquickitem/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickitem Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickitem LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -30,8 +36,6 @@ qt_internal_add_test(tst_qquickitem
#####################################################################
qt_internal_extend_target(tst_qquickitem CONDITION TARGET Qt::Widgets
- DEFINES
- TEST_QTBUG_60123
LIBRARIES
Qt::Widgets
)
diff --git a/tests/auto/quick/qquickitem/data/childAtRectangle.qml b/tests/auto/quick/qquickitem/data/childAtRectangle.qml
index 3070b33dca..b21f52c3cd 100644
--- a/tests/auto/quick/qquickitem/data/childAtRectangle.qml
+++ b/tests/auto/quick/qquickitem/data/childAtRectangle.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickitem/data/mainWindowQtBug60123.qml b/tests/auto/quick/qquickitem/data/mainWindowQtBug60123.qml
index 9f50be04cb..8790c5beb3 100644
--- a/tests/auto/quick/qquickitem/data/mainWindowQtBug60123.qml
+++ b/tests/auto/quick/qquickitem/data/mainWindowQtBug60123.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickitem/data/shortcutOverride.qml b/tests/auto/quick/qquickitem/data/shortcutOverride.qml
index dbc2be27b9..cde49ebaf9 100644
--- a/tests/auto/quick/qquickitem/data/shortcutOverride.qml
+++ b/tests/auto/quick/qquickitem/data/shortcutOverride.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.8
import QtQuick.Window 2.1
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index 23616156d6..338070b730 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
@@ -24,7 +24,7 @@
#include <QTranslator>
#include <QtCore/qregularexpression.h>
-#ifdef TEST_QTBUG_60123
+#ifdef QT_WIDGETS_LIB
#include <QWidget>
#include <QMainWindow>
#endif
@@ -217,7 +217,7 @@ private slots:
void shortcutOverride();
-#ifdef TEST_QTBUG_60123
+#ifdef QT_WIDGETS_LIB
void qtBug60123();
#endif
@@ -228,6 +228,9 @@ private slots:
void polishLoopDetection();
void objectCastInDestructor();
+ void listsAreNotLists();
+
+ void transformChanged();
private:
@@ -1993,13 +1996,6 @@ void tst_qquickitem::acceptedMouseButtons()
QCOMPARE(item.releaseCount, 3);
}
-static void gc(QQmlEngine &engine)
-{
- engine.collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
-}
-
void tst_qquickitem::visualParentOwnership()
{
QQmlEngine engine;
@@ -2338,7 +2334,7 @@ void tst_qquickitem::shortcutOverride()
QCOMPARE(view.rootObject()->property("shortcutActivationCount").toInt(), 1);
}
-#ifdef TEST_QTBUG_60123
+#ifdef QT_WIDGETS_LIB
void tst_qquickitem::qtBug60123()
{
QMainWindow main;
@@ -2462,6 +2458,225 @@ void tst_qquickitem::objectCastInDestructor()
QVERIFY(QTest::qWaitFor([&destroyed]{ return destroyed; }));
}
+template<typename T>
+void verifyListProperty(const T &data)
+{
+ QVERIFY(data.object);
+ QVERIFY(data.append);
+ QVERIFY(data.count);
+ QVERIFY(data.at);
+ QVERIFY(data.clear);
+ QVERIFY(data.removeLast);
+
+ // We must not synthesize the replace and removeLast methods on those properties.
+ // They would be even more broken than the explicitly defined methods.
+ QVERIFY(!data.replace);
+}
+
+void tst_qquickitem::listsAreNotLists()
+{
+ QQuickItem item;
+ QQuickItem child;
+ QObject resource;
+
+ QQmlListProperty<QObject> data
+ = item.property("data").value<QQmlListProperty<QObject>>();
+ QQmlListProperty<QObject> resources
+ = item.property("resources").value<QQmlListProperty<QObject>>();
+ QQmlListProperty<QQuickItem> children
+ = item.property("children").value<QQmlListProperty<QQuickItem>>();
+
+ verifyListProperty(data);
+ verifyListProperty(resources);
+ verifyListProperty(children);
+
+
+ QCOMPARE(data.count(&data), 0);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 0);
+ children.append(&children, &child);
+ QCOMPARE(data.count(&data), 1);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 1);
+ children.removeLast(&children);
+ QCOMPARE(data.count(&data), 0);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 0);
+ data.append(&data, &child);
+ QCOMPARE(data.count(&data), 1);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 1);
+ data.removeLast(&data);
+ QCOMPARE(data.count(&data), 0);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 0);
+ children.append(&children, &child);
+ QCOMPARE(data.count(&data), 1);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 1);
+ data.removeLast(&data);
+ QCOMPARE(data.count(&data), 0);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 0);
+ data.append(&data, &child);
+ QCOMPARE(data.count(&data), 1);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 1);
+ children.removeLast(&children);
+ QCOMPARE(data.count(&data), 0);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 0);
+
+
+ resources.append(&resources, &resource);
+ QCOMPARE(data.count(&data), 1);
+ QCOMPARE(resources.count(&resources), 1);
+ QCOMPARE(children.count(&children), 0);
+ resources.removeLast(&resources);
+ QCOMPARE(data.count(&data), 0);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 0);
+ data.append(&data, &resource);
+ QCOMPARE(data.count(&data), 1);
+ QCOMPARE(resources.count(&resources), 1);
+ QCOMPARE(children.count(&children), 0);
+ data.removeLast(&data);
+ QCOMPARE(data.count(&data), 0);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 0);
+ resources.append(&resources, &resource);
+ QCOMPARE(data.count(&data), 1);
+ QCOMPARE(resources.count(&resources), 1);
+ QCOMPARE(children.count(&children), 0);
+ data.removeLast(&data);
+ QCOMPARE(data.count(&data), 0);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 0);
+ data.append(&data, &resource);
+ QCOMPARE(data.count(&data), 1);
+ QCOMPARE(resources.count(&resources), 1);
+ QCOMPARE(children.count(&children), 0);
+ resources.removeLast(&resources);
+ QCOMPARE(data.count(&data), 0);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 0);
+
+
+ children.append(&children, &child);
+ resources.append(&resources, &resource);
+ QCOMPARE(data.count(&data), 2);
+ QCOMPARE(resources.count(&resources), 1);
+ QCOMPARE(children.count(&children), 1);
+ children.removeLast(&children);
+ QCOMPARE(data.count(&data), 1);
+ QCOMPARE(resources.count(&resources), 1);
+ QCOMPARE(children.count(&children), 0);
+ resources.removeLast(&resources);
+ QCOMPARE(data.count(&data), 0);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 0);
+
+
+ children.append(&children, &child);
+ resources.append(&resources, &resource);
+ QCOMPARE(data.count(&data), 2);
+ QCOMPARE(resources.count(&resources), 1);
+ QCOMPARE(children.count(&children), 1);
+ resources.removeLast(&resources);
+ QCOMPARE(data.count(&data), 1);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 1);
+ children.removeLast(&children);
+ QCOMPARE(data.count(&data), 0);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 0);
+
+
+ data.append(&data, &child);
+ data.append(&data, &resource);
+ QCOMPARE(data.count(&data), 2);
+ QCOMPARE(resources.count(&resources), 1);
+ QCOMPARE(children.count(&children), 1);
+ data.removeLast(&data);
+ QCOMPARE(data.count(&data), 1);
+ QCOMPARE(resources.count(&resources), 1);
+ QCOMPARE(children.count(&children), 0);
+ data.removeLast(&data);
+ QCOMPARE(data.count(&data), 0);
+ QCOMPARE(resources.count(&resources), 0);
+ QCOMPARE(children.count(&children), 0);
+}
+
+class TransformItemPrivate;
+class TransformItem : public QQuickItem {
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(TransformItem)
+public:
+ TransformItem(QQuickItem *parent = nullptr);
+
+ bool transformChanged = false;
+};
+
+class TransformItemPrivate :public QQuickItemPrivate
+{
+protected:
+ Q_DECLARE_PUBLIC(TransformItem)
+
+ bool transformChanged(QQuickItem *) override
+ {
+ Q_Q(TransformItem);
+ q->transformChanged = true;
+ return true;
+ }
+};
+
+TransformItem::TransformItem(QQuickItem *parent)
+ : QQuickItem(*(new TransformItemPrivate), parent)
+{
+}
+
+void tst_qquickitem::transformChanged()
+{
+ QQuickItem rootItem;
+ QQuickItem *parents[2][3] = {};
+ for (int i = 0; i < 2; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ auto *item = new QQuickItem;
+ item->setObjectName(QString("Item-%1.%2").arg(i).arg(j));
+ item->setParentItem(j > 0 ? parents[i][j - 1] : &rootItem);
+ parents[i][j] = item;
+ }
+ }
+
+ // Setting the root item's position will result in transformChanged,
+ // which will clear the subtreeTransformChangedEnabled flag that is
+ // by default set to true, since there are no children that observe
+ // the viewport.
+ parents[0][0]->setPosition(QPoint(100, 100));
+ parents[1][0]->setPosition(QPoint(200, 200));
+
+ TransformItem transformItem;
+ transformItem.setParentItem(parents[0][2]);
+ transformItem.setFlag(QQuickItem::ItemObservesViewport);
+ QCOMPARE(transformItem.mapToScene(QPoint(0, 0)), parents[0][0]->position());
+
+ parents[0][0]->setPosition(QPoint(110, 110));
+ QVERIFY2(transformItem.transformChanged,
+ "Moving an ancestor should trigger transformChanged");
+
+ transformItem.transformChanged = false;
+ transformItem.setParentItem(parents[1][2]);
+ QVERIFY2(transformItem.transformChanged,
+ "Reparenting the item should result in a transformChanged");
+ QCOMPARE(transformItem.mapToScene(QPoint(0, 0)), parents[1][0]->position());
+
+ transformItem.transformChanged = false;
+ parents[1][0]->setPosition(QPoint(220, 220));
+ QVERIFY2(transformItem.transformChanged,
+ "Changing one of the new ancestors should result in transformChanged");
+ QCOMPARE(transformItem.mapToScene(QPoint(0, 0)), parents[1][0]->position());
+}
+
QTEST_MAIN(tst_qquickitem)
#include "tst_qquickitem.moc"
diff --git a/tests/auto/quick/qquickitem2/CMakeLists.txt b/tests/auto/quick/qquickitem2/CMakeLists.txt
index 44620cacd6..6b115efd2e 100644
--- a/tests/auto/quick/qquickitem2/CMakeLists.txt
+++ b/tests/auto/quick/qquickitem2/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickitem2 Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickitem2 LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -31,6 +37,11 @@ qt_internal_add_test(tst_qquickitem2
## Scopes:
#####################################################################
+qt_internal_extend_target(tst_qquickitem2 CONDITION TARGET Qt::Widgets
+ LIBRARIES
+ Qt::Widgets
+)
+
qt_internal_extend_target(tst_qquickitem2 CONDITION ANDROID OR IOS
DEFINES
QT_QMLTEST_DATADIR=":/data"
diff --git a/tests/auto/quick/qquickitem2/data/embedded.qml b/tests/auto/quick/qquickitem2/data/embedded.qml
new file mode 100644
index 0000000000..a9cf115699
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/embedded.qml
@@ -0,0 +1,30 @@
+import QtQuick
+
+Rectangle {
+ width: 300
+ height: 300
+
+ Column {
+ anchors.fill: parent
+ anchors.rightMargin: 2
+ anchors.leftMargin: 2
+ anchors.topMargin: 10
+ spacing: 20
+ Rectangle {
+ objectName: "rect1"
+ width: parent.width
+ height: 30
+ border.width: 1
+ border.color: activeFocus ? "blue" : "black"
+ focusPolicy: Qt.TabFocus
+ }
+ Rectangle {
+ objectName: "rect2"
+ width: parent.width
+ height: 30
+ border.width: 1
+ border.color: activeFocus ? "blue" : "black"
+ focusPolicy: Qt.TabFocus
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/embedded_FocusScope.qml b/tests/auto/quick/qquickitem2/data/embedded_FocusScope.qml
new file mode 100644
index 0000000000..0d154f76e5
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/embedded_FocusScope.qml
@@ -0,0 +1,37 @@
+import QtQuick
+
+Rectangle {
+ width: 300
+ height: 300
+
+ FocusScope {
+ width: parent.width
+ height: parent.height
+ focus: true
+
+ Column {
+ anchors.fill: parent
+ anchors.rightMargin: 2
+ anchors.leftMargin: 2
+ anchors.topMargin: 10
+ spacing: 20
+ Rectangle {
+ objectName: "rect1"
+ width: parent.width
+ height: 30
+ border.width: 1
+ border.color: activeFocus ? "blue" : "black"
+ focusPolicy: Qt.TabFocus
+ }
+ Rectangle {
+ objectName: "rect2"
+ width: parent.width
+ height: 30
+ border.width: 1
+ border.color: activeFocus ? "blue" : "black"
+ focusPolicy: Qt.TabFocus
+ focus: true
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/focusInScopeChanges.qml b/tests/auto/quick/qquickitem2/data/focusInScopeChanges.qml
new file mode 100644
index 0000000000..3bf765a29d
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/focusInScopeChanges.qml
@@ -0,0 +1,31 @@
+import QtQuick
+
+Item {
+ id: main
+ objectName: "main"
+ width: 800
+ height: 600
+
+ FocusScope {
+ objectName: "focusScope"
+
+ Column {
+ Rectangle {
+ id: rectangle
+ focus: true
+ objectName: "rect"
+ width: textInput.width
+ height: textInput.height
+ border.width: 1
+ onActiveFocusChanged: textInput.forceActiveFocus()
+ }
+
+ TextInput {
+ id: textInput
+ objectName: "textInput"
+ font.pixelSize: 40
+ text: "focus me"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/focusReason.qml b/tests/auto/quick/qquickitem2/data/focusReason.qml
new file mode 100644
index 0000000000..7f9e303dba
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/focusReason.qml
@@ -0,0 +1,85 @@
+import QtQuick
+
+Item {
+ Component.onCompleted: item.focus = true
+ width: 640
+ height: 480
+
+ Column {
+ anchors.top: parent.top
+ anchors.topMargin: 10
+ spacing: 10
+ objectName: "column"
+ focusPolicy: Qt.ClickFocus
+
+ Item {
+ id: item
+ implicitWidth: 100
+ implicitHeight: 20
+ objectName: "item"
+ focusPolicy: Qt.TabFocus
+
+ Rectangle {
+ id: rect
+ anchors.fill: parent
+ color: "yellow"
+ opacity: 0.5
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onClicked: function onClicked(mouseEvent) {
+ if (mouseEvent.button == Qt.RightButton)
+ rect.color = "pink"
+ }
+ }
+ }
+
+ Item {
+ id: customText
+ objectName: "customText"
+ implicitWidth: 100
+ implicitHeight: 50
+ TextInput {
+ anchors.fill: parent
+ objectName: "textInputChild"
+ text: parent.activeFocus ? "focus" : "no focus"
+ }
+ activeFocusOnTab: true
+ }
+
+ Item {
+ id: customItem
+ objectName: "customItem"
+ implicitWidth: 100
+ implicitHeight: 50
+ Rectangle {
+ anchors.fill: parent
+ color: parent.activeFocus ? "red" : "blue"
+ opacity: 0.3
+ }
+ focusPolicy: Qt.WheelFocus
+ }
+
+ Text {
+ id: hyperlink
+ objectName: "hyperlink"
+ color: "blue"
+ onLinkActivated: { text = "Clicked"; }
+ textFormat: Text.RichText
+ text: "<a href=\"http://qt-project.org\">Qt Project website</a>"
+ focusPolicy: Qt.StrongFocus
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ acceptedButtons: Qt.NoButton // Don't eat the mouse clicks
+ cursorShape: Qt.PointingHandCursor
+ // the acceptedButtons will take precedence
+ // and the click focus policy will be ignored
+ focusPolicy: Qt.ClickFocus
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/grabToImage.qml b/tests/auto/quick/qquickitem2/data/grabToImage.qml
index 7df6d097a6..1298a3c6a9 100644
--- a/tests/auto/quick/qquickitem2/data/grabToImage.qml
+++ b/tests/auto/quick/qquickitem2/data/grabToImage.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickitem2/data/keysforward.qml b/tests/auto/quick/qquickitem2/data/keysforward.qml
index 8ea2d96022..09a0f926ed 100644
--- a/tests/auto/quick/qquickitem2/data/keysforward.qml
+++ b/tests/auto/quick/qquickitem2/data/keysforward.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickitem2/data/mapCoordinates.qml b/tests/auto/quick/qquickitem2/data/mapCoordinates.qml
index 1db5a4219d..29cfdd73cb 100644
--- a/tests/auto/quick/qquickitem2/data/mapCoordinates.qml
+++ b/tests/auto/quick/qquickitem2/data/mapCoordinates.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml b/tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml
index 2cd48adc06..06f625624a 100644
--- a/tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml
+++ b/tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml b/tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml
new file mode 100644
index 0000000000..98fc0e77af
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml
@@ -0,0 +1,51 @@
+import QtQuick
+
+QtObject {
+ id: root
+
+ property Window windowA: Window {
+ visible: true
+ flags: Qt.FramelessWindowHint
+ color: "green"
+ x: 100; y: 100
+ width: 300; height: 300
+
+ Rectangle {
+ objectName: "childItem"
+ x: 50; y: 50
+ width: 100; height: 100
+ color: "red"
+ }
+
+ WindowContainer {
+ x: 100; y: 100
+ width: 100; height: 100
+ window: Window {
+ objectName: "childWindow"
+ color: "blue"
+
+ Rectangle {
+ objectName: "childItemInChildWindow"
+ x: 30; y: 30
+ width: 50; height: 50
+ color: "orange"
+ }
+ }
+ }
+ }
+
+ property Window windowB: Window {
+ visible: true
+ flags: Qt.FramelessWindowHint
+ color: "magenta"
+ x: 500; y: 200
+ width: 200; height: 200
+
+ Rectangle {
+ objectName: "childItem"
+ x: 50; y: 50
+ width: 100; height: 100
+ color: "cyan"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/standardkeys.qml b/tests/auto/quick/qquickitem2/data/standardkeys.qml
index 68ee185e87..e19b0705c1 100644
--- a/tests/auto/quick/qquickitem2/data/standardkeys.qml
+++ b/tests/auto/quick/qquickitem2/data/standardkeys.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index f7601cade1..56271ec3f2 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <QtTest/QSignalSpy>
#include <QtQml/qqmlengine.h>
@@ -16,11 +17,17 @@
#include <QtQuick/private/qquickanchors_p.h>
#include <QtGui/qstylehints.h>
#include <private/qquickitem_p.h>
+#include <QtQuickTest/QtQuickTest>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
#include <QtQuickTestUtils/private/platforminputcontext_p.h>
#include <QtTest/private/qpropertytesthelper_p.h>
+#ifdef QT_WIDGETS_LIB
+#include <QtWidgets/qwidget.h>
+#include <QtWidgets/qboxlayout.h>
+#include <QtWidgets/qlineedit.h>
+#endif
using namespace QQuickVisualTestUtils;
@@ -87,6 +94,7 @@ private slots:
void mapCoordinates_data();
void mapCoordinatesRect();
void mapCoordinatesRect_data();
+ void mapCoordinatesWithWindows();
void propertyChanges();
void nonexistentPropertyConnection();
void transforms();
@@ -128,6 +136,14 @@ private slots:
void signalsOnDestruction();
void visibleChanged();
+ void lastFocusChangeReason();
+ void focusInScopeChanges();
+
+#ifdef QT_WIDGETS_LIB
+ void embeddedInWidgetsFocus_data();
+ void embeddedInWidgetsFocus();
+#endif
+
private:
QQmlEngine engine;
bool qt_tab_all_widgets() {
@@ -1873,90 +1889,90 @@ void tst_QQuickItem::layoutMirroring()
QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(rootItem);
QVERIFY(rootPrivate);
- QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
-
- QCOMPARE(anchorsMirrored(rootItem, "mirrored1"), true);
- QCOMPARE(anchorsMirrored(rootItem, "mirrored2"), true);
- QCOMPARE(anchorsMirrored(rootItem, "notMirrored1"), false);
- QCOMPARE(anchorsMirrored(rootItem, "notMirrored2"), false);
- QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror1"), true);
- QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror2"), true);
-
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
-
- QCOMPARE(childPrivate(rootItem, "mirrored1")->isMirrorImplicit, false);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->isMirrorImplicit, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->isMirrorImplicit, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->isMirrorImplicit, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->isMirrorImplicit, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->isMirrorImplicit, true);
-
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromParent, true);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromParent, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromParent, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromParent, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromParent, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromParent, true);
-
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromItem, true);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromItem, false);
+ QVERIFY(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "mirrored2")->effectiveLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "notMirrored2")->effectiveLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror);
+
+ QVERIFY(anchorsMirrored(rootItem, "mirrored1"));
+ QVERIFY(anchorsMirrored(rootItem, "mirrored2"));
+ QVERIFY(!anchorsMirrored(rootItem, "notMirrored1"));
+ QVERIFY(!anchorsMirrored(rootItem, "notMirrored2"));
+ QVERIFY(anchorsMirrored(rootItem, "inheritedMirror1"));
+ QVERIFY(anchorsMirrored(rootItem, "inheritedMirror2"));
+
+ QVERIFY(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "mirrored2")->inheritedLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "notMirrored2")->inheritedLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror);
+
+ QVERIFY(!childPrivate(rootItem, "mirrored1")->isMirrorImplicit);
+ QVERIFY(!childPrivate(rootItem, "mirrored2")->isMirrorImplicit);
+ QVERIFY(!childPrivate(rootItem, "notMirrored1")->isMirrorImplicit);
+ QVERIFY(childPrivate(rootItem, "notMirrored2")->isMirrorImplicit);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror1")->isMirrorImplicit);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror2")->isMirrorImplicit);
+
+ QVERIFY(childPrivate(rootItem, "mirrored1")->inheritMirrorFromParent);
+ QVERIFY(!childPrivate(rootItem, "mirrored2")->inheritMirrorFromParent);
+ QVERIFY(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromParent);
+ QVERIFY(!childPrivate(rootItem, "notMirrored2")->inheritMirrorFromParent);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromParent);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromParent);
+
+ QVERIFY(childPrivate(rootItem, "mirrored1")->inheritMirrorFromItem);
+ QVERIFY(!childPrivate(rootItem, "mirrored2")->inheritMirrorFromItem);
+ QVERIFY(!childPrivate(rootItem, "notMirrored1")->inheritMirrorFromItem);
+ QVERIFY(!childPrivate(rootItem, "notMirrored2")->inheritMirrorFromItem);
+ QVERIFY(!childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromItem);
+ QVERIFY(!childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromItem);
// load dynamic content using Loader that needs to inherit mirroring
rootItem->setProperty("state", "newContent");
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->effectiveLayoutMirror, true);
+ QVERIFY(!childPrivate(rootItem, "notMirrored3")->effectiveLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror3")->effectiveLayoutMirror);
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritedLayoutMirror, true);
+ QVERIFY(childPrivate(rootItem, "notMirrored3")->inheritedLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror3")->inheritedLayoutMirror);
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->isMirrorImplicit, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->isMirrorImplicit, true);
+ QVERIFY(!childPrivate(rootItem, "notMirrored3")->isMirrorImplicit);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror3")->isMirrorImplicit);
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromParent, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritMirrorFromParent, true);
+ QVERIFY(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromParent);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror3")->inheritMirrorFromParent);
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
+ QVERIFY(!childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem);
+ QVERIFY(!childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem);
// disable inheritance
rootItem->setProperty("childrenInherit", false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
+ QVERIFY(!childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, false);
+ QVERIFY(!childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror);
// re-enable inheritance
rootItem->setProperty("childrenInherit", true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror);
//
// dynamic parenting
@@ -1969,24 +1985,24 @@ void tst_QQuickItem::layoutMirroring()
// inherit in constructor
QQuickItem *childItem1 = new QQuickItem(parentItem1);
- QCOMPARE(QQuickItemPrivate::get(childItem1)->effectiveLayoutMirror, true);
- QCOMPARE(QQuickItemPrivate::get(childItem1)->inheritMirrorFromParent, true);
+ QVERIFY(QQuickItemPrivate::get(childItem1)->effectiveLayoutMirror);
+ QVERIFY(QQuickItemPrivate::get(childItem1)->inheritMirrorFromParent);
// inherit through a parent change
QQuickItem *childItem2 = new QQuickItem();
- QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, false);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, false);
+ QVERIFY(!QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror);
+ QVERIFY(!QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent);
childItem2->setParentItem(parentItem1);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, true);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, true);
+ QVERIFY(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror);
+ QVERIFY(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent);
// stop inherting through a parent change
QQuickItem *parentItem2 = new QQuickItem();
QQuickItemPrivate::get(parentItem2)->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
QQuickItemPrivate::get(parentItem2)->resolveLayoutMirror();
childItem2->setParentItem(parentItem2);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, false);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, false);
+ QVERIFY(!QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror);
+ QVERIFY(!QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent);
delete parentItem1;
delete parentItem2;
@@ -2002,11 +2018,11 @@ void tst_QQuickItem::layoutMirroringWindow()
window->show();
QQuickItemPrivate *content = QQuickItemPrivate::get(window->contentItem());
- QCOMPARE(content->effectiveLayoutMirror, true);
- QCOMPARE(content->inheritedLayoutMirror, true);
- QCOMPARE(content->isMirrorImplicit, false);
- QCOMPARE(content->inheritMirrorFromParent, true);
- QCOMPARE(content->inheritMirrorFromItem, true);
+ QVERIFY(content->effectiveLayoutMirror);
+ QVERIFY(content->inheritedLayoutMirror);
+ QVERIFY(!content->isMirrorImplicit);
+ QVERIFY(content->inheritMirrorFromParent);
+ QVERIFY(content->inheritMirrorFromItem);
}
void tst_QQuickItem::layoutMirroringIllegalParent()
@@ -2797,6 +2813,76 @@ void tst_QQuickItem::mapCoordinatesRect_data()
QTest::newRow(QTest::toString(i)) << i << i << i << i;
}
+void tst_QQuickItem::mapCoordinatesWithWindows()
+{
+ QQmlComponent component(&engine, testFileUrl("mapCoordinatesWithWindows.qml"));
+ std::unique_ptr<QObject> root(component.create());
+ QVERIFY(root);
+
+ auto *windowA = root->property("windowA").value<QQuickWindow*>();
+ QVERIFY(windowA);
+
+ // The window container geometry, parenting, etc, is applied
+ // during polish, so to test these we need to wait for one.
+ QVERIFY(QQuickTest::qWaitForPolish(windowA));
+
+ auto *childItem = windowA->findChild<QQuickItem*>("childItem");
+ QVERIFY(childItem);
+
+ QPoint itemPos = childItem->position().toPoint();
+ QCOMPARE(childItem->mapToScene({0, 0}), itemPos);
+ QCOMPARE(childItem->mapToGlobal({0, 0}), windowA->position() + itemPos);
+
+ auto *childItemInChildWindow = windowA->findChild<QQuickItem*>("childItemInChildWindow");
+ QVERIFY(childItemInChildWindow);
+
+ QPoint windowItemPos = childItemInChildWindow->position().toPoint();
+ QCOMPARE(childItemInChildWindow->mapToScene({0, 0}), windowItemPos);
+ QCOMPARE(childItemInChildWindow->mapToGlobal({0, 0}), windowA->position()
+ + childItemInChildWindow->window()->position() + windowItemPos);
+
+ QCOMPARE(childItemInChildWindow->mapToItem(nullptr, {0, 0}), windowItemPos);
+
+ auto globalItemOffset = [](QQuickItem *a, QQuickItem *b) {
+ return a->mapToGlobal({0, 0}) - b->mapToGlobal({0, 0});
+ };
+
+ QCOMPARE(childItemInChildWindow->mapToItem(childItem, {0, 0}),
+ globalItemOffset(childItemInChildWindow, childItem));
+ QCOMPARE(childItemInChildWindow->mapFromItem(childItem, {0, 0}),
+ globalItemOffset(childItem, childItemInChildWindow));
+
+ QCOMPARE(childItem->mapToItem(childItemInChildWindow, {0, 0}),
+ globalItemOffset(childItem, childItemInChildWindow));
+ QCOMPARE(childItem->mapFromItem(childItemInChildWindow, {0, 0}),
+ globalItemOffset(childItemInChildWindow, childItem));
+
+ auto *windowB = root->property("windowB").value<QQuickWindow*>();
+ QVERIFY(windowA);
+ auto *childItemInOtherWindow = windowB->findChild<QQuickItem*>("childItem");
+ QVERIFY(childItemInOtherWindow);
+
+ QCOMPARE(childItemInOtherWindow->mapToItem(childItem, {0, 0}),
+ globalItemOffset(childItemInOtherWindow, childItem));
+ QCOMPARE(childItemInOtherWindow->mapFromItem(childItem, {0, 0}),
+ globalItemOffset(childItem, childItemInOtherWindow));
+
+ QCOMPARE(childItem->mapToItem(childItemInOtherWindow, {0, 0}),
+ globalItemOffset(childItem, childItemInOtherWindow));
+ QCOMPARE(childItem->mapFromItem(childItemInOtherWindow, {0, 0}),
+ globalItemOffset(childItemInOtherWindow, childItem));
+
+ QCOMPARE(childItemInOtherWindow->mapToItem(childItemInChildWindow, {0, 0}),
+ globalItemOffset(childItemInOtherWindow, childItemInChildWindow));
+ QCOMPARE(childItemInOtherWindow->mapFromItem(childItemInChildWindow, {0, 0}),
+ globalItemOffset(childItemInChildWindow, childItemInOtherWindow));
+
+ QCOMPARE(childItemInChildWindow->mapToItem(childItemInOtherWindow, {0, 0}),
+ globalItemOffset(childItemInChildWindow, childItemInOtherWindow));
+ QCOMPARE(childItemInChildWindow->mapFromItem(childItemInOtherWindow, {0, 0}),
+ globalItemOffset(childItemInOtherWindow, childItemInChildWindow));
+}
+
void tst_QQuickItem::transforms_data()
{
QTest::addColumn<QByteArray>("qml");
@@ -3268,93 +3354,93 @@ void tst_QQuickItem::changeListener()
listeners << new TestListener(true);
// itemVisibilityChanged x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Visibility);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
parent->setVisible(false);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Visibility), 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemRotationChanged x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Rotation);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
parent->setRotation(90);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Rotation), 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemOpacityChanged x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Opacity);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
parent->setOpacity(0.5);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Opacity), 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemChildAdded() x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Children);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
child1 = new QQuickItem(parent);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Children), 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemParentChanged() x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(child1)->addItemChangeListener(listener, QQuickItemPrivate::Parent);
QCOMPARE(QQuickItemPrivate::get(child1)->changeListeners.size(), listeners.size());
child1->setParentItem(nullptr);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Parent), 1);
QCOMPARE(QQuickItemPrivate::get(child1)->changeListeners.size(), 0);
// itemImplicitWidthChanged() x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::ImplicitWidth);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
parent->setImplicitWidth(parent->implicitWidth() + 1);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::ImplicitWidth), 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemImplicitHeightChanged() x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::ImplicitHeight);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
parent->setImplicitHeight(parent->implicitHeight() + 1);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::ImplicitHeight), 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemGeometryChanged() x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Geometry);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
parent->setWidth(parent->width() + 1);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Geometry), 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemChildRemoved() x 5
child1->setParentItem(parent);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Children);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
delete child1;
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Children), 2);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemDestroyed() x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Destroyed);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
delete parent;
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Destroyed), 1);
}
@@ -4139,6 +4225,294 @@ void tst_QQuickItem::visibleChanged()
QCOMPARE(childItemSpy.count(), 1);
}
+void tst_QQuickItem::lastFocusChangeReason()
+{
+ std::unique_ptr<QQuickView> window = std::make_unique<QQuickView>();
+ window->setSource(testFileUrl("focusReason.qml"));
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window.get()));
+
+ QQuickItem *item = window->findChild<QQuickItem *>("item");
+ QQuickItem *customText = window->findChild<QQuickItem *>("customText");
+ QQuickItem *customItem = window->findChild<QQuickItem *>("customItem");
+ QQuickItem *hyperlink = window->findChild<QQuickItem *>("hyperlink");
+ QQuickItem *textInputChild = window->findChild<QQuickItem *>("textInputChild");
+
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ QQuickItemPrivate *customTextPrivate = QQuickItemPrivate::get(customText);
+ QQuickItemPrivate *customItemPrivate = QQuickItemPrivate::get(customItem);
+ QQuickItemPrivate *hyperlinkPrivate = QQuickItemPrivate::get(hyperlink);
+ QQuickItemPrivate *textInputChildPrivate = QQuickItemPrivate::get(textInputChild);
+
+ QVERIFY(item);
+ QVERIFY(customText);
+ QVERIFY(customItem);
+ QVERIFY(hyperlink);
+ QVERIFY(textInputChild);
+
+ QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusAllControls);
+ auto resetTabFocusBehavior = qScopeGuard([]{
+ QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusBehavior(-1));
+ });
+
+ // helper for clicking into an item
+ const auto itemCenter = [](const QQuickItem *item) -> QPoint {
+ return item->mapToScene(item->clipRect().center()).toPoint();
+ };
+
+ // setting focusPolicy to Strong/WheelFocus doesn't implicitly turn on event delivery
+ customText->setAcceptedMouseButtons(Qt::LeftButton);
+ customItem->setAcceptedMouseButtons(Qt::LeftButton);
+ customItem->setAcceptTouchEvents(true);
+ customText->setAcceptTouchEvents(true);
+ hyperlink->setAcceptTouchEvents(true);
+
+ // window activation -> ActiveWindowFocusReason
+ QVERIFY(item->hasFocus());
+ QVERIFY(item->hasActiveFocus());
+ if (itemPrivate->lastFocusChangeReason() != Qt::ActiveWindowFocusReason
+ && QStringList{"windows", "offscreen"}.contains(QGuiApplication::platformName())) {
+ QEXPECT_FAIL("", "On Windows and offscreen platforms, window activation does not set focus reason", Continue);
+ }
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::ActiveWindowFocusReason);
+
+ // test setter/getter
+ item->setFocus(false, Qt::MouseFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+ item->setFocus(true, Qt::TabFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+ item->setFocus(false, Qt::BacktabFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::BacktabFocusReason);
+ item->forceActiveFocus(Qt::ShortcutFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::ShortcutFocusReason);
+ item->setFocus(false, Qt::NoFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::NoFocusReason);
+ QVERIFY(!item->hasFocus());
+
+ // programmatic focus changes
+ item->setFocus(true, Qt::OtherFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::OtherFocusReason);
+
+ QVERIFY(item->hasFocus());
+ QVERIFY(item->hasActiveFocus());
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::OtherFocusReason);
+
+ // tab focus -> TabFocusReason
+ QTest::keyClick(window.get(), Qt::Key_Tab);
+ QVERIFY(customText->hasFocus());
+ QVERIFY(customText->hasActiveFocus());
+ QCOMPARE(qApp->focusObject(), customText);
+ QCOMPARE(customTextPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+
+ QTest::keyClick(window.get(), Qt::Key_Tab);
+ QVERIFY(customItem->hasFocus());
+ QVERIFY(customItem->hasActiveFocus());
+ QCOMPARE(qApp->focusObject(), customItem);
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+ QCOMPARE(customTextPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+
+ QTest::keyClick(window.get(), Qt::Key_Tab);
+ QVERIFY(hyperlink->hasFocus());
+ QVERIFY(hyperlink->hasActiveFocus());
+ QCOMPARE(qApp->focusObject(), hyperlink);
+ QCOMPARE(hyperlinkPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+ QCOMPARE(customTextPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+
+ QTest::keyClick(window.get(), Qt::Key_Tab);
+ QVERIFY(item->hasFocus());
+ QVERIFY(item->hasActiveFocus());
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+ QCOMPARE(hyperlinkPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+
+ // backtab -> BacktabFocusReason
+ QTest::keyClick(window.get(), Qt::Key_Tab, Qt::ShiftModifier);
+ QVERIFY(hyperlink->hasFocus());
+ QCOMPARE(hyperlinkPrivate->lastFocusChangeReason(), Qt::BacktabFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::BacktabFocusReason);
+
+ QTest::keyClick(window.get(), Qt::Key_Tab, Qt::ShiftModifier);
+ QVERIFY(customItem->hasFocus());
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::BacktabFocusReason);
+ QCOMPARE(hyperlinkPrivate->lastFocusChangeReason(), Qt::BacktabFocusReason);
+
+ QTest::keyClick(window.get(), Qt::Key_Tab, Qt::ShiftModifier);
+ QVERIFY(customText->hasFocus());
+ QCOMPARE(customTextPrivate->lastFocusChangeReason(), Qt::BacktabFocusReason);
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::BacktabFocusReason);
+
+ // click focus -> MouseFocusReason
+ QTest::mouseClick(window.get(), Qt::LeftButton, {}, itemCenter(customItem));
+ QVERIFY(customItem->hasFocus());
+ QVERIFY(customItem->hasActiveFocus());
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+ QCOMPARE(customTextPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+
+ QTest::mouseClick(window.get(), Qt::LeftButton, {}, itemCenter(hyperlink));
+ QVERIFY(hyperlink->hasFocus());
+ QVERIFY(hyperlink->hasActiveFocus());
+ QCOMPARE(hyperlinkPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+
+ QTest::mouseClick(window.get(), Qt::LeftButton, {}, itemCenter(customText));
+ QCOMPARE(textInputChild, textInputChild);
+ QVERIFY(textInputChild->hasFocus());
+ QVERIFY(textInputChild->hasActiveFocus());
+ QCOMPARE(textInputChildPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+ QCOMPARE(hyperlinkPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+
+ // touch focus -> MouseFocusReason
+ std::unique_ptr<QPointingDevice> touchDevice(QTest::createTouchDevice());
+
+ QTest::touchEvent(window.get(), touchDevice.get()).press(0, itemCenter(customItem));
+ QTest::touchEvent(window.get(), touchDevice.get()).press(0, itemCenter(customItem));
+ QTest::touchEvent(window.get(), touchDevice.get()).release(0, itemCenter(customItem));
+ QVERIFY(customItem->hasFocus());
+ QVERIFY(customItem->hasActiveFocus());
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+ QCOMPARE(textInputChildPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+
+ QTest::touchEvent(window.get(), touchDevice.get()).press(0, itemCenter(hyperlink));
+ QTest::touchEvent(window.get(), touchDevice.get()).release(0, itemCenter(hyperlink));
+ QVERIFY(hyperlink->hasFocus());
+ QVERIFY(hyperlink->hasActiveFocus());
+ QCOMPARE(hyperlinkPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+
+ // Wheel focus -> MouseFocusReason
+ QWheelEvent wheelEvent(QPointF(customItem->width() / 2, customItem->height() / 2), QPointF(),
+ QPoint(), QPoint(0, 10), Qt::NoButton, Qt::NoModifier,
+ Qt::NoScrollPhase, false);
+ QGuiApplication::sendEvent(customItem, &wheelEvent);
+ QVERIFY(customItem->hasActiveFocus());
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+}
+
+void tst_QQuickItem::focusInScopeChanges()
+{
+ std::unique_ptr<QQuickView> window = std::make_unique<QQuickView>();
+ window->setSource(testFileUrl("focusInScopeChanges.qml"));
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowFocused(window.get()));
+
+ QQuickItem *main = window->rootObject();
+ QVERIFY(main);
+ QQuickItem *focusScope = main->findChild<QQuickItem *>("focusScope");
+ QQuickItem *rect = main->findChild<QQuickItem *>("rect");
+ QQuickItem *textInput = main->findChild<QQuickItem *>("textInput");
+
+ QVERIFY(focusScope);
+ QVERIFY(rect);
+ QVERIFY(textInput);
+ QVERIFY(window->contentItem());
+
+ QSignalSpy fsActiveFocusSpy(focusScope, SIGNAL(activeFocusChanged(bool)));
+ QSignalSpy rectActiveFocusSpy(rect, SIGNAL(activeFocusChanged(bool)));
+ QSignalSpy textInputActiveFocusSpy(textInput, SIGNAL(activeFocusChanged(bool)));
+
+ // The window's content item will have activeFocus if window is focused
+ QTRY_VERIFY(window->contentItem()->hasActiveFocus());
+
+ QVERIFY(!focusScope->hasActiveFocus());
+ QVERIFY(!rect->hasActiveFocus());
+ QVERIFY(!textInput->hasActiveFocus());
+ QCOMPARE(fsActiveFocusSpy.size(), 0);
+ QCOMPARE(rectActiveFocusSpy.size(), 0);
+ QCOMPARE(textInputActiveFocusSpy.size(), 0);
+
+ // setting focus to rect shouldn't affect activeFocus as long as its
+ // parent focus scope doesn't have the activeFocus
+ rect->setFocus(true);
+ QCOMPARE(fsActiveFocusSpy.size(), 0);
+ QCOMPARE(rectActiveFocusSpy.size(), 0);
+ QCOMPARE(textInputActiveFocusSpy.size(), 0);
+
+ // focusScope is the only child with focus in the parent
+ // scope, so it will gain activeFocus
+ focusScope->setFocus(true);
+ QCOMPARE(fsActiveFocusSpy.size(), 1);
+ QVERIFY(fsActiveFocusSpy.first().at(0).toBool());
+ // rect loses activeFocus because textInput gains it (as a result of code in signal handler)
+ QCOMPARE(rectActiveFocusSpy.size(), 2);
+ QVERIFY(!rect->hasActiveFocus());
+ QCOMPARE(textInputActiveFocusSpy.size(), 1);
+ QVERIFY(textInput->hasActiveFocus());
+}
+
+#ifdef QT_WIDGETS_LIB
+void tst_QQuickItem::embeddedInWidgetsFocus_data()
+{
+ QTest::addColumn<QUrl>("source");
+ QTest::newRow("Embedded") << testFileUrl("embedded.qml");
+ QTest::newRow("Embedded Focus Scope") << testFileUrl("embedded_FocusScope.qml");
+}
+
+void tst_QQuickItem::embeddedInWidgetsFocus()
+{
+ QFETCH(QUrl, source);
+ QWidget root;
+ QVBoxLayout *layout = new QVBoxLayout(&root);
+
+ QLineEdit *lineEdit1 = new QLineEdit(&root);
+ lineEdit1->setFocusPolicy(Qt::FocusPolicy::TabFocus);
+
+ QQuickView *quickView = new QQuickView;
+ quickView->setSource(source);
+ QWidget *container = QWidget::createWindowContainer(quickView, &root);
+ container->setMinimumSize(quickView->size());
+ container->setFocusPolicy(Qt::TabFocus);
+
+ QLineEdit *lineEdit2 = new QLineEdit(&root);
+ lineEdit2->setFocusPolicy(Qt::FocusPolicy::TabFocus);
+
+ layout->addWidget(lineEdit1);
+ layout->addWidget(container);
+ layout->addWidget(lineEdit2);
+
+ QQuickItem *rect1 = findItem<QQuickItem>(quickView->rootObject(), "rect1");
+ QQuickItem *rect2 = findItem<QQuickItem>(quickView->rootObject(), "rect2");
+ QVERIFY(rect1);
+ QVERIFY(rect2);
+
+ root.show();
+ QTRY_VERIFY(root.isVisible());
+ QVERIFY(QTest::qWaitForWindowExposed(&root));
+ QVERIFY(QTest::qWaitForWindowFocused(root.windowHandle()));
+
+ lineEdit1->setFocus();
+ QTRY_VERIFY(lineEdit1->hasFocus());
+
+ // Tab forward
+ QTest::keyClick(QGuiApplication::focusWindow(), Qt::Key_Tab);
+ QTRY_VERIFY(container->hasFocus());
+ QVERIFY(QTest::qWaitForWindowFocused(quickView));
+ QVERIFY(rect1->hasActiveFocus());
+
+ QTest::keyClick(QGuiApplication::focusWindow(), Qt::Key_Tab);
+ QTRY_VERIFY(rect2->hasActiveFocus());
+
+ QTest::keyClick(QGuiApplication::focusWindow(), Qt::Key_Tab);
+ QVERIFY(QTest::qWaitForWindowFocused(root.windowHandle()));
+ QVERIFY(lineEdit2->hasFocus());
+ QVERIFY(!rect2->hasActiveFocus());
+
+ // Tab backwards
+ QTest::keyClick(QGuiApplication::focusWindow(), Qt::Key_Tab, Qt::ShiftModifier);
+ QTRY_VERIFY(container->hasFocus());
+ QVERIFY(QTest::qWaitForWindowFocused(quickView));
+ QVERIFY(rect2->hasActiveFocus());
+
+ QTest::keyClick(QGuiApplication::focusWindow(), Qt::Key_Tab, Qt::ShiftModifier);
+ QVERIFY(rect1->hasActiveFocus());
+
+ QTest::keyClick(QGuiApplication::focusWindow(), Qt::Key_Tab, Qt::ShiftModifier);
+ QVERIFY(QTest::qWaitForWindowFocused(root.windowHandle()));
+ QVERIFY(lineEdit1->hasFocus());
+}
+#endif
+
QTEST_MAIN(tst_QQuickItem)
#include "tst_qquickitem.moc"
diff --git a/tests/auto/quick/qquickitemlayer/CMakeLists.txt b/tests/auto/quick/qquickitemlayer/CMakeLists.txt
index ae98bd5bb5..b83ada3081 100644
--- a/tests/auto/quick/qquickitemlayer/CMakeLists.txt
+++ b/tests/auto/quick/qquickitemlayer/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickitemlayer Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickitemlayer LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
index 6cdcd2829c..fb18d2be54 100644
--- a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
+++ b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
diff --git a/tests/auto/quick/qquickitemrhiintegration/rhiitem.cpp b/tests/auto/quick/qquickitemrhiintegration/rhiitem.cpp
deleted file mode 100644
index bcc1f2f6a3..0000000000
--- a/tests/auto/quick/qquickitemrhiintegration/rhiitem.cpp
+++ /dev/null
@@ -1,352 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#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
deleted file mode 100644
index 6439bfba4a..0000000000
--- a/tests/auto/quick/qquickitemrhiintegration/rhiitem.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#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
deleted file mode 100644
index 5fe2de8de0..0000000000
--- a/tests/auto/quick/qquickitemrhiintegration/rhiitem_p.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#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.h b/tests/auto/quick/qquickitemrhiintegration/testrhiitem.h
deleted file mode 100644
index 94a50a6d9b..0000000000
--- a/tests/auto/quick/qquickitemrhiintegration/testrhiitem.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#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/tst_qquickitemrhiintegration.cpp b/tests/auto/quick/qquickitemrhiintegration/tst_qquickitemrhiintegration.cpp
deleted file mode 100644
index 9915c81fc1..0000000000
--- a/tests/auto/quick/qquickitemrhiintegration/tst_qquickitemrhiintegration.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#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/CMakeLists.txt b/tests/auto/quick/qquicklayouts/CMakeLists.txt
index 5f0b48f5a5..4716ee4a37 100644
--- a/tests/auto/quick/qquicklayouts/CMakeLists.txt
+++ b/tests/auto/quick/qquicklayouts/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicklayouts Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicklayouts LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquicklayouts/data/LayoutHelperLibrary.js b/tests/auto/quick/qquicklayouts/data/LayoutHelperLibrary.js
new file mode 100644
index 0000000000..7dbbc1ad64
--- /dev/null
+++ b/tests/auto/quick/qquicklayouts/data/LayoutHelperLibrary.js
@@ -0,0 +1,42 @@
+.pragma library
+
+
+function buildLayout(layoutData, parentItem) {
+ let layout = null
+ switch (layoutData.type) {
+ case "GridLayout":
+ case "RowLayout":
+ case "ColumnLayout":
+ layout = Qt.createQmlObject("import QtQuick.Layouts\n" +
+ layoutData.type + " {}", parentItem)
+ break
+ default:
+ console.log("data.layout.type not recognized(" + layoutdata.type + ")")
+ }
+ if (layout) {
+ for (let name in layoutData) {
+ let val = layoutData[name]
+ switch (name) {
+ case "items":
+ let arrLayoutData = layoutData.items
+ for (let i = 0; i < arrLayoutData.length; i++) {
+ let layoutItemDesc = arrLayoutData[i]
+ let strProps = ""
+ for (let keyName in layoutItemDesc) {
+ strProps += "Layout." + keyName + ": " + layoutItemDesc[keyName] + ";"
+ }
+ // For some reason we cannot assign the "Layout." attached properties from
+ // here, so for now we have to serialize them as strings.
+ let rect = Qt.createQmlObject("import QtQuick\nimport QtQuick.Layouts\n\nRectangle { implicitWidth: 20; implicitHeight: 20; " + strProps + "}", layout)
+ }
+ break;
+ case "type":
+ break;
+ default:
+ layout[name] = val
+ break;
+ }
+ }
+ }
+ return layout
+}
diff --git a/tests/auto/quick/qquicklayouts/data/rowlayout/Container.qml b/tests/auto/quick/qquicklayouts/data/rowlayout/Container.qml
index 962bc78580..9a5ae0cc7a 100644
--- a/tests/auto/quick/qquicklayouts/data/rowlayout/Container.qml
+++ b/tests/auto/quick/qquicklayouts/data/rowlayout/Container.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.7
import QtQuick.Layouts 1.3
diff --git a/tests/auto/quick/qquicklayouts/data/rowlayout/Container2.qml b/tests/auto/quick/qquicklayouts/data/rowlayout/Container2.qml
index a2aa7b93b2..30880e2d91 100644
--- a/tests/auto/quick/qquicklayouts/data/rowlayout/Container2.qml
+++ b/tests/auto/quick/qquicklayouts/data/rowlayout/Container2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.9
import QtQuick.Layouts 1.3
diff --git a/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser.qml b/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser.qml
index c324131ef6..22cf2353da 100644
--- a/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser.qml
+++ b/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.6
import QtQuick.Window 2.2
diff --git a/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser2.qml b/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser2.qml
index 7a5389e81e..46fbae02a0 100644
--- a/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser2.qml
+++ b/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.6
diff --git a/tests/auto/quick/qquicklayouts/data/rowlayout/LayerEnabled.qml b/tests/auto/quick/qquicklayouts/data/rowlayout/LayerEnabled.qml
index d7ad38ffaf..ac12868627 100644
--- a/tests/auto/quick/qquicklayouts/data/rowlayout/LayerEnabled.qml
+++ b/tests/auto/quick/qquicklayouts/data/rowlayout/LayerEnabled.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.7
import QtQuick.Layouts 1.3
diff --git a/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
index 261b8a9a8e..f311cc34d6 100644
--- a/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
+++ b/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
@@ -1,9 +1,10 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.6
import QtTest 1.0
import QtQuick.Layouts 1.1
+import "LayoutHelperLibrary.js" as LayoutHelpers
Item {
id: container
@@ -207,7 +208,7 @@ Item {
}
function test_flowLeftToRightDefaultPositions() {
- ignoreWarning("QGridLayoutEngine::addItem: Cell (1, 0) already taken");
+ ignoreWarning(/QGridLayoutEngine::addItem: Can't add .* at cell \(1, 0\) because it's already taken by .*/);
var layout = createTemporaryObject(layout_flowLeftToRightDefaultPositions_Component, container);
compare(layout.implicitWidth, 40);
compare(layout.children[0].x, 0);
@@ -1255,5 +1256,126 @@ Item {
}
verify(layout.implicitHeight > initialImplicitHeight)
}
+
+ function test_uniformCellSizes_data()
+ {
+ return [
+ {
+ tag: "hor 9/3",
+ layout: {
+ type: "GridLayout",
+ columns: 3,
+ items: [
+ {minimumWidth: 1, preferredWidth: 10, maximumWidth: 20, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 4, maximumWidth: 10, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 50, maximumWidth: 99, fillWidth: true}
+ ]
+ },
+ layoutWidth: 9,
+ expectedWidths: [3, 3, 3],
+ expectedPositions: [0, 3, 6]
+ },
+ {
+ tag: "hor 30/3",
+ layout: {
+ type: "GridLayout",
+ columns: 3,
+ items: [
+ {minimumWidth: 1, preferredWidth: 10, maximumWidth: 20, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 4, maximumWidth: 10, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 50, maximumWidth: 99, fillWidth: true}
+ ]
+ },
+ layoutWidth: 30,
+ expectedWidths: [10, 10, 10]
+ },
+ {
+ tag: "hor 60/3",
+ layout: {
+ type: "GridLayout",
+ columns: 3,
+ items: [
+ {minimumWidth: 1, preferredWidth: 10, maximumWidth: 20, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 4, maximumWidth: 10, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 50, maximumWidth: 99, fillWidth: true}
+ ]
+ },
+ layoutWidth: 60,
+ expectedWidths: [20, 10, 20], // We are beyond the maximumWidth. of the middle item,
+ expectedPositions: [0, 20, 40] // check that *cellSize* is still uniform
+ // (middle item will be left-aligned in the cell by default)
+ },
+ {
+ tag: "hor 66/3",
+ layout: {
+ type: "GridLayout",
+ columns: 3,
+ items: [
+ {minimumWidth: 1, preferredWidth: 10, maximumWidth: 20, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 4, maximumWidth: 10, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 50, maximumWidth: 99, fillWidth: true}
+ ]
+ },
+ layoutWidth: 66,
+ expectedWidths: [20, 10, 22],
+ expectedPositions: [0, 22, 44]
+ },
+ {
+ tag: "ver 66/3",
+ layout: {
+ type: "GridLayout",
+ columns: 1,
+ items: [
+ {minimumHeight: 1, preferredHeight: 10, maximumHeight: 20, fillHeight: true},
+ {minimumHeight: 1, preferredHeight: 4, maximumHeight: 10, fillHeight: true},
+ {minimumHeight: 1, preferredHeight: 50, maximumHeight: 99, fillHeight: true}
+ ]
+ },
+ layoutHeight: 66,
+ expectedHeights: [20, 10, 22],
+ // If items are too small to fit the cell, they have a default alignment of
+ // Qt::AlignLeft | Qt::AlignVCenter
+ expectedPositions: [1, 22+6, 44]
+ }
+ ];
+ }
+
+ function test_uniformCellSizes(data)
+ {
+ let layout = LayoutHelpers.buildLayout(data.layout, testCase)
+ let isHorizontal = data.hasOwnProperty("expectedWidths")
+ layout.rowSpacing = 0
+ layout.columnSpacing = 0
+ layout.uniformCellWidths = true
+ layout.uniformCellHeights = true
+ waitForPolish(layout)
+ if (data.hasOwnProperty('layoutWidth')) {
+ layout.width = data.layoutWidth
+ }
+ if (data.hasOwnProperty('layoutHeight')) {
+ layout.height = data.layoutHeight
+ }
+
+ let expectedSizes = isHorizontal ? data.expectedWidths : data.expectedHeights
+ let actualSizes = []
+ let i = 0
+ for (i = 0; i < layout.children.length; i++) {
+ let item = layout.children[i]
+ actualSizes.push(isHorizontal ? item.width : item.height)
+ }
+ compare(actualSizes, expectedSizes)
+
+ if (data.hasOwnProperty('expectedPositions')) {
+ let actualPositions = []
+ // If items are too small to fit the cell, they have a default alignment of
+ // Qt::AlignLeft | Qt::AlignVCenter
+ for (i = 0; i < layout.children.length; i++) {
+ let item = layout.children[i]
+ actualPositions.push(isHorizontal ? item.x : item.y)
+ }
+ compare(actualPositions, data.expectedPositions)
+ }
+ }
+
}
}
diff --git a/tests/auto/quick/qquicklayouts/data/tst_layoutproxy.qml b/tests/auto/quick/qquicklayouts/data/tst_layoutproxy.qml
new file mode 100644
index 0000000000..28b0f9a61c
--- /dev/null
+++ b/tests/auto/quick/qquicklayouts/data/tst_layoutproxy.qml
@@ -0,0 +1,687 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.6
+import QtTest 1.0
+import QtQuick.Layouts
+
+Item {
+ id: container
+ width: 200
+ height: 200
+ TestCase {
+ id: testCase
+ name: "Tests_LayoutProxy"
+ when: windowShown
+ width: parent.width
+ height: parent.height
+
+ Component {
+ id: layout_proxy_Component
+ Item {
+ anchors.fill: container
+
+ property var rect1: Rectangle {
+ id: redRectanlge
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: 0
+ property var itemRect: [mapToItem(container, Qt.point(0, 0)).x,
+ mapToItem(container, Qt.point(0, 0)).y,
+ width, height]
+ color: "red"
+ }
+
+
+ property var rect2: Rectangle {
+ id: blueRectanlge
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: 0
+ property var itemRect: [mapToItem(container, Qt.point(0, 0)).x,
+ mapToItem(container, Qt.point(0, 0)).y,
+ width, height]
+ color: "blue"
+ }
+
+ property var layout1: RowLayout {
+ parent: container
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: redRectanlge }
+ LayoutItemProxy { target: blueRectanlge }
+ }
+
+ property var layout2: ColumnLayout {
+ parent: container
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: redRectanlge }
+ LayoutItemProxy { target: blueRectanlge }
+ }
+ }
+ }
+
+ function test_Proxy_simple()
+ {
+ var item = createTemporaryObject(layout_proxy_Component, container);
+
+ item.layout2.visible = false
+ item.layout1.visible = true
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 100, 200])
+ tryCompare(item.rect2, "itemRect", [ 100, 0, 100, 200])
+
+ item.layout1.visible = false
+ item.layout2.visible = true
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 200, 100])
+ tryCompare(item.rect2, "itemRect", [ 0, 100, 200, 100])
+
+ item.layout1.visible = true
+ item.layout2.visible = false
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 100, 200])
+ tryCompare(item.rect2, "itemRect", [ 100, 0, 100, 200])
+
+ }
+
+ function test_Proxy_layout_destruction1()
+ {
+ var item = createTemporaryObject(layout_proxy_Component, container);
+
+ item.layout1.visible = true
+ item.layout2.visible = false
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 100, 200])
+ tryCompare(item.rect2, "itemRect", [ 100, 0, 100, 200])
+
+ item.layout1.visible = false
+ item.layout2.visible = true
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 200, 100])
+ tryCompare(item.rect2, "itemRect", [ 0, 100, 200, 100])
+
+ item.layout2.destroy() //destroy the layout that has control
+ wait(0) // process the scheduled delete and actually invoke the dtor
+ compare(item.layout2, null)
+ item.layout1.visible = true //check that the other one still works
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 100, 200])
+ tryCompare(item.rect2, "itemRect", [ 100, 0, 100, 200])
+ }
+
+ function test_Proxy_layout_destruction2()
+ {
+ var item = createTemporaryObject(layout_proxy_Component, container);
+
+ item.layout1.visible = false
+ item.layout2.visible = false
+
+ //destroy both layouts while none has control
+ item.layout1.destroy()
+ item.layout2.destroy()
+ wait(0) // process the scheduled delete and actually invoke the dtor
+ //all layouts should be gone now
+ compare(item.layout1, null)
+ compare(item.layout2, null)
+ //but the rectangles should still be here
+ verify(item.rect1 !== null)
+ verify(item.rect2 !== null)
+ }
+
+ function test_Proxy_layout_destruction3()
+ {
+ var item = createTemporaryObject(layout_proxy_Component, container);
+
+ item.layout1.visible = true
+ item.layout2.visible = true
+
+ //destroy both layouts while both have control
+ item.layout1.destroy()
+ item.layout2.destroy()
+ wait(0) // process the scheduled delete and actually invoke the dtor
+ //all layouts should be gone now
+ compare(item.layout1, null)
+ compare(item.layout2, null)
+ //but the rectangles should still be here
+ verify(item.rect1 !== null)
+ verify(item.rect2 !== null)
+ }
+
+ function test_Proxy_layout_destruction_of_targets()
+ {
+ var item = createTemporaryObject(layout_proxy_Component, container);
+
+ item.layout1.visible = true
+ item.layout2.visible = false
+
+ //destroy a rectangle just to see if the proxy crashes
+ item.rect1.destroy()
+ wait(0) // process the scheduled delete and actually invoke the dtor
+ compare(item.rect1, null)
+
+ //the proxy still has the size of the item and is still there
+ tryCompare(item.layout1.children[0], "x", 0)
+ tryCompare(item.layout1.children[0], "y", 0)
+ tryCompare(item.layout1.children[0], "width", 100)
+ tryCompare(item.layout1.children[0], "height", 200)
+ //the second item is still here
+ tryCompare(item.rect2, "itemRect", [ 100, 0, 100, 200])
+ //the most important thing is that it does not crash
+
+ }
+
+ Component {
+ id: layout_proxy_Component_Three
+ Item {
+ anchors.fill: container
+ property var rect1: Rectangle {
+ id: redRectanlge
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: 0
+ property var itemRect: [mapToItem(container, Qt.point(0, 0)).x,
+ mapToItem(container, Qt.point(0, 0)).y,
+ width, height]
+ color: "red"
+ }
+
+ property var rect2: Rectangle {
+ id: blueRectanlge
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: 0
+ property var itemRect: [mapToItem(container, Qt.point(0, 0)).x,
+ mapToItem(container, Qt.point(0, 0)).y,
+ width, height]
+ color: "blue"
+ }
+
+ property var layout1: RowLayout {
+ parent: container
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: redRectanlge }
+ LayoutItemProxy { target: blueRectanlge }
+ }
+
+ property var layout2: ColumnLayout {
+ parent: container
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: redRectanlge }
+ LayoutItemProxy { target: blueRectanlge }
+ }
+
+ property var layout3: ColumnLayout {
+ parent: container
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: redRectanlge }
+ LayoutItemProxy { target: blueRectanlge }
+ Rectangle {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ color: "green"
+ }
+ }
+ }
+ }
+
+ function test_Proxy_native_item()
+ {
+ var item = createTemporaryObject(layout_proxy_Component_Three, container);
+
+ item.layout1.visible = true
+ item.layout2.visible = false
+ item.layout3.visible = false
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 100, 200])
+ tryCompare(item.rect2, "itemRect", [ 100, 0, 100, 200])
+
+ item.layout1.visible = false
+ item.layout2.visible = true
+ item.layout3.visible = false
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 200, 100])
+ tryCompare(item.rect2, "itemRect", [ 0, 100, 200, 100])
+
+ item.layout1.visible = false
+ item.layout2.visible = false
+ item.layout3.visible = true
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 200, 67]) //66.6 = 67
+ tryCompare(item.rect2, "itemRect", [ 0, 67, 200, 66])
+ }
+
+
+ Component {
+ id: layout_proxy_Component_overwrite
+ Item {
+ anchors.fill: container
+ property var rect1: Rectangle {
+ id: redRectanlge
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.preferredWidth: 180
+ Layout.preferredHeight: 180
+ Layout.margins: 0
+ property var itemRect: [mapToItem(container, Qt.point(0, 0)).x,
+ mapToItem(container, Qt.point(0, 0)).y,
+ width, height]
+ color: "red"
+ }
+
+ property var rect2: Rectangle {
+ id: blueRectanlge
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ Layout.margins: 0
+ property var itemRect: [mapToItem(container, Qt.point(0, 0)).x,
+ mapToItem(container, Qt.point(0, 0)).y,
+ width, height]
+ color: "blue"
+ }
+
+ property var layout1: RowLayout {
+ parent: container
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: redRectanlge }
+ LayoutItemProxy { target: blueRectanlge }
+ }
+
+ property var layout2: ColumnLayout {
+ parent: container
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: redRectanlge }
+ LayoutItemProxy { target: blueRectanlge }
+ }
+ }
+ }
+
+ function test_Proxy_overwrite_layout_properties()
+ {
+ var item = createTemporaryObject(layout_proxy_Component_overwrite, container);
+
+ item.layout1.visible = true
+ item.layout2.visible = false
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 180, 200])
+ tryCompare(item.rect2, "itemRect", [ 180, 0, 20, 200])
+
+ item.layout1.visible = false
+ item.layout2.visible = true
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 200, 180])
+ tryCompare(item.rect2, "itemRect", [ 0, 180, 200, 20])
+
+ //should overwrite the rectangles preferences
+ item.layout1.children[0].Layout.preferredWidth = 100
+ item.layout1.children[0].Layout.preferredHeight = 100
+ item.layout1.children[1].Layout.preferredWidth = 100
+ item.layout1.children[1].Layout.preferredHeight = 100
+
+ item.layout1.visible = true
+ item.layout2.visible = false
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 100, 200])
+ tryCompare(item.rect2, "itemRect", [ 100, 0, 100, 200])
+ }
+
+ Component {
+ id: layout_proxy_Component_overwrite_declarative
+ Item {
+ anchors.fill: container
+ property var rect1: Rectangle {
+ id: redRectanlge
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.minimumWidth: 1
+ Layout.minimumHeight: 1
+ Layout.maximumWidth: 3
+ Layout.maximumHeight: 3
+ Layout.preferredWidth: 2
+ Layout.preferredHeight: 2
+ Layout.margins: 1
+ Layout.leftMargin: 2
+ Layout.topMargin: 3
+ Layout.rightMargin: 4
+ Layout.bottomMargin: 5
+ Layout.alignment: Qt.AlignBottom
+ property var itemRect: [mapToItem(container, Qt.point(0, 0)).x,
+ mapToItem(container, Qt.point(0, 0)).y,
+ width, height]
+ color: "red"
+ }
+
+
+ property var layout1: RowLayout {
+ parent: container
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: redRectanlge
+ Layout.fillWidth: false
+ Layout.fillHeight: false
+ Layout.minimumWidth: 100
+ Layout.minimumHeight: 100
+ Layout.maximumWidth: 300
+ Layout.maximumHeight: 300
+ Layout.preferredWidth: 200
+ Layout.preferredHeight: 200
+ Layout.margins: 100
+ Layout.leftMargin: 200
+ Layout.topMargin: 300
+ Layout.rightMargin: 400
+ Layout.bottomMargin: 500
+ Layout.alignment: Qt.AlignTop
+ }
+ }
+
+ property var layout2: RowLayout {
+ parent: container
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: redRectanlge }
+ }
+ }
+ }
+
+ function test_Proxy_overwrite_layout_properties_declarative()
+ {
+ var item = createTemporaryObject(layout_proxy_Component_overwrite_declarative, container);
+
+ compare(item.layout2.children[0].Layout.fillWidth, item.rect1.Layout.fillWidth)
+ compare(item.layout2.children[0].Layout.fillHeight, item.rect1.Layout.fillHeight)
+ compare(item.layout2.children[0].Layout.minimumWidth, item.rect1.Layout.minimumWidth)
+ compare(item.layout2.children[0].Layout.minimumHeight, item.rect1.Layout.minimumHeight)
+ compare(item.layout2.children[0].Layout.maximumWidth, item.rect1.Layout.maximumWidth)
+ compare(item.layout2.children[0].Layout.maximumHeight, item.rect1.Layout.maximumHeight)
+ compare(item.layout2.children[0].Layout.preferredWidth, item.rect1.Layout.preferredWidth)
+ compare(item.layout2.children[0].Layout.preferredHeight, item.rect1.Layout.preferredHeight)
+ compare(item.layout2.children[0].Layout.margins, item.rect1.Layout.margins)
+ compare(item.layout2.children[0].Layout.leftMargin, item.rect1.Layout.leftMargin)
+ compare(item.layout2.children[0].Layout.topMargin, item.rect1.Layout.topMargin)
+ compare(item.layout2.children[0].Layout.rightMargin, item.rect1.Layout.rightMargin)
+ compare(item.layout2.children[0].Layout.bottomMargin, item.rect1.Layout.bottomMargin)
+ compare(item.layout2.children[0].Layout.alignment, item.rect1.Layout.alignment)
+
+ verify(item.layout1.children[0].Layout.fillWidth != item.rect1.Layout.fillWidth)
+ verify(item.layout1.children[0].Layout.fillHeight != item.rect1.Layout.fillHeight)
+ verify(item.layout1.children[0].Layout.minimumWidth != item.rect1.Layout.minimumWidth)
+ verify(item.layout1.children[0].Layout.minimumHeight != item.rect1.Layout.minimumHeight)
+ verify(item.layout1.children[0].Layout.maximumWidth != item.rect1.Layout.maximumWidth)
+ verify(item.layout1.children[0].Layout.maximumHeight != item.rect1.Layout.maximumHeight)
+ verify(item.layout1.children[0].Layout.preferredWidth != item.rect1.Layout.preferredWidth)
+ verify(item.layout1.children[0].Layout.preferredHeight != item.rect1.Layout.preferredHeight)
+ verify(item.layout1.children[0].Layout.margins != item.rect1.Layout.margins)
+ verify(item.layout1.children[0].Layout.leftMargin != item.rect1.Layout.leftMargin)
+ verify(item.layout1.children[0].Layout.topMargin != item.rect1.Layout.topMargin)
+ verify(item.layout1.children[0].Layout.rightMargin != item.rect1.Layout.rightMargin)
+ verify(item.layout1.children[0].Layout.bottomMargin != item.rect1.Layout.bottomMargin)
+ verify(item.layout1.children[0].Layout.alignment != item.rect1.alignment)
+
+ compare(item.layout1.children[0].Layout.fillWidth, false)
+ compare(item.layout1.children[0].Layout.fillHeight, false)
+ compare(item.layout1.children[0].Layout.minimumWidth, item.rect1.Layout.minimumWidth * 100)
+ compare(item.layout1.children[0].Layout.minimumHeight, item.rect1.Layout.minimumHeight * 100)
+ compare(item.layout1.children[0].Layout.maximumWidth, item.rect1.Layout.maximumWidth * 100)
+ compare(item.layout1.children[0].Layout.maximumHeight, item.rect1.Layout.maximumHeight * 100)
+ compare(item.layout1.children[0].Layout.preferredWidth, item.rect1.Layout.preferredWidth * 100)
+ compare(item.layout1.children[0].Layout.preferredHeight, item.rect1.Layout.preferredHeight * 100)
+ compare(item.layout1.children[0].Layout.margins, item.rect1.Layout.margins * 100)
+ compare(item.layout1.children[0].Layout.leftMargin, item.rect1.Layout.leftMargin * 100)
+ compare(item.layout1.children[0].Layout.topMargin, item.rect1.Layout.topMargin * 100)
+ compare(item.layout1.children[0].Layout.rightMargin, item.rect1.Layout.rightMargin * 100)
+ compare(item.layout1.children[0].Layout.bottomMargin, item.rect1.Layout.bottomMargin * 100)
+ compare(item.layout1.children[0].Layout.alignment, Qt.AlignTop)
+ }
+
+ Component {
+ id: layout_proxy_Component_nesting
+ Item {
+ anchors.fill: container
+
+ property var rect1: Rectangle {
+ id: redRectanlge
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: 0
+ property var itemRect: [parent ? parent.mapToItem(container, Qt.point(x, y)).x : 0,
+ parent ? parent.mapToItem(container, Qt.point(x, y)).y : 0,
+ width, height]
+ color: "red"
+ }
+
+
+ property var rect2: Rectangle {
+ id: blueRectanlge
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: 0
+ property var itemRect: [parent ? parent.mapToItem(container, Qt.point(x, y)).x : 0,
+ parent ? parent.mapToItem(container, Qt.point(x, y)).y : 0,
+ width, height]
+ color: "blue"
+ }
+
+ property var rect3: Rectangle {
+ id: greenRectanlge
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: 0
+ property var itemRect: [parent ? parent.mapToItem(container, Qt.point(x, y)).x : 0,
+ parent ? parent.mapToItem(container, Qt.point(x, y)).y : 0,
+ width, height]
+ color: "green"
+ }
+
+ property var layout1: RowLayout {
+ parent: container
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: redRectanlge }
+ ColumnLayout {
+ spacing: 0
+ LayoutItemProxy { target: blueRectanlge }
+ LayoutItemProxy { target: greenRectanlge }
+ }
+ }
+
+ property var layout2: ColumnLayout {
+ parent: container
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: redRectanlge }
+ RowLayout {
+ spacing: 0
+ LayoutItemProxy { target: blueRectanlge }
+ LayoutItemProxy { target: greenRectanlge }
+ }
+ }
+ }
+ }
+
+ function test_Proxy_nesting()
+ {
+ var item = createTemporaryObject(layout_proxy_Component_nesting, container);
+
+ item.layout2.visible = false
+ item.layout1.visible = true
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 100, 200])
+ tryCompare(item.rect2, "itemRect", [ 100, 0, 100, 100])
+ tryCompare(item.rect3, "itemRect", [ 100, 100, 100, 100])
+
+ item.layout1.visible = false
+ item.layout2.visible = true
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 200, 100])
+ tryCompare(item.rect2, "itemRect", [ 0, 100, 100, 100])
+ tryCompare(item.rect3, "itemRect", [ 100, 100, 100, 100])
+
+ item.layout1.visible = true
+ item.layout2.visible = false
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 100, 200])
+ tryCompare(item.rect2, "itemRect", [ 100, 0, 100, 100])
+ tryCompare(item.rect3, "itemRect", [ 100, 100, 100, 100])
+ }
+
+
+
+ Component {
+ id: layout_proxy_Component_nesting_item
+ Item {
+ anchors.fill: container
+
+ property var rect1: Rectangle {
+ id: redRectanlge
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: 0
+ property var itemRect: [parent ? parent.mapToItem(container, Qt.point(x, y)).x : 0,
+ parent ? parent.mapToItem(container, Qt.point(x, y)).y : 0,
+ width, height]
+ color: "red"
+ }
+
+ property var rect2: Rectangle {
+ id: blueRectanlge
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: 0
+ property var itemRect: [parent ? parent.mapToItem(container, Qt.point(x, y)).x : 0,
+ parent ? parent.mapToItem(container, Qt.point(x, y)).y : 0,
+ width, height]
+ color: "blue"
+ }
+
+ property var rect3: Rectangle {
+ id: greenRectanlge
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: 0
+ property var itemRect: [parent ? parent.mapToItem(container, Qt.point(x, y)).x : 0,
+ parent ? parent.mapToItem(container, Qt.point(x, y)).y : 0,
+ width, height]
+ color: "green"
+ }
+
+ property var rect4: Rectangle {
+ id: yellowRectangle
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: 0
+ property var itemRect: [parent ? parent.mapToItem(container, Qt.point(x, y)).x : 0,
+ parent ? parent.mapToItem(container, Qt.point(x, y)).y : 0,
+ width, height]
+ color: "yellow"
+ }
+
+ property var rect5: Rectangle {
+ id: brownRectangle
+ parent: container
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: 0
+ property var itemRect: [parent ? parent.mapToItem(container, Qt.point(x, y)).x : 0,
+ parent ? parent.mapToItem(container, Qt.point(x, y)).y : 0,
+ width, height]
+ color: "brown"
+ }
+
+ property var layout1: RowLayout {
+ parent: container
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: redRectanlge }
+ ColumnLayout {
+ spacing: 0
+ LayoutItemProxy { target: blueRectanlge }
+ LayoutItemProxy { target: greenRectanlge }
+ Item {
+ implicitWidth: rll.implicitWidth
+ implicitHeight: rll.implicitHeight
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ RowLayout {
+ id: rll
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: yellowRectangle }
+ LayoutItemProxy { target: brownRectangle }
+ }
+ }
+ }
+ }
+
+ property var layout2: ColumnLayout {
+ parent: container
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: redRectanlge }
+ RowLayout {
+ spacing: 0
+ LayoutItemProxy { target: blueRectanlge }
+ LayoutItemProxy { target: greenRectanlge }
+ Item {
+ implicitWidth: cll.implicitWidth
+ implicitHeight: cll.implicitHeight
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ ColumnLayout {
+ id: cll
+ anchors.fill: parent
+ spacing: 0
+ LayoutItemProxy { target: yellowRectangle }
+ LayoutItemProxy { target: brownRectangle }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ function test_Proxy_nesting_item()
+ {
+ var item = createTemporaryObject(layout_proxy_Component_nesting_item, container);
+
+ item.layout1.visible = true
+ item.layout2.visible = false
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 100, 200])
+ tryCompare(item.rect2, "itemRect", [ 100, 0, 100, 67])
+ tryCompare(item.rect3, "itemRect", [ 100, 67, 100, 66])
+ tryCompare(item.rect4, "itemRect", [ 100, 133, 50, 67])
+ tryCompare(item.rect5, "itemRect", [ 150, 133, 50, 67])
+
+ item.layout2.visible = true
+ item.layout1.visible = false
+
+ tryCompare(item.rect1, "itemRect", [ 0, 0, 200, 100])
+ tryCompare(item.rect2, "itemRect", [ 0, 100, 67, 100])
+ tryCompare(item.rect3, "itemRect", [ 67, 100, 66, 100])
+ tryCompare(item.rect4, "itemRect", [ 133, 100, 67, 50])
+ tryCompare(item.rect5, "itemRect", [ 133, 150, 67, 50])
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
index 506893b631..56198f0d2e 100644
--- a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
+++ b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
@@ -1,9 +1,11 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-import QtQuick 2.2
-import QtTest 1.0
-import QtQuick.Layouts 1.0
+import QtQuick
+import QtTest
+import QtQuick.Controls
+import QtQuick.Layouts
+import "LayoutHelperLibrary.js" as LayoutHelpers
import org.qtproject.Test
@@ -23,6 +25,13 @@ Item {
return [item.x, item.y, item.width, item.height];
}
+ function cleanup() {
+ if (LayoutSetup.useDefaultSizePolicy) {
+ LayoutSetup.useDefaultSizePolicy = false
+ compare(LayoutSetup.useDefaultSizePolicy, false)
+ }
+ }
+
Component {
id: rectangle_Component
Rectangle {
@@ -926,6 +935,28 @@ Item {
},
layoutWidth: 28,
expectedWidths: [22, 6]
+ },{
+ tag: "resize_to_0_width",
+ layout: {
+ type: "RowLayout",
+ items: [
+ {preferredWidth: 10, fillWidth: true},
+ ]
+ },
+ layoutWidth: 0,
+ expectedWidths: [0]
+ },{
+ tag: "preferred_infinity", // Do not crash/assert when the preferred size is infinity
+ layout: {
+ type: "RowLayout",
+ items: [
+ {minimumWidth: 10, preferredWidth: Number.POSITIVE_INFINITY, fillWidth: true},
+ {minimumWidth: 20, preferredWidth: Number.POSITIVE_INFINITY, fillWidth: true},
+ ]
+ },
+ layoutWidth: 31, // Important that this is between minimum and preferred width of the layout.
+ expectedWidths: [10, 21] // The result here does not have to be exact. (This
+ // test is mostly concerned about not crashing).
}
];
}
@@ -946,6 +977,148 @@ Item {
layout.destroy();
}
+ function test_uniformCellSizes_data()
+ {
+ return [
+ {
+ tag: "hor 9/3",
+ layout: {
+ type: "RowLayout",
+ items: [
+ {minimumWidth: 1, preferredWidth: 10, maximumWidth: 20, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 4, maximumWidth: 10, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 50, maximumWidth: 99, fillWidth: true}
+ ]
+ },
+ layoutWidth: 9,
+ expectedWidths: [3, 3, 3],
+ expectedPositions: [0, 3, 6]
+ },
+ {
+ tag: "hor 30/3",
+ layout: {
+ type: "RowLayout",
+ items: [
+ {minimumWidth: 1, preferredWidth: 10, maximumWidth: 20, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 4, maximumWidth: 10, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 50, maximumWidth: 99, fillWidth: true}
+ ]
+ },
+ layoutWidth: 30,
+ expectedWidths: [10, 10, 10]
+ },
+ {
+ tag: "hor 60/3",
+ layout: {
+ type: "RowLayout",
+ items: [
+ {minimumWidth: 1, preferredWidth: 10, maximumWidth: 20, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 4, maximumWidth: 10, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 50, maximumWidth: 99, fillWidth: true}
+ ]
+ },
+ layoutWidth: 60,
+ expectedWidths: [20, 10, 20], // We are beyond the maximumWidth. of the middle item,
+ expectedPositions: [0, 20, 40] // check that *cellSize* is still uniform
+ // (middle item will be left-aligned in the cell by default)
+ },
+ {
+ tag: "hor 66/3",
+ layout: {
+ type: "RowLayout",
+ items: [
+ {minimumWidth: 1, preferredWidth: 10, maximumWidth: 20, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 4, maximumWidth: 10, fillWidth: true},
+ {minimumWidth: 1, preferredWidth: 50, maximumWidth: 99, fillWidth: true}
+ ]
+ },
+ layoutWidth: 66,
+ expectedWidths: [20, 10, 22],
+ expectedPositions: [0, 22, 44]
+ },
+ {
+ tag: "ver 66/3",
+ layout: {
+ type: "ColumnLayout",
+ items: [
+ {minimumHeight: 1, preferredHeight: 10, maximumHeight: 20, fillHeight: true},
+ {minimumHeight: 1, preferredHeight: 4, maximumHeight: 10, fillHeight: true},
+ {minimumHeight: 1, preferredHeight: 50, maximumHeight: 99, fillHeight: true}
+ ]
+ },
+ layoutHeight: 66,
+ expectedHeights: [20, 10, 22],
+ // If items are too small to fit the cell, they have a default alignment of
+ // Qt::AlignLeft | Qt::AlignVCenter
+ expectedPositions: [1, 22+6, 44]
+ }
+ ];
+ }
+
+ function test_uniformCellSizes(data)
+ {
+ let layout = LayoutHelpers.buildLayout(data.layout, testCase)
+ let isHorizontal = data.hasOwnProperty("expectedWidths")
+ layout.spacing = 0
+ layout.uniformCellSizes = true
+ waitForPolish(layout)
+ if (data.hasOwnProperty('layoutWidth')) {
+ layout.width = data.layoutWidth
+ }
+ if (data.hasOwnProperty('layoutHeight')) {
+ layout.height = data.layoutHeight
+ }
+
+ let expectedSizes = (isHorizontal ? data.expectedWidths : data.expectedHeights)
+ let actualSizes = []
+ let i = 0
+ for (i = 0; i < layout.children.length; i++) {
+ let item = layout.children[i]
+ actualSizes.push(isHorizontal ? item.width : item.height)
+ }
+ compare(actualSizes, expectedSizes)
+
+ if (data.hasOwnProperty('expectedPositions')) {
+ let actualPositions = []
+ for (i = 0; i < layout.children.length; i++) {
+ let item = layout.children[i]
+ actualPositions.push(isHorizontal ? item.x : item.y)
+ }
+ compare(actualPositions, data.expectedPositions)
+ }
+ }
+
+ Component {
+ id: uniformCellSizes_QML_Component
+ RowLayout {
+ spacing: 0
+ uniformCellSizes: true
+ Rectangle {
+ implicitWidth: 1
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ color: "red"
+ }
+ Rectangle {
+ implicitWidth: 2
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ color: "blue"
+ }
+ }
+ }
+
+ function test_uniformCellSizes_QML(data)
+ {
+ var layout = createTemporaryObject(uniformCellSizes_QML_Component, testCase)
+ layout.width = 40
+ layout.height = 20
+ let expectedWidths = [20, 20]
+ let actualWidths = [layout.children[0].width, layout.children[1].width]
+ compare(actualWidths, expectedWidths)
+ }
+
+
Component {
id: layout_alignToPixelGrid_Component
RowLayout {
@@ -1168,6 +1341,78 @@ Item {
}
Component {
+ id: sizeHintBindingLoopComp
+ Item {
+ id: root
+ anchors.fill: parent
+ property var customWidth: 100
+ RowLayout {
+ id: col
+ Item {
+ id: item
+ implicitHeight: 80
+ implicitWidth: Math.max(col2.implicitWidth, root.customWidth + 20)
+ ColumnLayout {
+ id: col2
+ width: parent.width
+ Item {
+ id: rect
+ implicitWidth: root.customWidth
+ implicitHeight: 80
+ }
+ }
+ }
+ }
+ }
+ }
+
+ function test_sizeHintBindingLoopIssue() {
+ var item = createTemporaryObject(sizeHintBindingLoopComp, container)
+ waitForRendering(item)
+ item.customWidth += 10
+ waitForRendering(item)
+ verify(!LayoutSetup.bindingLoopDetected, "Detected binding loop")
+ LayoutSetup.resetBindingLoopDetectedFlag()
+ }
+
+ Component {
+ id: polishLayoutItemComp
+ Item {
+ anchors.fill: parent
+ implicitHeight: contentLayout.implicitHeight
+ implicitWidth: contentLayout.implicitWidth
+ property alias textLayout: contentLayout
+ RowLayout {
+ width: parent.width
+ height: parent.height
+ ColumnLayout {
+ id: contentLayout
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
+ Layout.maximumWidth: 200
+ Repeater {
+ model: 2
+ Text {
+ Layout.fillWidth: true
+ text: "This is a long text causing line breaks to show the bug."
+ wrapMode: Text.Wrap
+ }
+ }
+ Item {
+ Layout.fillHeight: true
+ }
+ }
+ }
+ }
+ }
+
+ function test_polishLayoutItemIssue() {
+ var rootItem = createTemporaryObject(polishLayoutItemComp, container)
+ waitForRendering(rootItem)
+ var textItem = rootItem.textLayout.children[1]
+ verify(textItem.y >= rootItem.textLayout.children[0].height)
+ }
+
+ Component {
id: rearrangeNestedLayouts_Component
RowLayout {
id: layout
@@ -1268,6 +1513,44 @@ Item {
}
Component {
+ id: rearrangeInvalidatedChildInNestedLayout
+ ColumnLayout {
+ anchors.fill: parent
+ RowLayout {
+ spacing: 0
+ Text {
+ Layout.preferredWidth: 50
+ text: "Text Text Text"
+ wrapMode: Text.WordWrap
+ }
+ Rectangle {
+ color: "red";
+ Layout.preferredWidth: 50
+ Layout.preferredHeight: 20
+ }
+ Rectangle {
+ color: "green"
+ Layout.preferredHeight: 20
+ Layout.fillWidth: true
+ }
+ }
+ }
+ }
+
+ function test_rearrangeInvalidatedChildInNestedLayout() {
+ let layout = rearrangeInvalidatedChildInNestedLayout.createObject(container)
+ waitForRendering(layout)
+
+ let item1 = layout.children[0].children[0]
+ let item2 = layout.children[0].children[1]
+ let item3 = layout.children[0].children[2]
+
+ compare(item1.width, 50)
+ compare(item2.width, 50)
+ compare(item3.width, 100)
+ }
+
+ Component {
id: changeChildrenOfHiddenLayout_Component
RowLayout {
property int childCount: 1
@@ -1334,6 +1617,49 @@ Item {
compare(rootRect.item1.width, 100)
}
+ //---------------------------
+ // Layout with negative size
+ Component {
+ id: negativeSize_Component
+ Item {
+ id: rootItem
+ width: 0
+ height: 0
+ // default width x height: (0 x 0)
+ RowLayout {
+ spacing: 0
+ anchors.fill: parent
+ anchors.leftMargin: 1 // since parent size == (0 x 0), it causes layout size
+ anchors.bottomMargin: 1 // to become (-1, -1)
+ Item {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+ }
+ }
+ }
+
+ function test_negativeSize() {
+ let rootItem = createTemporaryObject(negativeSize_Component, container)
+ let rowLayout = rootItem.children[0]
+ let item = rowLayout.children[0]
+
+ const arr = [7, 1, 7, 0]
+ arr.forEach((n) => {
+ rootItem.width = n
+ rootItem.height = n
+
+ // n === 0 is special: It will cause the layout to have a
+ // negative size. In this case it will simply not rearrange its
+ // child (and leave it at its previous size, 6)
+ const expectedItemExtent = n === 0 ? 6 : n - 1
+
+ compare(item.width, expectedItemExtent)
+ compare(item.height, expectedItemExtent)
+ });
+ }
+
+
//---------------------------
Component {
id: rowlayoutWithTextItems_Component
@@ -1467,9 +1793,146 @@ Item {
compare(rootItem.maxWidth, 66)
// Should not trigger a binding loop
- verify(!BindingLoopDetector.bindingLoopDetected, "Detected binding loop")
- BindingLoopDetector.reset()
+ verify(!LayoutSetup.bindingLoopDetected, "Detected binding loop")
+ LayoutSetup.resetBindingLoopDetectedFlag()
}
- }
+
+ //---------------------------
+ // QTBUG-111792
+ Component {
+ id: rowlayoutCrashes_Component
+ RowLayout {
+ spacing: 5
+ Rectangle {
+ color: "red"
+ implicitWidth: 10
+ implicitHeight: 10
+ }
+ Rectangle {
+ color: "green"
+ implicitWidth: 10
+ implicitHeight: 10
+ }
+ }
+ }
+
+ function test_dontCrashAfterDestroyingChildren_data() {
+ return [
+ { tag: "setWidth", func: function (layout) { layout.width = 42 } },
+ { tag: "setHeight", func: function (layout) { layout.height = 42 } },
+ { tag: "getImplicitWidth", func: function (layout) { let x = layout.implicitWidth } },
+ { tag: "getImplicitHeight", func: function (layout) { let x = layout.implicitHeight } },
+ ]
+ }
+
+ function test_dontCrashAfterDestroyingChildren(data) {
+ var layout = createTemporaryObject(rowlayoutCrashes_Component, container)
+ waitForRendering(layout)
+ compare(layout.implicitWidth, 25)
+ layout.children[0].destroy() // deleteLater()
+ wait(0) // process the scheduled delete and actually invoke the dtor
+ data.func(layout) // call a function that might ultimately access the deleted item (but shouldn't)
+ }
+
+ //---------------------------
+ // Default layout size policy
+ Component {
+ id: defaultLayoutComp
+ Item {
+ id: rootItem
+ width: 110
+ height: 100
+ // Check default layout size policy
+ RowLayout {
+ spacing: 0
+ anchors.fill: parent
+ // Rectangle item - SizePolicy { Horizontal: Fixed; Vertical: Fixed }
+ Rectangle {}
+ // Button item - SizePolicy { Horizontal: Preferred; Vertical: Fixed }
+ Button {}
+ // Frame item - SizePolicy { Horizontal: Preferred; Vertical: Preferred }
+ Frame {}
+ }
+ }
+ }
+
+ function test_defaultLayoutSize() {
+ let rootItem = createTemporaryObject(defaultLayoutComp, container)
+ waitForRendering(rootItem)
+
+ let rowLayout = rootItem.children[0]
+
+ // Test default size policy disabled by default
+ compare(LayoutSetup.useDefaultSizePolicy, false)
+
+ let defaultButtonWidth = rowLayout.children[1].width
+ let defaultFrameWidth = rowLayout.children[2].width
+
+ // Enable attached properties for items and check its size
+ {
+ rowLayout.children[0].Layout.fillWidth = true
+ rowLayout.children[0].Layout.fillHeight = true
+ rowLayout.children[1].Layout.fillWidth = true
+ rowLayout.children[1].Layout.fillHeight = true
+ rowLayout.children[2].Layout.fillWidth = true
+ rowLayout.children[2].Layout.fillHeight = true
+ waitForRendering(rowLayout)
+ let isAbovePreferred = rowLayout.width >= rowLayout.implicitWidth
+ // Removing rectangle as width & implicitWidth be zero always, which makes validation of no use
+ for (let i = 1; i < rowLayout.children.length; i++) {
+ compare(rowLayout.children[i].width >= rowLayout.children[i].implicitWidth, isAbovePreferred)
+ compare(rowLayout.children[i].height, rowLayout.height)
+ }
+ }
+
+ // Destroy existing object
+ rootItem.destroy()
+
+ // Enable default size policy
+ LayoutSetup.useDefaultSizePolicy = true
+ compare(LayoutSetup.useDefaultSizePolicy, true)
+ rootItem = createTemporaryObject(defaultLayoutComp, container)
+ waitForRendering(rootItem)
+ rowLayout = rootItem.children[0]
+
+ // The default size policy would stretch button and frame accordingly
+ {
+ verify(Math.abs(rowLayout.width - (rowLayout.children[0].width + rowLayout.children[1].width + rowLayout.children[2].width)) <= 1)
+ compare(rowLayout.children[1].width < rowLayout.children[2].width, rowLayout.children[1].implicitWidth < rowLayout.children[2].implicitWidth)
+ compare(rowLayout.children[1].height, rowLayout.children[1].implicitHeight)
+ compare(rowLayout.children[2].height, rowLayout.height)
+ }
+
+ // Change the width and height of the root item to see layout size change
+ // Since default size policy for button and frame are Preferred, these items should
+ // stretch
+ {
+ let szDefaultButtonWidth = rowLayout.children[1].width
+ let szDefaultFrameWidth = rowLayout.children[2].width
+
+ rootItem.width = 210
+ rootItem.height = 200
+ waitForRendering(rootItem)
+ verify(rowLayout.children[1].width > szDefaultButtonWidth)
+ compare(rowLayout.children[1].height, rowLayout.children[1].implicitHeight)
+ verify(rowLayout.children[2].width > szDefaultFrameWidth)
+ compare(rowLayout.children[2].height, rowLayout.height)
+ }
+
+ // Disable size policies through attached properties and check item size
+ {
+ rowLayout.children[1].Layout.fillWidth = false
+ rowLayout.children[2].Layout.fillWidth = false
+ rowLayout.children[2].Layout.fillHeight = false
+ waitForRendering(rowLayout)
+ compare(rowLayout.children[1].width, defaultButtonWidth)
+ compare(rowLayout.children[2].width, defaultFrameWidth)
+ for (let index = 1; index < rowLayout.children.length; index++)
+ compare(rowLayout.children[index].height, rowLayout.children[index].implicitHeight)
+ }
+
+ rootItem.destroy()
+ }
+ }
}
diff --git a/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml b/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml
index e8d311183e..f627a90dfd 100644
--- a/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml
+++ b/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.15
import QtTest 1.15
@@ -724,6 +724,146 @@ Item {
compare(layout.num_onCountChanged, 1)
}
+ // QTBUG-111902
+ Component {
+ id: stackComponent
+ Loader {
+ id: loader
+ asynchronous: true
+ sourceComponent: StackLayout {
+ id: stackLayout
+ Repeater {
+ model: 3
+ Item {
+ required property int index
+ }
+ }
+ }
+ }
+ }
+
+ function test_loadStackLayoutAsynchronously() {
+ var loaderObj = stackComponent.createObject(container)
+ // Check for loader status to be ready
+ tryCompare(loaderObj, 'status', 1)
+ // Get stack layout object
+ var stackLayoutObj = loaderObj.item
+ // Check repeater index of child object
+ compare(stackLayoutObj.children[0].index, 0)
+ compare(stackLayoutObj.children[1].index, 1)
+ compare(stackLayoutObj.children[2].index, 2)
+ // Check stack layout attached property index
+ compare(stackLayoutObj.children[0].StackLayout.index, 0)
+ compare(stackLayoutObj.children[1].StackLayout.index, 1)
+ compare(stackLayoutObj.children[2].StackLayout.index, 2)
+ }
+
+ Component {
+ id: test_repeater_Component
+
+ Item {
+ property alias stackLayout : stackLayout
+ property var model : ListModel {
+ /*
+ * We cannot programmatically reorder siblings (QQuickItem::stackBefore()
+ * and QQuickItem::stackAfter() are not not available to QML, and we cannot
+ * alter the Item::children property to reorder siblings)
+ * Therefore, we have to go through the hoops with a ListModel and Repeater in
+ * order to trigger sibling reordering, just as reported in QTBUG-112691.
+ * Adding an item to a specific index (with model.insert()), will be done in
+ * two steps:
+ * 1. Append an Item to be the last of the siblings
+ * 2. Reorder that Rectangle to be at the correct child index that corresponds
+ * to the index given to model.insert()
+ *
+ * Adding an item to a specific index will therefore test sibling reordering
+ */
+ id: listModel
+ }
+ StackLayout {
+ id: stackLayout
+ anchors.fill: parent
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ Repeater {
+ id: repeater
+ model:listModel
+ delegate: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 100
+ objectName: model.color
+ color: model.color
+ }
+ }
+ }
+ }
+ }
+
+ function test_repeater() {
+ let item = createTemporaryObject(test_repeater_Component, container)
+ let layout = item.stackLayout
+ let model = item.model
+ function verifyVisibilityOfItems() {
+ for (let i = 0; i < layout.count; ++i) {
+ compare(layout.children[i].visible, layout.currentIndex === i)
+ }
+ }
+
+ compare(layout.currentIndex, -1)
+ compare(layout.count, 0)
+ model.append({ "color": "red" })
+ compare(layout.currentIndex, 0)
+ compare(layout.count, 1)
+ verifyVisibilityOfItems()
+
+ model.append({ "color": "green" })
+ compare(layout.currentIndex, 0)
+ compare(layout.count, 2)
+ verifyVisibilityOfItems()
+
+ model.append({ "color": "blue" })
+ compare(layout.currentIndex, 0)
+ compare(layout.count, 3)
+ verifyVisibilityOfItems()
+
+ model.insert(0, { "color": "black" })
+ compare(layout.currentIndex, 1)
+ compare(layout.count, 4)
+ verifyVisibilityOfItems()
+
+ // An implicit currentIndex will reset back to -1 if
+ // the StackLayout is empty
+ model.clear()
+ compare(layout.currentIndex, -1)
+ compare(layout.count, 0)
+
+ // set explicit index to out of bounds
+ layout.currentIndex = 1
+ compare(layout.currentIndex, 1)
+ compare(layout.count, 0)
+ verifyVisibilityOfItems()
+
+ model.append({ "color": "red" })
+ compare(layout.currentIndex, 1)
+ compare(layout.count, 1)
+ verifyVisibilityOfItems()
+
+ model.append({ "color": "green" })
+ compare(layout.currentIndex, 1)
+ compare(layout.count, 2)
+ verifyVisibilityOfItems()
+
+ model.insert(1, { "color": "brown" })
+ compare(layout.currentIndex, 2)
+ compare(layout.count, 3)
+ verifyVisibilityOfItems()
+
+ // remove red, currentIndex should decrease
+ model.remove(0, 1)
+ compare(layout.currentIndex, 1)
+ compare(layout.count, 2)
+ verifyVisibilityOfItems()
+ }
}
}
diff --git a/tests/auto/quick/qquicklayouts/tst_qquicklayouts.cpp b/tests/auto/quick/qquicklayouts/tst_qquicklayouts.cpp
index 26b01b806d..98b5e96486 100644
--- a/tests/auto/quick/qquicklayouts/tst_qquicklayouts.cpp
+++ b/tests/auto/quick/qquicklayouts/tst_qquicklayouts.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcontext.h>
#include <QtQuickTest/quicktest.h>
@@ -8,20 +8,23 @@ class Setup : public QObject
{
Q_OBJECT
Q_PROPERTY(bool bindingLoopDetected READ wasBindingLoopDetected FINAL)
+ Q_PROPERTY(bool useDefaultSizePolicy READ useDefaultSizePolicy WRITE setUseDefaultSizePolicy FINAL)
public:
Setup() {}
bool wasBindingLoopDetected() const { return mBindingLoopDetected; }
+ bool useDefaultSizePolicy() const { return QCoreApplication::testAttribute(Qt::AA_QtQuickUseDefaultSizePolicy); }
+ void setUseDefaultSizePolicy(bool policy) { QCoreApplication::setAttribute(Qt::AA_QtQuickUseDefaultSizePolicy, policy); }
+
public slots:
- void reset() { mBindingLoopDetected = false; }
+ void resetBindingLoopDetectedFlag() { mBindingLoopDetected = false; }
void qmlEngineAvailable(QQmlEngine *engine)
{
connect(engine, &QQmlEngine::warnings, this, &Setup::qmlWarnings);
-
- qmlRegisterSingletonInstance("org.qtproject.Test", 1, 0, "BindingLoopDetector", this);
+ qmlRegisterSingletonInstance("org.qtproject.Test", 1, 0, "LayoutSetup", this);
}
void qmlWarnings(const QList<QQmlError> &warnings)
diff --git a/tests/auto/quick/qquicklistview/BLACKLIST b/tests/auto/quick/qquicklistview/BLACKLIST
index e4da77acba..0871e4e5c4 100644
--- a/tests/auto/quick/qquicklistview/BLACKLIST
+++ b/tests/auto/quick/qquicklistview/BLACKLIST
@@ -13,3 +13,7 @@ macos ci
android
[contentHeightWithDelayRemove]
android
+
+# QTBUG-123894
+[multipleTransitions]
+macos
diff --git a/tests/auto/quick/qquicklistview/CMakeLists.txt b/tests/auto/quick/qquicklistview/CMakeLists.txt
index 87171ec3ea..cee287ae41 100644
--- a/tests/auto/quick/qquicklistview/CMakeLists.txt
+++ b/tests/auto/quick/qquicklistview/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicklistview Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicklistview LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquicklistview/data/addoncompleted.qml b/tests/auto/quick/qquicklistview/data/addoncompleted.qml
index 0ee94fa0b9..34ee459aa4 100644
--- a/tests/auto/quick/qquicklistview/data/addoncompleted.qml
+++ b/tests/auto/quick/qquicklistview/data/addoncompleted.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.9
diff --git a/tests/auto/quick/qquicklistview/data/attachedProperties.qml b/tests/auto/quick/qquicklistview/data/attachedProperties.qml
index bfcd8fc5eb..72fdc009e0 100644
--- a/tests/auto/quick/qquicklistview/data/attachedProperties.qml
+++ b/tests/auto/quick/qquicklistview/data/attachedProperties.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquicklistview/data/displayMargin.qml b/tests/auto/quick/qquicklistview/data/displayMargin.qml
index 20ba124a97..64b668326f 100644
--- a/tests/auto/quick/qquicklistview/data/displayMargin.qml
+++ b/tests/auto/quick/qquicklistview/data/displayMargin.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.3
diff --git a/tests/auto/quick/qquicklistview/data/flickBothDirections.qml b/tests/auto/quick/qquicklistview/data/flickBothDirections.qml
index 6efd0d5a61..a9905adba5 100644
--- a/tests/auto/quick/qquicklistview/data/flickBothDirections.qml
+++ b/tests/auto/quick/qquicklistview/data/flickBothDirections.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.9
Rectangle {
diff --git a/tests/auto/quick/qquicklistview/data/moveObjectModelItemToAnotherObjectModel.qml b/tests/auto/quick/qquicklistview/data/moveObjectModelItemToAnotherObjectModel.qml
index 6d7b1c4e21..6f5160f13d 100644
--- a/tests/auto/quick/qquicklistview/data/moveObjectModelItemToAnotherObjectModel.qml
+++ b/tests/auto/quick/qquicklistview/data/moveObjectModelItemToAnotherObjectModel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.14
import QtQml.Models 2.14
diff --git a/tests/auto/quick/qquicklistview/data/negativeDisplayMargin.qml b/tests/auto/quick/qquicklistview/data/negativeDisplayMargin.qml
index 87ae08478b..d34069d721 100644
--- a/tests/auto/quick/qquicklistview/data/negativeDisplayMargin.qml
+++ b/tests/auto/quick/qquicklistview/data/negativeDisplayMargin.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.3
diff --git a/tests/auto/quick/qquicklistview/data/objectModelCulling.qml b/tests/auto/quick/qquicklistview/data/objectModelCulling.qml
index c0a70ec485..9ca79ec8e4 100644
--- a/tests/auto/quick/qquicklistview/data/objectModelCulling.qml
+++ b/tests/auto/quick/qquicklistview/data/objectModelCulling.qml
@@ -3,6 +3,7 @@ import QtQuick 2.12
import QtQml.Models 2.12
Item {
+ anchors.fill: parent
ObjectModel {
id: model1
diff --git a/tests/auto/quick/qquicklistview/data/outsideViewportChangeNotAffectingView.qml b/tests/auto/quick/qquicklistview/data/outsideViewportChangeNotAffectingView.qml
index 772b79b500..2215252aef 100644
--- a/tests/auto/quick/qquicklistview/data/outsideViewportChangeNotAffectingView.qml
+++ b/tests/auto/quick/qquicklistview/data/outsideViewportChangeNotAffectingView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.1
import QtTest 1.1
diff --git a/tests/auto/quick/qquicklistview/data/proxytest.qml b/tests/auto/quick/qquicklistview/data/proxytest.qml
index 2d733d81e4..dad5dbad8a 100644
--- a/tests/auto/quick/qquicklistview/data/proxytest.qml
+++ b/tests/auto/quick/qquicklistview/data/proxytest.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.1
import Proxy 1.0
diff --git a/tests/auto/quick/qquicklistview/data/qtbug34576.qml b/tests/auto/quick/qquicklistview/data/qtbug34576.qml
index e1b96f5d5f..fdc94c0c0b 100644
--- a/tests/auto/quick/qquicklistview/data/qtbug34576.qml
+++ b/tests/auto/quick/qquicklistview/data/qtbug34576.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.7
diff --git a/tests/auto/quick/qquicklistview/data/qtbug61537_modelChangesAsync.qml b/tests/auto/quick/qquicklistview/data/qtbug61537_modelChangesAsync.qml
index a526d8669a..c385a9b4b8 100644
--- a/tests/auto/quick/qquicklistview/data/qtbug61537_modelChangesAsync.qml
+++ b/tests/auto/quick/qquicklistview/data/qtbug61537_modelChangesAsync.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
Item {
diff --git a/tests/auto/quick/qquicklistview/data/repositionListViewOnPopulateTransition.qml b/tests/auto/quick/qquicklistview/data/repositionListViewOnPopulateTransition.qml
new file mode 100644
index 0000000000..7a313f7f87
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/repositionListViewOnPopulateTransition.qml
@@ -0,0 +1,51 @@
+import QtQuick
+import QtQuick.Controls.Basic
+
+ListView {
+ id: listView
+
+ width: 100
+ height: 100
+
+ verticalLayoutDirection: ListView.BottomToTop
+ interactive: true
+ reuseItems: false
+
+ model: ListModel {
+ ListElement {index: 0; text: "Item0"}
+ }
+
+ delegate: Button {
+ id: button
+
+ required text
+
+ property alias yScale: scaleTransform.yScale
+ property bool inverted: ListView.view.verticalLayoutDirection === ListView.BottomToTop
+
+ transform: Scale {
+ id: scaleTransform
+ origin.y: button.inverted ? button.implicitHeight : 0
+ }
+ }
+
+ populate: Transition {
+ id: populateTransition
+
+ NumberAnimation {
+ // in this case we do want to animate y to achieve a smooth
+ // transition from y=0 to its assigned y location
+ property: "y"
+ duration: 500
+ easing.type: Easing.InOutQuad
+ }
+ NumberAnimation {
+ property: "yScale"
+ from: 0
+ to: 1
+ duration: 500
+ easing.type: Easing.InOutQuad
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qquicklistview/data/resizeAfterComponentComplete.qml b/tests/auto/quick/qquicklistview/data/resizeAfterComponentComplete.qml
index c169d92826..fdeca4454a 100644
--- a/tests/auto/quick/qquicklistview/data/resizeAfterComponentComplete.qml
+++ b/tests/auto/quick/qquicklistview/data/resizeAfterComponentComplete.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/qquicklistview/data/reusedelegateitems.qml b/tests/auto/quick/qquicklistview/data/reusedelegateitems.qml
index e5e64dcbc6..c54d10f88c 100644
--- a/tests/auto/quick/qquicklistview/data/reusedelegateitems.qml
+++ b/tests/auto/quick/qquicklistview/data/reusedelegateitems.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.15
Rectangle {
diff --git a/tests/auto/quick/qquicklistview/data/roundingErrors.qml b/tests/auto/quick/qquicklistview/data/roundingErrors.qml
index 2c1a1e665d..f850b3573a 100644
--- a/tests/auto/quick/qquicklistview/data/roundingErrors.qml
+++ b/tests/auto/quick/qquicklistview/data/roundingErrors.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQml.Models 2.1
diff --git a/tests/auto/quick/qquicklistview/data/setpositiononlayout.qml b/tests/auto/quick/qquicklistview/data/setpositiononlayout.qml
index 4e43efa33b..a605b2103d 100644
--- a/tests/auto/quick/qquicklistview/data/setpositiononlayout.qml
+++ b/tests/auto/quick/qquicklistview/data/setpositiononlayout.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquicklistview/data/sizeTransitions.qml b/tests/auto/quick/qquicklistview/data/sizeTransitions.qml
index da0c8226fb..d1bddb2047 100644
--- a/tests/auto/quick/qquicklistview/data/sizeTransitions.qml
+++ b/tests/auto/quick/qquicklistview/data/sizeTransitions.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import QtQuick.Window 2.1
diff --git a/tests/auto/quick/qquicklistview/data/snapOneItemResize.qml b/tests/auto/quick/qquicklistview/data/snapOneItemResize.qml
index 7ecc833a64..4603cd9f34 100644
--- a/tests/auto/quick/qquicklistview/data/snapOneItemResize.qml
+++ b/tests/auto/quick/qquicklistview/data/snapOneItemResize.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
ListView {
id: list
+ anchors.fill: parent
currentIndex: 5
snapMode: ListView.SnapOneItem
orientation: ListView.Horizontal
diff --git a/tests/auto/quick/qquicklistview/data/stickyPositioning-both.qml b/tests/auto/quick/qquicklistview/data/stickyPositioning-both.qml
index c28070f183..ece0e2527b 100644
--- a/tests/auto/quick/qquicklistview/data/stickyPositioning-both.qml
+++ b/tests/auto/quick/qquicklistview/data/stickyPositioning-both.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
Rectangle {
diff --git a/tests/auto/quick/qquicklistview/data/stickyPositioning-footer.qml b/tests/auto/quick/qquicklistview/data/stickyPositioning-footer.qml
index 1b398138c8..568762b445 100644
--- a/tests/auto/quick/qquicklistview/data/stickyPositioning-footer.qml
+++ b/tests/auto/quick/qquicklistview/data/stickyPositioning-footer.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
Rectangle {
diff --git a/tests/auto/quick/qquicklistview/data/stickyPositioning-header.qml b/tests/auto/quick/qquicklistview/data/stickyPositioning-header.qml
index c0f2a5b2fb..6b5889a808 100644
--- a/tests/auto/quick/qquicklistview/data/stickyPositioning-header.qml
+++ b/tests/auto/quick/qquicklistview/data/stickyPositioning-header.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
Rectangle {
diff --git a/tests/auto/quick/qquicklistview/data/usechooserwithoutdefault.qml b/tests/auto/quick/qquicklistview/data/usechooserwithoutdefault.qml
index 7c555ea264..cba0ad5720 100644
--- a/tests/auto/quick/qquicklistview/data/usechooserwithoutdefault.qml
+++ b/tests/auto/quick/qquicklistview/data/usechooserwithoutdefault.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicklistview/incrementalmodel.cpp b/tests/auto/quick/qquicklistview/incrementalmodel.cpp
index 1670fcd1cf..f2c6219711 100644
--- a/tests/auto/quick/qquicklistview/incrementalmodel.cpp
+++ b/tests/auto/quick/qquicklistview/incrementalmodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "incrementalmodel.h"
#include <QGuiApplication>
diff --git a/tests/auto/quick/qquicklistview/incrementalmodel.h b/tests/auto/quick/qquicklistview/incrementalmodel.h
index 1cbd483551..f61d38a3d1 100644
--- a/tests/auto/quick/qquicklistview/incrementalmodel.h
+++ b/tests/auto/quick/qquicklistview/incrementalmodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef IncrementalModel_H
#define IncrementalModel_H
diff --git a/tests/auto/quick/qquicklistview/proxytestinnermodel.cpp b/tests/auto/quick/qquicklistview/proxytestinnermodel.cpp
index d00b417429..e142a8a58b 100644
--- a/tests/auto/quick/qquicklistview/proxytestinnermodel.cpp
+++ b/tests/auto/quick/qquicklistview/proxytestinnermodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "proxytestinnermodel.h"
diff --git a/tests/auto/quick/qquicklistview/proxytestinnermodel.h b/tests/auto/quick/qquicklistview/proxytestinnermodel.h
index 3177ec51b3..5ea78ae864 100644
--- a/tests/auto/quick/qquicklistview/proxytestinnermodel.h
+++ b/tests/auto/quick/qquicklistview/proxytestinnermodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef INNERMODEL_H
#define INNERMODEL_H
diff --git a/tests/auto/quick/qquicklistview/randomsortmodel.cpp b/tests/auto/quick/qquicklistview/randomsortmodel.cpp
index 3e0c45bb1a..0e5f562e4b 100644
--- a/tests/auto/quick/qquicklistview/randomsortmodel.cpp
+++ b/tests/auto/quick/qquicklistview/randomsortmodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "randomsortmodel.h"
#include <QRandomGenerator>
diff --git a/tests/auto/quick/qquicklistview/randomsortmodel.h b/tests/auto/quick/qquicklistview/randomsortmodel.h
index 9fae9b2b76..9d53a8cff3 100644
--- a/tests/auto/quick/qquicklistview/randomsortmodel.h
+++ b/tests/auto/quick/qquicklistview/randomsortmodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef RANDOMSORTMODEL_H
#define RANDOMSORTMODEL_H
diff --git a/tests/auto/quick/qquicklistview/reusemodel.h b/tests/auto/quick/qquicklistview/reusemodel.h
index 4f0ab817b2..0a23a2bda4 100644
--- a/tests/auto/quick/qquicklistview/reusemodel.h
+++ b/tests/auto/quick/qquicklistview/reusemodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef REUSEMODEL_H
#define REUSEMODEL_H
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index 8a3a23826d..3def877f00 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtCore/QStringListModel>
@@ -187,6 +187,7 @@ private slots:
void populateTransitions();
void populateTransitions_data();
+ void repositionFirstItemOnPopulateTransition();
void sizeTransitions();
void sizeTransitions_data();
@@ -1172,7 +1173,7 @@ void tst_QQuickListView::removed_more(const QUrl &source, QQuickItemView::Vertic
int firstVisibleIndex = -1;
for (int i=0; i<items.size(); i++) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (item && delegateVisible(item)) {
+ if (item && isDelegateVisible(item)) {
firstVisibleIndex = i;
break;
}
@@ -1404,7 +1405,7 @@ void tst_QQuickListView::moved(const QUrl &source, QQuickItemView::VerticalLayou
int firstVisibleIndex = -1;
for (int i=0; i<items.size(); i++) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (item && delegateVisible(item)) {
+ if (item && isDelegateVisible(item)) {
firstVisibleIndex = i;
break;
}
@@ -2739,7 +2740,7 @@ void tst_QQuickListView::sectionsSnap()
QTRY_VERIFY(listview != nullptr);
listview->setSnapMode(snapMode);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(!QQuickItemPrivate::get(listview)->polishScheduled);
QTRY_COMPARE(listview->currentIndex(), 0);
QCOMPARE(listview->contentY(), qreal(-50));
@@ -2897,9 +2898,9 @@ void tst_QQuickListView::currentIndex()
// moving currentItem out of view should make it invisible
listview->setCurrentIndex(0);
- QTRY_VERIFY(delegateVisible(listview->currentItem()));
+ QTRY_VERIFY(isDelegateVisible(listview->currentItem()));
listview->setContentY(200);
- QTRY_VERIFY(!delegateVisible(listview->currentItem()));
+ QTRY_VERIFY(!isDelegateVisible(listview->currentItem()));
// empty model should reset currentIndex to -1
QaimModel emptyModel;
@@ -3131,37 +3132,37 @@ void tst_QQuickListView::itemListFlicker()
QQuickItem *item = findItem<QQuickItem>(contentItem, "item1");
QVERIFY(item);
- QVERIFY(delegateVisible(item));
+ QVERIFY(isDelegateVisible(item));
item = findItem<QQuickItem>(contentItem, "item2");
QVERIFY(item);
- QVERIFY(delegateVisible(item));
+ QVERIFY(isDelegateVisible(item));
item = findItem<QQuickItem>(contentItem, "item3");
QVERIFY(item);
- QVERIFY(delegateVisible(item));
+ QVERIFY(isDelegateVisible(item));
listview->setCurrentIndex(1);
item = findItem<QQuickItem>(contentItem, "item1");
QVERIFY(item);
- QVERIFY(delegateVisible(item));
+ QVERIFY(isDelegateVisible(item));
item = findItem<QQuickItem>(contentItem, "item2");
QVERIFY(item);
- QVERIFY(delegateVisible(item));
+ QVERIFY(isDelegateVisible(item));
item = findItem<QQuickItem>(contentItem, "item3");
QVERIFY(item);
- QVERIFY(delegateVisible(item));
+ QVERIFY(isDelegateVisible(item));
listview->setCurrentIndex(2);
item = findItem<QQuickItem>(contentItem, "item1");
QVERIFY(item);
- QVERIFY(delegateVisible(item));
+ QVERIFY(isDelegateVisible(item));
item = findItem<QQuickItem>(contentItem, "item2");
QVERIFY(item);
- QVERIFY(delegateVisible(item));
+ QVERIFY(isDelegateVisible(item));
item = findItem<QQuickItem>(contentItem, "item3");
QVERIFY(item);
- QVERIFY(delegateVisible(item));
+ QVERIFY(isDelegateVisible(item));
}
void tst_QQuickListView::cacheBuffer()
@@ -4406,7 +4407,7 @@ void tst_QQuickListView::resizeView()
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
QTRY_COMPARE(item->y(), i*20.);
- QCOMPARE(delegateVisible(item), i < 11); // inside view visible, outside not visible
+ QCOMPARE(isDelegateVisible(item), i < 11); // inside view visible, outside not visible
}
// ensure items outside view become invisible
@@ -4419,7 +4420,7 @@ void tst_QQuickListView::resizeView()
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
QTRY_COMPARE(item->y(), i*20.);
- QCOMPARE(delegateVisible(item), i < 6); // inside view visible, outside not visible
+ QCOMPARE(isDelegateVisible(item), i < 6); // inside view visible, outside not visible
}
}
@@ -5058,14 +5059,14 @@ void tst_QQuickListView::test_mirroring()
QCOMPARE(listviewA->layoutDirection(), listviewA->effectiveLayoutDirection());
// LTR != RTL
- foreach (const QString objectName, objectNames)
+ for (const QString &objectName : std::as_const(objectNames))
QVERIFY(findItem<QQuickItem>(listviewA, objectName)->x() != findItem<QQuickItem>(listviewB, objectName)->x());
listviewA->setProperty("layoutDirection", Qt::LeftToRight);
listviewB->setProperty("layoutDirection", Qt::LeftToRight);
// LTR == LTR
- foreach (const QString objectName, objectNames)
+ for (const QString &objectName : std::as_const(objectNames))
QCOMPARE(findItem<QQuickItem>(listviewA, objectName)->x(), findItem<QQuickItem>(listviewB, objectName)->x());
QCOMPARE(listviewB->layoutDirection(), listviewB->effectiveLayoutDirection());
@@ -5073,25 +5074,25 @@ void tst_QQuickListView::test_mirroring()
QVERIFY(listviewB->layoutDirection() != listviewB->effectiveLayoutDirection());
// LTR != LTR+mirror
- foreach (const QString objectName, objectNames)
+ for (const QString &objectName : std::as_const(objectNames))
QVERIFY(findItem<QQuickItem>(listviewA, objectName)->x() != findItem<QQuickItem>(listviewB, objectName)->x());
listviewA->setProperty("layoutDirection", Qt::RightToLeft);
// RTL == LTR+mirror
- foreach (const QString objectName, objectNames)
+ for (const QString &objectName : std::as_const(objectNames))
QCOMPARE(findItem<QQuickItem>(listviewA, objectName)->x(), findItem<QQuickItem>(listviewB, objectName)->x());
listviewB->setProperty("layoutDirection", Qt::RightToLeft);
// RTL != RTL+mirror
- foreach (const QString objectName, objectNames)
+ for (const QString &objectName : std::as_const(objectNames))
QVERIFY(findItem<QQuickItem>(listviewA, objectName)->x() != findItem<QQuickItem>(listviewB, objectName)->x());
listviewA->setProperty("layoutDirection", Qt::LeftToRight);
// LTR == RTL+mirror
- foreach (const QString objectName, objectNames)
+ for (const QString &objectName : std::as_const(objectNames))
QCOMPARE(findItem<QQuickItem>(listviewA, objectName)->x(), findItem<QQuickItem>(listviewB, objectName)->x());
}
@@ -6495,30 +6496,30 @@ void tst_QQuickListView::unrequestedVisibility()
const QString wrapperObjectName = QStringLiteral("wrapper");
QQuickItem *item = findItem<QQuickItem>(leftContent, wrapperObjectName, 1);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 1);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 19);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 19);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 16);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 17);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 3);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 4);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
rightview->setCurrentIndex(0);
@@ -6527,10 +6528,10 @@ void tst_QQuickListView::unrequestedVisibility()
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 1);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 1);
QVERIFY(item);
- QTRY_COMPARE(delegateVisible(item), true);
+ QTRY_COMPARE(isDelegateVisible(item), true);
QVERIFY(!findItem<QQuickItem>(leftContent, wrapperObjectName, 19));
QVERIFY(!findItem<QQuickItem>(rightContent, wrapperObjectName, 19));
@@ -6542,123 +6543,123 @@ void tst_QQuickListView::unrequestedVisibility()
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 1);
QVERIFY(item);
- QTRY_COMPARE(delegateVisible(item), false);
+ QTRY_COMPARE(isDelegateVisible(item), false);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 1);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 19);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 19);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 3);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 4);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 16);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 17);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
model.moveItems(19, 1, 1);
QVERIFY(QQuickTest::qWaitForPolish(leftview));
QTRY_VERIFY((item = findItem<QQuickItem>(leftContent, wrapperObjectName, 1)));
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 1);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 19);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 19);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 4);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 5);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 16);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 17);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
model.moveItems(3, 4, 1);
QVERIFY(QQuickTest::qWaitForPolish(leftview));
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 4);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 5);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 16);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 17);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
model.moveItems(4, 3, 1);
QVERIFY(QQuickTest::qWaitForPolish(leftview));
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 4);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 5);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 16);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 17);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
model.moveItems(16, 17, 1);
QVERIFY(QQuickTest::qWaitForPolish(leftview));
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 4);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 5);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 16);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 17);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
model.moveItems(17, 16, 1);
QVERIFY(QQuickTest::qWaitForPolish(leftview));
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 4);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 5);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 16);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 17);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
}
void tst_QQuickListView::populateTransitions()
@@ -6792,6 +6793,20 @@ void tst_QQuickListView::populateTransitions_data()
QTest::newRow("empty to start with, no populate") << false << false << false;
}
+// QTBUG-111050
+/* Reposition first visible item in list view on populate transition
+ Note: Occurs only in BottomToTop or RightToLeft layout */
+void tst_QQuickListView::repositionFirstItemOnPopulateTransition()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("repositionListViewOnPopulateTransition.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
+ QTRY_VERIFY(listview != nullptr);
+ QTRY_COMPARE(listview->contentY(), -100.0);
+}
/*
* Tests if the first visible item is not repositioned if the same item
@@ -7871,7 +7886,8 @@ void tst_QQuickListView::multipleDisplaced()
QTRY_VERIFY(listview->property("displaceTransitionsDone").toBool());
QVariantMap transitionsStarted = listview->property("displaceTransitionsStarted").toMap();
- foreach (const QString &name, transitionsStarted.keys()) {
+ const QStringList keys = transitionsStarted.keys();
+ for (const QString &name : keys) {
QVERIFY2(transitionsStarted[name] == 1,
qPrintable(QString("%1 was displaced %2 times").arg(name).arg(transitionsStarted[name].toInt())));
}
@@ -7963,7 +7979,7 @@ void tst_QQuickListView::flickBeyondBounds()
// Flick view up beyond bounds
flick(window.data(), QPoint(10, 10), QPoint(10, -2000), 180);
-#ifdef Q_OS_MAC
+#ifdef Q_OS_MACOS
QSKIP("Disabled due to flaky behavior on CI system (QTBUG-44493)");
QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper").count(), 0);
#endif
@@ -8241,24 +8257,24 @@ void tst_QQuickListView::displayMargin()
QQuickItem *item0 = findItem<QQuickItem>(content, "delegate", 0);
QVERIFY(item0);
- QCOMPARE(delegateVisible(item0), true);
+ QCOMPARE(isDelegateVisible(item0), true);
// the 14th item should be within the end margin
QQuickItem *item14 = findItem<QQuickItem>(content, "delegate", 13);
QVERIFY(item14);
- QCOMPARE(delegateVisible(item14), true);
+ QCOMPARE(isDelegateVisible(item14), true);
// the 15th item should be outside the end margin
QVERIFY(findItem<QQuickItem>(content, "delegate", 14) == nullptr);
// the first delegate should still be within the begin margin
listview->positionViewAtIndex(3, QQuickListView::Beginning);
- QCOMPARE(delegateVisible(item0), true);
+ QCOMPARE(isDelegateVisible(item0), true);
// the first delegate should now be outside the begin margin
listview->positionViewAtIndex(4, QQuickListView::Beginning);
- QCOMPARE(delegateVisible(item0), false);
+ QCOMPARE(isDelegateVisible(item0), false);
}
void tst_QQuickListView::negativeDisplayMargin()
@@ -8280,29 +8296,29 @@ void tst_QQuickListView::negativeDisplayMargin()
QQuickItem *item = findItem<QQuickItem>(content, "delegate", 0);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(content, "delegate", 7);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), true);
+ QCOMPARE(isDelegateVisible(item), true);
item = findItem<QQuickItem>(content, "delegate", 8);
QVERIFY(item);
- QCOMPARE(delegateVisible(item), false);
+ QCOMPARE(isDelegateVisible(item), false);
// Flick until contentY means that delegate8 should be visible
listview->setProperty("contentY", 500);
item = findItem<QQuickItem>(content, "delegate", 8);
QVERIFY(item);
- QTRY_COMPARE(delegateVisible(item), true);
+ QTRY_COMPARE(isDelegateVisible(item), true);
listview->setProperty("contentY", 1000);
QTRY_VERIFY((item = findItem<QQuickItem>(content, "delegate", 14)));
- QTRY_COMPARE(delegateVisible(item), true);
+ QTRY_COMPARE(isDelegateVisible(item), true);
listview->setProperty("contentY", 0);
QTRY_VERIFY(item = findItem<QQuickItem>(content, "delegate", 4));
- QTRY_COMPARE(delegateVisible(item), true);
+ QTRY_COMPARE(isDelegateVisible(item), true);
}
void tst_QQuickListView::highlightItemGeometryChanges()
@@ -8404,7 +8420,7 @@ void tst_QQuickListView::stickyPositioning()
listview->positionViewAtIndex(positionIndex, positionMode);
- foreach (const QPointF &offset, movement) {
+ for (const QPointF &offset : std::as_const(movement)) {
listview->setContentX(listview->contentX() + offset.x());
listview->setContentY(listview->contentY() + offset.y());
}
diff --git a/tests/auto/quick/qquicklistview2/CMakeLists.txt b/tests/auto/quick/qquicklistview2/CMakeLists.txt
index 6af00b60e8..faa86ce733 100644
--- a/tests/auto/quick/qquicklistview2/CMakeLists.txt
+++ b/tests/auto/quick/qquicklistview2/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicklistview2 LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -23,9 +29,10 @@ qt_internal_add_test(tst_qquicklistview2
TESTDATA ${test_data}
)
+qt_policy(SET QTP0001 NEW)
+
qt6_add_qml_module(tst_qquicklistview2
URI Test
- AUTO_RESOURCE_PREFIX
)
qt_internal_extend_target(tst_qquicklistview2 CONDITION ANDROID OR IOS
diff --git a/tests/auto/quick/qquicklistview2/data/areaZeroView.qml b/tests/auto/quick/qquicklistview2/data/areaZeroView.qml
new file mode 100644
index 0000000000..e0329f4e83
--- /dev/null
+++ b/tests/auto/quick/qquicklistview2/data/areaZeroView.qml
@@ -0,0 +1,22 @@
+import QtQuick
+
+Window {
+ width: 600
+ height: 600
+ visible: true
+ property int delegateCreationCounter: 0
+
+ ListView {
+ id: lv
+ anchors.fill: parent
+ model: 6000
+
+ delegate: Rectangle {
+ width: ListView.view.width
+ height: ListView.view.width / 6
+ color: "white"
+ border.width: 1
+ Component.onCompleted: ++delegateCreationCounter
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview2/data/bindOnHeaderAndFooterXPosition.qml b/tests/auto/quick/qquicklistview2/data/bindOnHeaderAndFooterXPosition.qml
new file mode 100644
index 0000000000..69431fb525
--- /dev/null
+++ b/tests/auto/quick/qquicklistview2/data/bindOnHeaderAndFooterXPosition.qml
@@ -0,0 +1,29 @@
+import QtQuick
+
+ListView {
+ width: 200
+ height: 300
+ spacing: 20
+ orientation: ListView.Vertical
+
+ header: Rectangle {
+ x: (ListView.view.width - width) / 2
+ color: 'tomato'
+ width: 50
+ height: 50
+ }
+
+ footer: Rectangle {
+ x: (ListView.view.width - width) / 2
+ color: 'lime'
+ width: 50
+ height: 50
+ }
+
+ model: 3
+ delegate: Text {
+ text: 'Foobar'
+ horizontalAlignment: Text.AlignHCenter
+ width: ListView.view.width
+ }
+}
diff --git a/tests/auto/quick/qquicklistview2/data/bindOnHeaderAndFooterYPosition.qml b/tests/auto/quick/qquicklistview2/data/bindOnHeaderAndFooterYPosition.qml
new file mode 100644
index 0000000000..a484a154a7
--- /dev/null
+++ b/tests/auto/quick/qquicklistview2/data/bindOnHeaderAndFooterYPosition.qml
@@ -0,0 +1,29 @@
+import QtQuick
+
+ListView {
+ width: 300
+ height: 200
+ spacing: 20
+ orientation: ListView.Horizontal
+
+ header: Rectangle {
+ y: (ListView.view.height - height) / 2
+ color: 'tomato'
+ width: 50
+ height: 50
+ }
+
+ footer: Rectangle {
+ y: (ListView.view.height - height) / 2
+ color: 'lime'
+ width: 50
+ height: 50
+ }
+
+ model: 3
+ delegate: Text {
+ text: 'Foobar'
+ verticalAlignment: Text.AlignVCenter
+ height: ListView.view.height
+ }
+}
diff --git a/tests/auto/quick/qquicklistview2/data/boundDelegateComponent.qml b/tests/auto/quick/qquicklistview2/data/boundDelegateComponent.qml
index 6fb84279b0..5e4de1a08d 100644
--- a/tests/auto/quick/qquicklistview2/data/boundDelegateComponent.qml
+++ b/tests/auto/quick/qquicklistview2/data/boundDelegateComponent.qml
@@ -6,6 +6,8 @@ Item {
objectName: "outer"
ListView {
id: listView
+ width: 100
+ height: 100
model: 1
property string foo: "foo"
delegate: Text {
@@ -16,6 +18,8 @@ Item {
ListView {
id: listView2
+ width: 100
+ height: 100
model: 1
delegate: Text {
required property int index
@@ -49,6 +53,8 @@ Item {
}
ListView {
+ width: 100
+ height: 100
id: innerListView
model: listModel
delegate: innerComponent
diff --git a/tests/auto/quick/qquicklistview2/data/changingOrientationWithListModel.qml b/tests/auto/quick/qquicklistview2/data/changingOrientationWithListModel.qml
new file mode 100644
index 0000000000..366b20b029
--- /dev/null
+++ b/tests/auto/quick/qquicklistview2/data/changingOrientationWithListModel.qml
@@ -0,0 +1,47 @@
+import QtQuick
+
+ListView {
+ id: root
+
+ function allDelegates(valueSelector) {
+ let sum = 0;
+ for (let i = 0; i < root.count; i++)
+ sum += valueSelector(root.itemAtIndex(i));
+ return sum;
+ }
+
+ readonly property bool isXReset: allDelegates(function(item) { return item?.x ?? 0; }) === 0
+ readonly property bool isYReset: allDelegates(function(item) { return item?.y ?? 0; }) === 0
+
+ width: 500
+ height: 500
+ delegate: Rectangle {
+ width: root.width
+ height: root.height
+ color: c
+ }
+ model: ListModel {
+ ListElement {
+ c: "red"
+ }
+ ListElement {
+ c: "green"
+ }
+ ListElement {
+ c: "blue"
+ }
+ ListElement {
+ c: "cyan"
+ }
+ ListElement {
+ c: "magenta"
+ }
+ ListElement {
+ c: "teal"
+ }
+ }
+ clip: true
+ orientation: ListView.Vertical
+ snapMode: ListView.SnapOneItem
+ highlightRangeMode: ListView.StrictlyEnforceRange
+} \ No newline at end of file
diff --git a/tests/auto/quick/qquicklistview2/data/changingOrientationWithObjectModel.qml b/tests/auto/quick/qquicklistview2/data/changingOrientationWithObjectModel.qml
new file mode 100644
index 0000000000..1d165a496e
--- /dev/null
+++ b/tests/auto/quick/qquicklistview2/data/changingOrientationWithObjectModel.qml
@@ -0,0 +1,54 @@
+import QtQuick
+
+ListView {
+ id: root
+
+ readonly property bool isXReset: red.x === 0 && green.x === 0 && blue.x === 0 && cyan.x === 0 && magenta.x === 0 && teal.x === 0
+
+ readonly property bool isYReset: red.y === 0 && green.y === 0 && blue.y === 0 && cyan.y === 0 && magenta.y === 0 && teal.y === 0
+
+ width: 500
+ height: 500
+ model: ObjectModel {
+ Rectangle {
+ id: red
+ width: root.width
+ height: root.height
+ color: "red"
+ }
+ Rectangle {
+ id: green
+ width: root.width
+ height: root.height
+ color: "green"
+ }
+ Rectangle {
+ id: blue
+ width: root.width
+ height: root.height
+ color: "blue"
+ }
+ Rectangle {
+ id: cyan
+ width: root.width
+ height: root.height
+ color: "cyan"
+ }
+ Rectangle {
+ id: magenta
+ width: root.width
+ height: root.height
+ color: "magenta"
+ }
+ Rectangle {
+ id: teal
+ width: root.width
+ height: root.height
+ color: "teal"
+ }
+ }
+ clip: true
+ orientation: ListView.Vertical
+ snapMode: ListView.SnapOneItem
+ highlightRangeMode: ListView.StrictlyEnforceRange
+} \ No newline at end of file
diff --git a/tests/auto/quick/qquicklistview2/data/delegateChooserEnumRole.qml b/tests/auto/quick/qquicklistview2/data/delegateChooserEnumRole.qml
index 655900d9de..66e92c5616 100644
--- a/tests/auto/quick/qquicklistview2/data/delegateChooserEnumRole.qml
+++ b/tests/auto/quick/qquicklistview2/data/delegateChooserEnumRole.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import Qt.labs.qmlmodels
diff --git a/tests/auto/quick/qquicklistview2/data/delegateContextHandling.qml b/tests/auto/quick/qquicklistview2/data/delegateContextHandling.qml
new file mode 100644
index 0000000000..4c513df905
--- /dev/null
+++ b/tests/auto/quick/qquicklistview2/data/delegateContextHandling.qml
@@ -0,0 +1,75 @@
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Window
+
+Item {
+ id: win
+ height: 640
+ width: 480
+
+ property string currentModel: 'foo'
+
+ function toggle() : Item {
+ var ret = listView.itemAtIndex(0);
+ win.currentModel = win.currentModel === 'foo' ? 'bar' : 'foo'
+
+ switch (win.currentModel) {
+ case 'foo':
+ if (listView.model) {
+ listView.model.destroy()
+ }
+ listView.model = fooModelComponent.createObject(win)
+ break
+
+ case 'bar':
+ if (listView.model) {
+ listView.model.destroy()
+ }
+ listView.model = barModelComponent.createObject(win)
+ break
+ }
+
+ return ret;
+ }
+
+ Component {
+ id: fooModelComponent
+ ListModel {
+ ListElement { textValue: "foo1" }
+ }
+ }
+
+ Component {
+ id: barModelComponent
+ ListModel {
+ ListElement { textValue: "bar1" }
+ }
+ }
+
+ ListView {
+ states: [
+ State {
+ when: win.currentModel === 'bar'
+ PropertyChanges {
+ listView.section.property: 'sectionProp'
+ }
+ }
+ ]
+
+ id: listView
+ model: fooModelComponent.createObject(win)
+ anchors.fill: parent
+
+ section.delegate: Text {
+ required property string section
+ text: section
+ }
+
+ delegate: Text {
+ id: delg
+ text: delg.textValue
+ required property string textValue
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview2/data/delegateModelRefresh.qml b/tests/auto/quick/qquicklistview2/data/delegateModelRefresh.qml
index 7a2a017515..7a22f1a0f4 100644
--- a/tests/auto/quick/qquicklistview2/data/delegateModelRefresh.qml
+++ b/tests/auto/quick/qquicklistview2/data/delegateModelRefresh.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quick/qquicklistview2/data/delegateWithMouseArea.qml b/tests/auto/quick/qquicklistview2/data/delegateWithMouseArea.qml
index c94001eb43..f447f913e6 100644
--- a/tests/auto/quick/qquicklistview2/data/delegateWithMouseArea.qml
+++ b/tests/auto/quick/qquicklistview2/data/delegateWithMouseArea.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/qquicklistview2/data/fetchMore.qml b/tests/auto/quick/qquicklistview2/data/fetchMore.qml
new file mode 100644
index 0000000000..4ce53e4d28
--- /dev/null
+++ b/tests/auto/quick/qquicklistview2/data/fetchMore.qml
@@ -0,0 +1,21 @@
+import QtQuick
+import org.qtproject.Test
+
+ListView {
+ id: listView
+ width: 300
+ height: 150
+ flickDeceleration: 10000
+
+ model: FetchMoreModel
+ delegate: Text {
+ height: 50
+ text: model.display
+ }
+
+ Text {
+ anchors.right: parent.right
+ text: "count " + listView.count
+ color: listView.moving ? "red" : "blue"
+ }
+}
diff --git a/tests/auto/quick/qquicklistview2/data/footerUpdate.qml b/tests/auto/quick/qquicklistview2/data/footerUpdate.qml
index 058b7a6276..c5729ad633 100644
--- a/tests/auto/quick/qquicklistview2/data/footerUpdate.qml
+++ b/tests/auto/quick/qquicklistview2/data/footerUpdate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/qquicklistview2/data/innerRequired.qml b/tests/auto/quick/qquicklistview2/data/innerRequired.qml
index b45181c0d2..c0862cec0d 100644
--- a/tests/auto/quick/qquicklistview2/data/innerRequired.qml
+++ b/tests/auto/quick/qquicklistview2/data/innerRequired.qml
@@ -25,6 +25,8 @@ Item {
ListView {
id: listView
model: myModel
+ width: 100
+ height: 100
delegate: AnotherDelegate {
age: model.age
text: model.noise
diff --git a/tests/auto/quick/qquicklistview2/data/maxXExtent.qml b/tests/auto/quick/qquicklistview2/data/maxXExtent.qml
index b9e88cfc9e..d72f825654 100644
--- a/tests/auto/quick/qquicklistview2/data/maxXExtent.qml
+++ b/tests/auto/quick/qquicklistview2/data/maxXExtent.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/qquicklistview2/data/maxYExtent.qml b/tests/auto/quick/qquicklistview2/data/maxYExtent.qml
index 3be8948691..b8a1f0e12b 100644
--- a/tests/auto/quick/qquicklistview2/data/maxYExtent.qml
+++ b/tests/auto/quick/qquicklistview2/data/maxYExtent.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/qquicklistview2/data/metaSequenceAsModel.qml b/tests/auto/quick/qquicklistview2/data/metaSequenceAsModel.qml
index 2b4651feaa..461450239f 100644
--- a/tests/auto/quick/qquicklistview2/data/metaSequenceAsModel.qml
+++ b/tests/auto/quick/qquicklistview2/data/metaSequenceAsModel.qml
@@ -2,6 +2,8 @@ import QtQuick
ListView {
id: view
+ width: 100
+ height: 100
property list<rect> rects: [ Qt.rect(1, 2, 3, 4), Qt.rect(5, 6, 7, 8) ]
property list<string> texts
diff --git a/tests/auto/quick/qquicklistview2/data/qtbug86744.qml b/tests/auto/quick/qquicklistview2/data/qtbug86744.qml
index c69a4f7ec6..d8b89a147d 100644
--- a/tests/auto/quick/qquicklistview2/data/qtbug86744.qml
+++ b/tests/auto/quick/qquicklistview2/data/qtbug86744.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQml.Models
diff --git a/tests/auto/quick/qquicklistview2/data/qtbug98315.qml b/tests/auto/quick/qquicklistview2/data/qtbug98315.qml
index bf2ed857b1..4035915c6d 100644
--- a/tests/auto/quick/qquicklistview2/data/qtbug98315.qml
+++ b/tests/auto/quick/qquicklistview2/data/qtbug98315.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQml.Models
diff --git a/tests/auto/quick/qquicklistview2/data/qtbug_92809.qml b/tests/auto/quick/qquicklistview2/data/qtbug_92809.qml
index a003b51335..7507e83f73 100644
--- a/tests/auto/quick/qquicklistview2/data/qtbug_92809.qml
+++ b/tests/auto/quick/qquicklistview2/data/qtbug_92809.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/qquicklistview2/data/sectionBoundComponent.qml b/tests/auto/quick/qquicklistview2/data/sectionBoundComponent.qml
new file mode 100644
index 0000000000..74ab6b59fa
--- /dev/null
+++ b/tests/auto/quick/qquicklistview2/data/sectionBoundComponent.qml
@@ -0,0 +1,14 @@
+pragma ComponentBehavior: Bound
+import QtQuick
+ListView {
+ id: view
+ width: 100
+ height: 100
+ model: ListModel {
+ ListElement { name: "foo"; age: 42 }
+ ListElement { name: "bar"; age: 13 }
+ }
+ delegate: Text { required property string name; text: name}
+ section.property: "age"
+ section.delegate: Rectangle { color: "gray"; width: view.width; height: 20; required property string section; Text {text: parent.section} }
+}
diff --git a/tests/auto/quick/qquicklistview2/data/sectionGeometryChange.qml b/tests/auto/quick/qquicklistview2/data/sectionGeometryChange.qml
new file mode 100644
index 0000000000..6981af51ec
--- /dev/null
+++ b/tests/auto/quick/qquicklistview2/data/sectionGeometryChange.qml
@@ -0,0 +1,58 @@
+import QtQuick
+import QtQuick.Controls
+
+Rectangle {
+ width: 640
+ height: 480
+ color: "#FFFFFF"
+ ListView {
+ objectName: "list"
+ anchors.fill: parent
+
+ delegate: Rectangle {
+ objectName: value
+ implicitHeight: text.implicitHeight
+ color: "#ff3"
+
+ Text {
+ id: text
+ width: parent.width
+ padding: 5
+ font.pixelSize: 20
+ text: value
+ }
+ }
+
+ section {
+ property: "section"
+
+ delegate: Rectangle {
+ objectName: section
+ width: parent.width
+ implicitHeight: text.implicitHeight
+ color: "#3ff"
+
+ Text {
+ id: text
+ width: parent.width
+ padding: 5
+ font.pixelSize: 20
+ text: section
+ wrapMode: Text.Wrap
+ }
+ }
+ }
+
+ model: ListModel {
+ ListElement { value: "Element1"; section: "Section1" }
+ ListElement { value: "Element2"; section: "Section1" }
+ ListElement { value: "Element3"; section: "Section1" }
+ ListElement { value: "Element4"; section: "Section2" }
+ ListElement { value: "Element5"; section: "Section2" }
+ ListElement { value: "Element6"; section: "Section2" }
+ ListElement { value: "Element7"; section: "Section2" }
+ ListElement { value: "Element8"; section: "Section3" }
+ ListElement { value: "Element9"; section: "Section3" }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview2/data/sectionsNoOverlap.qml b/tests/auto/quick/qquicklistview2/data/sectionsNoOverlap.qml
index d931bbb77c..3a22626032 100644
--- a/tests/auto/quick/qquicklistview2/data/sectionsNoOverlap.qml
+++ b/tests/auto/quick/qquicklistview2/data/sectionsNoOverlap.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quick/qquicklistview2/data/urlListModel.qml b/tests/auto/quick/qquicklistview2/data/urlListModel.qml
index 94d5c37a56..38237234e0 100644
--- a/tests/auto/quick/qquicklistview2/data/urlListModel.qml
+++ b/tests/auto/quick/qquicklistview2/data/urlListModel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/qquicklistview2/data/viewportAvoidUndesiredMovementOnSetCurrentIndex.qml b/tests/auto/quick/qquicklistview2/data/viewportAvoidUndesiredMovementOnSetCurrentIndex.qml
new file mode 100644
index 0000000000..cd3865d55b
--- /dev/null
+++ b/tests/auto/quick/qquicklistview2/data/viewportAvoidUndesiredMovementOnSetCurrentIndex.qml
@@ -0,0 +1,47 @@
+import QtQuick
+
+Item {
+ id: root
+ width: 400
+ height: 600
+
+ ListView {
+ id: rawList
+ objectName: "list"
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: 300
+
+ // full disabling of automatic viewport positioning
+ highlightFollowsCurrentItem: false
+ snapMode: ListView.NoSnap
+ highlightRangeMode: ListView.NoHighlightRange
+
+ delegate: Rectangle {
+ color: model.index === rawList.currentIndex ? "red" : "white"
+ border.color: rawList.currentItem === this ? "red" : "black"
+ height: 100
+ width: 400
+
+ Text {
+ anchors.centerIn: parent
+ text: model.index
+ font.pixelSize: 50
+ }
+
+ MouseArea {
+ // only for using this file to do manual testing
+ // autotest calls setCurrentIndex
+ anchors.fill: parent
+
+ onClicked: {
+ rawList.currentIndex = model.index;
+ }
+ }
+ }
+
+ model: 30
+ }
+
+}
diff --git a/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp b/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp
index 117ec0c94d..bdac2112b6 100644
--- a/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp
+++ b/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuick/qquickview.h>
@@ -52,6 +52,21 @@ private slots:
void pullbackSparseList();
void highlightWithBound();
+ void sectionIsCompatibleWithBoundComponents();
+ void sectionGeometryChange();
+ void areaZeroviewDoesNotNeedlesslyPopulateWholeModel();
+ void viewportAvoidUndesiredMovementOnSetCurrentIndex();
+
+ void delegateContextHandling();
+ void fetchMore_data();
+ void fetchMore();
+
+ void changingOrientationResetsPreviousAxisValues_data();
+ void changingOrientationResetsPreviousAxisValues();
+ void bindingDirectlyOnPositionInHeaderAndFooterDelegates_data();
+ void bindingDirectlyOnPositionInHeaderAndFooterDelegates();
+
+ void clearObjectListModel();
private:
void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to);
@@ -120,6 +135,33 @@ void tst_QQuickListView2::dragDelegateWithMouseArea_data()
}
}
+void tst_QQuickListView2::viewportAvoidUndesiredMovementOnSetCurrentIndex()
+{
+ QScopedPointer<QQuickView> window(createView());
+ QVERIFY(window);
+ window->setFlag(Qt::FramelessWindowHint);
+ window->setSource(testFileUrl("viewportAvoidUndesiredMovementOnSetCurrentIndex.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(window->rootObject());
+ QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
+ QVERIFY(listview);
+ listview->setCurrentIndex(2); // change current item
+ // partially obscure first item
+ QCOMPARE(listview->contentY(), 0);
+ listview->setContentY(50);
+ QTRY_COMPARE(listview->contentY(), 50);
+ listview->setCurrentIndex(0); // change current item back to first one
+ QVERIFY(QQuickTest::qWaitForPolish(listview));
+ // that shouldn't have caused any movement
+ QCOMPARE(listview->contentY(), 50);
+
+ // that even applies to the case where the current item is completely out of the viewport
+ listview->setCurrentIndex(25);
+ QVERIFY(QQuickTest::qWaitForPolish(listview));
+ QCOMPARE(listview->contentY(), 50);
+}
+
void tst_QQuickListView2::dragDelegateWithMouseArea()
{
QFETCH(QQuickItemView::LayoutDirection, layoutDirection);
@@ -332,7 +374,7 @@ void tst_QQuickListView2::boundDelegateComponent()
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QTest::ignoreMessage(
- QtWarningMsg, qPrintable(QLatin1String("%1:12: ReferenceError: index is not defined")
+ QtWarningMsg, qPrintable(QLatin1String("%1:14: ReferenceError: index is not defined")
.arg(url.toString())));
QScopedPointer<QObject> o(c.create());
@@ -363,7 +405,7 @@ void tst_QQuickListView2::boundDelegateComponent()
for (int i = 0; i < 3; ++i) {
QTest::ignoreMessage(
QtWarningMsg,
- qPrintable(QLatin1String("%1:47:21: ReferenceError: model is not defined")
+ qPrintable(QLatin1String("%1:51:21: ReferenceError: model is not defined")
.arg(url.toString())));
}
@@ -381,29 +423,31 @@ void tst_QQuickListView2::tapDelegateDuringFlicking_data()
{
QTest::addColumn<QByteArray>("qmlFile");
QTest::addColumn<QQuickFlickable::BoundsBehavior>("boundsBehavior");
+ QTest::addColumn<bool>("expectCanceled");
QTest::newRow("Button StopAtBounds") << QByteArray("buttonDelegate.qml")
- << QQuickFlickable::BoundsBehavior(QQuickFlickable::StopAtBounds);
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::StopAtBounds) << false;
QTest::newRow("MouseArea StopAtBounds") << QByteArray("mouseAreaDelegate.qml")
- << QQuickFlickable::BoundsBehavior(QQuickFlickable::StopAtBounds);
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::StopAtBounds) << true;
QTest::newRow("Button DragOverBounds") << QByteArray("buttonDelegate.qml")
- << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragOverBounds);
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragOverBounds) << false;
QTest::newRow("MouseArea DragOverBounds") << QByteArray("mouseAreaDelegate.qml")
- << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragOverBounds);
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragOverBounds) << true;
QTest::newRow("Button OvershootBounds") << QByteArray("buttonDelegate.qml")
- << QQuickFlickable::BoundsBehavior(QQuickFlickable::OvershootBounds);
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::OvershootBounds) << false;
QTest::newRow("MouseArea OvershootBounds") << QByteArray("mouseAreaDelegate.qml")
- << QQuickFlickable::BoundsBehavior(QQuickFlickable::OvershootBounds);
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::OvershootBounds) << true;
QTest::newRow("Button DragAndOvershootBounds") << QByteArray("buttonDelegate.qml")
- << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragAndOvershootBounds);
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragAndOvershootBounds) << false;
QTest::newRow("MouseArea DragAndOvershootBounds") << QByteArray("mouseAreaDelegate.qml")
- << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragAndOvershootBounds);
+ << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragAndOvershootBounds) << true;
}
void tst_QQuickListView2::tapDelegateDuringFlicking() // QTBUG-103832
{
QFETCH(QByteArray, qmlFile);
QFETCH(QQuickFlickable::BoundsBehavior, boundsBehavior);
+ QFETCH(bool, expectCanceled);
QQuickView window;
QVERIFY(QQuickTest::showView(window, testFileUrl(qmlFile.constData())));
@@ -416,7 +460,16 @@ void tst_QQuickListView2::tapDelegateDuringFlicking() // QTBUG-103832
QVERIFY(listView->isFlicking()); // we want to test the case when it's still moving while we tap
// @y = 400 we pressed the 4th delegate; started flicking, and the press was canceled
QCOMPARE(listView->property("pressedDelegates").toList().first(), 4);
- QCOMPARE(listView->property("canceledDelegates").toList().first(), 4);
+ // At first glance one would expect MouseArea and Button would be consistent about this;
+ // but in fact, before ListView takes over the grab via filtering,
+ // Button.pressed transitions to false because QQuickAbstractButtonPrivate::handleMove
+ // sees that the touchpoint has strayed outside its bounds, but it does NOT emit the canceled signal
+ if (expectCanceled) {
+ const QVariantList canceledDelegates = listView->property("canceledDelegates").toList();
+ QCOMPARE(canceledDelegates.size(), 1);
+ QCOMPARE(canceledDelegates.first(), 4);
+ }
+ QCOMPARE(listView->property("releasedDelegates").toList().size(), 0);
// press a delegate during flicking (at y > 501 + 100, so likely delegate 6)
QTest::touchEvent(&window, touchDevice.data()).press(0, {100, 100});
@@ -439,7 +492,7 @@ void tst_QQuickListView2::tapDelegateDuringFlicking() // QTBUG-103832
QVERIFY(lastPressed > 5);
QCOMPARE(releasedDelegates.last(), lastPressed);
QCOMPARE(tappedDelegates.last(), lastPressed);
- QCOMPARE(canceledDelegates.size(), 1); // only the first press was canceled, not the second
+ QCOMPARE(canceledDelegates.size(), expectCanceled ? 1 : 0); // only the first press was canceled, not the second
}
void tst_QQuickListView2::flickDuringFlicking_data()
@@ -698,122 +751,122 @@ void tst_QQuickListView2::wheelSnap_data()
QTest::newRow("vertical, top to bottom")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::TopToBottom
- << QQuickItemView::NoHighlightRange << QPoint(20, -120) << 200.0 << 600.0 << 0.0 << 0.0
+ << QQuickItemView::NoHighlightRange << QPoint(20, -240) << 200.0 << 600.0 << 0.0 << 0.0
<< 0.0;
QTest::newRow("vertical, bottom to top")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::BottomToTop
- << QQuickItemView::NoHighlightRange << QPoint(20, 120) << -400.0 << -800.0 << -200.0
+ << QQuickItemView::NoHighlightRange << QPoint(20, 240) << -400.0 << -800.0 << -200.0
<< 0.0 << 0.0;
QTest::newRow("horizontal, left to right")
<< QQuickListView::Horizontal << Qt::LeftToRight << QQuickItemView::TopToBottom
- << QQuickItemView::NoHighlightRange << QPoint(-120, 20) << 200.0 << 600.0 << 0.0 << 0.0
+ << QQuickItemView::NoHighlightRange << QPoint(-240, 20) << 200.0 << 600.0 << 0.0 << 0.0
<< 0.0;
QTest::newRow("horizontal, right to left")
<< QQuickListView::Horizontal << Qt::RightToLeft << QQuickItemView::TopToBottom
- << QQuickItemView::NoHighlightRange << QPoint(120, 20) << -400.0 << -800.0 << -200.0
+ << QQuickItemView::NoHighlightRange << QPoint(240, 20) << -400.0 << -800.0 << -200.0
<< 0.0 << 0.0;
QTest::newRow("vertical, top to bottom, enforce range")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::TopToBottom
- << QQuickItemView::StrictlyEnforceRange << QPoint(20, -120) << 200.0 << 600.0 << 0.0
+ << QQuickItemView::StrictlyEnforceRange << QPoint(20, -240) << 200.0 << 600.0 << 0.0
<< 0.0 << 0.0;
QTest::newRow("vertical, bottom to top, enforce range")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::BottomToTop
- << QQuickItemView::StrictlyEnforceRange << QPoint(20, 120) << -400.0 << -800.0 << -200.0
+ << QQuickItemView::StrictlyEnforceRange << QPoint(20, 240) << -400.0 << -800.0 << -200.0
<< 0.0 << 0.0;
QTest::newRow("horizontal, left to right, enforce range")
<< QQuickListView::Horizontal << Qt::LeftToRight << QQuickItemView::TopToBottom
- << QQuickItemView::StrictlyEnforceRange << QPoint(-120, 20) << 200.0 << 600.0 << 0.0
+ << QQuickItemView::StrictlyEnforceRange << QPoint(-240, 20) << 200.0 << 600.0 << 0.0
<< 0.0 << 0.0;
QTest::newRow("horizontal, right to left, enforce range")
<< QQuickListView::Horizontal << Qt::RightToLeft << QQuickItemView::TopToBottom
- << QQuickItemView::StrictlyEnforceRange << QPoint(120, 20) << -400.0 << -800.0 << -200.0
+ << QQuickItemView::StrictlyEnforceRange << QPoint(240, 20) << -400.0 << -800.0 << -200.0
<< 0.0 << 0.0;
QTest::newRow("vertical, top to bottom, apply range")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::TopToBottom
- << QQuickItemView::ApplyRange << QPoint(20, -120) << 200.0 << 600.0 << 0.0 << 0.0
+ << QQuickItemView::ApplyRange << QPoint(20, -240) << 200.0 << 600.0 << 0.0 << 0.0
<< 0.0;
QTest::newRow("vertical, bottom to top, apply range")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::BottomToTop
- << QQuickItemView::ApplyRange << QPoint(20, 120) << -400.0 << -800.0 << -200.0 << 0.0
+ << QQuickItemView::ApplyRange << QPoint(20, 240) << -400.0 << -800.0 << -200.0 << 0.0
<< 0.0;
QTest::newRow("horizontal, left to right, apply range")
<< QQuickListView::Horizontal << Qt::LeftToRight << QQuickItemView::TopToBottom
- << QQuickItemView::ApplyRange << QPoint(-120, 20) << 200.0 << 600.0 << 0.0 << 0.0
+ << QQuickItemView::ApplyRange << QPoint(-240, 20) << 200.0 << 600.0 << 0.0 << 0.0
<< 0.0;
QTest::newRow("horizontal, right to left, apply range")
<< QQuickListView::Horizontal << Qt::RightToLeft << QQuickItemView::TopToBottom
- << QQuickItemView::ApplyRange << QPoint(120, 20) << -400.0 << -800.0 << -200.0 << 0.0
+ << QQuickItemView::ApplyRange << QPoint(240, 20) << -400.0 << -800.0 << -200.0 << 0.0
<< 0.0;
QTest::newRow("vertical, top to bottom with highlightRange")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::TopToBottom
- << QQuickItemView::NoHighlightRange << QPoint(20, -120) << 190.0 << 600.0 << 0.0 << 10.0
+ << QQuickItemView::NoHighlightRange << QPoint(20, -240) << 190.0 << 600.0 << 0.0 << 10.0
<< 210.0;
QTest::newRow("vertical, bottom to top with highlightRange")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::BottomToTop
- << QQuickItemView::NoHighlightRange << QPoint(20, 120) << -390.0 << -800.0 << -200.0
+ << QQuickItemView::NoHighlightRange << QPoint(20, 240) << -390.0 << -800.0 << -200.0
<< 10.0 << 210.0;
QTest::newRow("horizontal, left to right with highlightRange")
<< QQuickListView::Horizontal << Qt::LeftToRight << QQuickItemView::TopToBottom
- << QQuickItemView::NoHighlightRange << QPoint(-120, 20) << 190.0 << 600.0 << 0.0 << 10.0
+ << QQuickItemView::NoHighlightRange << QPoint(-240, 20) << 190.0 << 600.0 << 0.0 << 10.0
<< 210.0;
QTest::newRow("horizontal, right to left with highlightRange")
<< QQuickListView::Horizontal << Qt::RightToLeft << QQuickItemView::TopToBottom
- << QQuickItemView::NoHighlightRange << QPoint(120, 20) << -390.0 << -800.0 << -200.0
+ << QQuickItemView::NoHighlightRange << QPoint(240, 20) << -390.0 << -800.0 << -200.0
<< 10.0 << 210.0;
QTest::newRow("vertical, top to bottom, enforce range with highlightRange")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::TopToBottom
- << QQuickItemView::StrictlyEnforceRange << QPoint(20, -120) << 190.0 << 590.0 << -10.0
+ << QQuickItemView::StrictlyEnforceRange << QPoint(20, -240) << 190.0 << 590.0 << -10.0
<< 10.0 << 210.0;
QTest::newRow("vertical, bottom to top, enforce range with highlightRange")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::BottomToTop
- << QQuickItemView::StrictlyEnforceRange << QPoint(20, 120) << -390.0 << -790.0 << -190.0
+ << QQuickItemView::StrictlyEnforceRange << QPoint(20, 240) << -390.0 << -790.0 << -190.0
<< 10.0 << 210.0;
QTest::newRow("horizontal, left to right, enforce range with highlightRange")
<< QQuickListView::Horizontal << Qt::LeftToRight << QQuickItemView::TopToBottom
- << QQuickItemView::StrictlyEnforceRange << QPoint(-120, 20) << 190.0 << 590.0 << -10.0
+ << QQuickItemView::StrictlyEnforceRange << QPoint(-240, 20) << 190.0 << 590.0 << -10.0
<< 10.0 << 210.0;
QTest::newRow("horizontal, right to left, enforce range with highlightRange")
<< QQuickListView::Horizontal << Qt::RightToLeft << QQuickItemView::TopToBottom
- << QQuickItemView::StrictlyEnforceRange << QPoint(120, 20) << -390.0 << -790.0 << -190.0
+ << QQuickItemView::StrictlyEnforceRange << QPoint(240, 20) << -390.0 << -790.0 << -190.0
<< 10.0 << 210.0;
QTest::newRow("vertical, top to bottom, apply range with highlightRange")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::TopToBottom
- << QQuickItemView::ApplyRange << QPoint(20, -120) << 190.0 << 600.0 << 0.0 << 10.0
+ << QQuickItemView::ApplyRange << QPoint(20, -240) << 190.0 << 600.0 << 0.0 << 10.0
<< 210.0;
QTest::newRow("vertical, bottom to top, apply range with highlightRange")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::BottomToTop
- << QQuickItemView::ApplyRange << QPoint(20, 120) << -390.0 << -800.0 << -200.0 << 10.0
+ << QQuickItemView::ApplyRange << QPoint(20, 240) << -390.0 << -800.0 << -200.0 << 10.0
<< 210.0;
QTest::newRow("horizontal, left to right, apply range with highlightRange")
<< QQuickListView::Horizontal << Qt::LeftToRight << QQuickItemView::TopToBottom
- << QQuickItemView::ApplyRange << QPoint(-120, 20) << 190.0 << 600.0 << 0.0 << 10.0
+ << QQuickItemView::ApplyRange << QPoint(-240, 20) << 190.0 << 600.0 << 0.0 << 10.0
<< 210.0;
QTest::newRow("horizontal, right to left, apply range with highlightRange")
<< QQuickListView::Horizontal << Qt::RightToLeft << QQuickItemView::TopToBottom
- << QQuickItemView::ApplyRange << QPoint(120, 20) << -390.0 << -800.0 << -200.0 << 10.0
+ << QQuickItemView::ApplyRange << QPoint(240, 20) << -390.0 << -800.0 << -200.0 << 10.0
<< 210.0;
}
@@ -946,6 +999,257 @@ void tst_QQuickListView2::highlightWithBound()
QCOMPARE(highlight->objectName(), QStringLiteral("highlight"));
}
+void tst_QQuickListView2::sectionIsCompatibleWithBoundComponents()
+{
+ QTest::failOnWarning(".?");
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("sectionBoundComponent.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QQuickListView *listView = qobject_cast<QQuickListView *>(o.data());
+ QVERIFY(listView);
+ QTRY_COMPARE(listView->currentSection(), "42");
+}
+
+void tst_QQuickListView2::sectionGeometryChange()
+{
+ QScopedPointer<QQuickView> window(createView());
+ QTRY_VERIFY(window);
+ window->setSource(testFileUrl("sectionGeometryChange.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
+ QTRY_VERIFY(listview);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem);
+ QVERIFY(QQuickTest::qWaitForPolish(listview));
+
+ QQuickItem *section1 = findItem<QQuickItem>(contentItem, "Section1");
+ QVERIFY(section1);
+ QQuickItem *element1 = findItem<QQuickItem>(contentItem, "Element1");
+ QVERIFY(element1);
+
+ QCOMPARE(element1->y(), section1->y() + section1->height());
+
+ // Update the height of the section delegate and verify that the next element is not overlapping
+ section1->setHeight(section1->height() + 10);
+ QTRY_COMPARE(element1->y(), section1->y() + section1->height());
+}
+
+void tst_QQuickListView2::areaZeroviewDoesNotNeedlesslyPopulateWholeModel()
+{
+ QTest::failOnWarning(QRegularExpression(".*"));
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("areaZeroView.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ std::unique_ptr<QObject> root(c.create());
+ QVERIFY(root);
+ auto delegateCreationCounter = [&]() {
+ return root->property("delegateCreationCounter").toInt();
+ };
+ // wait for onComplete to be settled
+ QTRY_VERIFY(delegateCreationCounter() != 0);
+ auto view = qobject_cast<QQuickListView *>(qmlContext(root.get())->objectForName("lv"));
+ QVERIFY(view);
+ QCOMPARE(view->count(), 6'000);
+ // we use 100, which is < 6000, but larger than the actual expected value
+ // that's to give the test some leniency in case the ListView implementation
+ // changes in the future to instantiate a few more items outside of the viewport
+ QVERIFY(delegateCreationCounter() < 100);
+}
+
+void tst_QQuickListView2::delegateContextHandling()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("delegateContextHandling.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ std::unique_ptr<QObject> o(c.create());
+ QVERIFY(o);
+
+ for (int i = 0; i < 10; ++i) {
+ QQuickItem *delegate = nullptr;
+ QMetaObject::invokeMethod(o.get(), "toggle", Q_RETURN_ARG(QQuickItem *, delegate));
+ QVERIFY(delegate);
+ }
+
+}
+
+class TestFetchMoreModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ QVariant data(const QModelIndex& index, int role) const override
+ {
+ if (role == Qt::DisplayRole)
+ return QString::number(index.row());
+ return {};
+ }
+
+ int columnCount(const QModelIndex&) const override { return 1; }
+
+ int rowCount(const QModelIndex& parent) const override
+ {
+ return parent.isValid() ? 0 : m_lines;
+ }
+
+ QModelIndex parent(const QModelIndex&) const override { return {}; }
+
+ bool canFetchMore(const QModelIndex &) const override { return true; }
+
+ void fetchMore(const QModelIndex & parent) override
+ {
+ if (Q_UNLIKELY(parent.isValid()))
+ return;
+ beginInsertRows(parent, m_lines, m_lines);
+ m_lines++;
+ endInsertRows();
+ }
+
+ int m_lines = 3;
+};
+
+void tst_QQuickListView2::fetchMore_data()
+{
+ QTest::addColumn<bool>("reuseItems");
+ QTest::addColumn<int>("cacheBuffer");
+
+ QTest::newRow("no reuseItems, default buffer") << false << -1;
+ QTest::newRow("reuseItems, default buffer") << true << -1;
+ QTest::newRow("no reuseItems, no buffer") << false << 0;
+ QTest::newRow("reuseItems, no buffer") << true << 0;
+ QTest::newRow("no reuseItems, buffer 100 px") << false << 100;
+ QTest::newRow("reuseItems, buffer 100 px") << true << 100;
+}
+
+void tst_QQuickListView2::fetchMore() // QTBUG-95107
+{
+ QFETCH(bool, reuseItems);
+ QFETCH(int, cacheBuffer);
+
+ TestFetchMoreModel model;
+ qmlRegisterSingletonInstance("org.qtproject.Test", 1, 0, "FetchMoreModel", &model);
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("fetchMore.qml")));
+ auto *listView = qobject_cast<QQuickListView*>(window.rootObject());
+ QVERIFY(listView);
+ listView->setReuseItems(reuseItems);
+ if (cacheBuffer >= 0)
+ listView->setCacheBuffer(cacheBuffer);
+
+ for (int i = 0; i < 3; ++i) {
+ const int rowCount = listView->count();
+ if (lcTests().isDebugEnabled()) QTest::qWait(1000);
+ listView->flick(0, -5000);
+ QTRY_VERIFY(!listView->isMoving());
+ qCDebug(lcTests) << "after flick: contentY" << listView->contentY()
+ << "rows" << rowCount << "->" << listView->count();
+ QCOMPARE_GT(listView->count(), rowCount);
+ QCOMPARE_GE(model.m_lines, listView->count()); // fetchMore() was called
+ }
+}
+
+void tst_QQuickListView2::changingOrientationResetsPreviousAxisValues_data()
+{
+ QTest::addColumn<QByteArray>("sourceFile");
+ QTest::newRow("ObjectModel") << QByteArray("changingOrientationWithObjectModel.qml");
+ QTest::newRow("ListModel") << QByteArray("changingOrientationWithListModel.qml");
+}
+
+void tst_QQuickListView2::changingOrientationResetsPreviousAxisValues() // QTBUG-115696
+{
+ QFETCH(QByteArray, sourceFile);
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl(QString::fromLatin1(sourceFile))));
+ auto *listView = qobject_cast<QQuickListView *>(window.rootObject());
+ QVERIFY(listView);
+
+ // Starts of with vertical orientation. X should be 0 for all delegates, but not Y.
+ QVERIFY(listView->property("isXReset").toBool());
+ QVERIFY(!listView->property("isYReset").toBool());
+
+ listView->setOrientation(QQuickListView::Orientation::Horizontal);
+
+ // Y should be 0 for all delegates, but not X.
+ QVERIFY(!listView->property("isXReset").toBool());
+ QVERIFY(listView->property("isYReset").toBool());
+
+ listView->setOrientation(QQuickListView::Orientation::Vertical);
+
+ // X should be 0 for all delegates, but not Y.
+ QVERIFY(listView->property("isXReset").toBool());
+ QVERIFY(!listView->property("isYReset").toBool());
+}
+
+void tst_QQuickListView2::bindingDirectlyOnPositionInHeaderAndFooterDelegates_data()
+{
+ QTest::addColumn<QByteArray>("sourceFile");
+ QTest::addColumn<qreal(QQuickItem::*)()const>("pos");
+ QTest::addColumn<qreal(QQuickItem::*)()const>("size");
+ QTest::newRow("XPosition") << QByteArray("bindOnHeaderAndFooterXPosition.qml") << &QQuickItem::x << &QQuickItem::width;
+ QTest::newRow("YPosition") << QByteArray("bindOnHeaderAndFooterYPosition.qml") << &QQuickItem::y << &QQuickItem::height;
+}
+void tst_QQuickListView2::bindingDirectlyOnPositionInHeaderAndFooterDelegates()
+{
+
+ typedef qreal (QQuickItem::*position_func_t)() const;
+ QFETCH(QByteArray, sourceFile);
+ QFETCH(position_func_t, pos);
+ QFETCH(position_func_t, size);
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl(QString::fromLatin1(sourceFile))));
+ auto *listView = qobject_cast<QQuickListView *>(window.rootObject());
+ QVERIFY(listView);
+
+ const qreal widthOrHeight = (listView->*size)();
+
+ QCOMPARE((listView->headerItem()->*pos)(), (widthOrHeight - 50) / 2);
+ QCOMPARE((listView->footerItem()->*pos)(), (widthOrHeight - 50) / 2);
+
+ // Verify that the "regular" delegate items, don't honor x and y bindings.
+ // This should only be allowed for header and footer delegates.
+ for (int i = 0; i < listView->count(); ++i)
+ QCOMPARE((listView->itemAtIndex(i)->*pos)(), 0);
+}
+
+void tst_QQuickListView2::clearObjectListModel()
+{
+ QQmlEngine engine;
+ QQmlComponent delegate(&engine);
+
+ // Need one required property to trigger the incremental rebuilding of metaobjects.
+ delegate.setData("import QtQuick\nItem { required property int index }", QUrl());
+
+ QQuickListView list;
+ engine.setContextForObject(&list, engine.rootContext());
+ list.setDelegate(&delegate);
+ list.setWidth(640);
+ list.setHeight(480);
+
+ QScopedPointer modelObject(new QObject);
+
+ // Use a list that might also carry something non-QObject
+
+ list.setModel(QVariantList {
+ QVariant::fromValue(modelObject.data()),
+ QVariant::fromValue(modelObject.data())
+ });
+
+ QVERIFY(list.itemAtIndex(0));
+
+ modelObject.reset();
+
+ // list should not access dangling pointer from old model data anymore.
+ list.setModel(QVariantList());
+
+ QVERIFY(!list.itemAtIndex(0));
+}
+
QTEST_MAIN(tst_QQuickListView2)
#include "tst_qquicklistview2.moc"
diff --git a/tests/auto/quick/qquicklistview2/typerolemodel.cpp b/tests/auto/quick/qquicklistview2/typerolemodel.cpp
index 36b3d28446..94da87beda 100644
--- a/tests/auto/quick/qquicklistview2/typerolemodel.cpp
+++ b/tests/auto/quick/qquicklistview2/typerolemodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "typerolemodel.h"
diff --git a/tests/auto/quick/qquicklistview2/typerolemodel.h b/tests/auto/quick/qquicklistview2/typerolemodel.h
index 4db39c9059..f47400a88c 100644
--- a/tests/auto/quick/qquicklistview2/typerolemodel.h
+++ b/tests/auto/quick/qquicklistview2/typerolemodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QAbstractListModel>
#include <qqml.h>
diff --git a/tests/auto/quick/qquickloader/CMakeLists.txt b/tests/auto/quick/qquickloader/CMakeLists.txt
index 0ee885a284..f7192df326 100644
--- a/tests/auto/quick/qquickloader/CMakeLists.txt
+++ b/tests/auto/quick/qquickloader/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickloader Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickloader LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickloader/data/Rect120x60.qml b/tests/auto/quick/qquickloader/data/Rect120x60.qml
index fc9e447e69..6a0bb3d766 100644
--- a/tests/auto/quick/qquickloader/data/Rect120x60.qml
+++ b/tests/auto/quick/qquickloader/data/Rect120x60.qml
@@ -1,6 +1,10 @@
import QtQuick 2.0
Rectangle {
- width: 120
- height:60
+ property int base: 60
+ property int w: base*2
+ property int h: base
+ property int ignore: 0
+ width: w
+ height: h
}
diff --git a/tests/auto/quick/qquickloader/data/bindings.qml b/tests/auto/quick/qquickloader/data/bindings.qml
index 1f4cc92864..5ea4ba34f4 100644
--- a/tests/auto/quick/qquickloader/data/bindings.qml
+++ b/tests/auto/quick/qquickloader/data/bindings.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickloader/data/itemLoaderItemWindow.qml b/tests/auto/quick/qquickloader/data/itemLoaderItemWindow.qml
index e4e6088ebe..0d355f6c38 100644
--- a/tests/auto/quick/qquickloader/data/itemLoaderItemWindow.qml
+++ b/tests/auto/quick/qquickloader/data/itemLoaderItemWindow.qml
@@ -18,7 +18,7 @@ Item {
color: "red"
title: "red"
flags: Qt.Dialog
- onVisibilityChanged: console.log("visibility " + visibility)
+ onVisibilityChanged: (visibility) => console.log("visibility " + visibility)
onVisibleChanged: console.log("visible " + visible)
}
}
diff --git a/tests/auto/quick/qquickloader/data/itemLoaderWindow.qml b/tests/auto/quick/qquickloader/data/itemLoaderWindow.qml
index e3eb0f7e9a..c5d4dd1509 100644
--- a/tests/auto/quick/qquickloader/data/itemLoaderWindow.qml
+++ b/tests/auto/quick/qquickloader/data/itemLoaderWindow.qml
@@ -14,7 +14,7 @@ Item {
color: "red"
title: "red"
flags: Qt.Dialog
- onVisibilityChanged: console.log("visibility " + visibility)
+ onVisibilityChanged: (visibility) => console.log("visibility " + visibility)
onVisibleChanged: console.log("visible " + visible)
}
}
diff --git a/tests/auto/quick/qquickloader/data/noEngine.qml b/tests/auto/quick/qquickloader/data/noEngine.qml
index 19e619f32e..821ed30649 100644
--- a/tests/auto/quick/qquickloader/data/noEngine.qml
+++ b/tests/auto/quick/qquickloader/data/noEngine.qml
@@ -18,7 +18,7 @@ Item {
Timer {
onTriggered: {
root.a = true
- l.source = "loaded.qml"
+ l.source = "BlueRect.qml"
}
interval: 0
running: true
diff --git a/tests/auto/quick/qquickloader/data/parentErrors.qml b/tests/auto/quick/qquickloader/data/parentErrors.qml
index 97a4e202a6..f73213c433 100644
--- a/tests/auto/quick/qquickloader/data/parentErrors.qml
+++ b/tests/auto/quick/qquickloader/data/parentErrors.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickloader/data/rootContext.qml b/tests/auto/quick/qquickloader/data/rootContext.qml
index bd6fe82bcf..f73df2c53c 100644
--- a/tests/auto/quick/qquickloader/data/rootContext.qml
+++ b/tests/auto/quick/qquickloader/data/rootContext.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index af7fd237f9..26dfd595cd 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <QSignalSpy>
@@ -63,6 +64,7 @@ private slots:
void componentToUrl();
void anchoredLoader();
void sizeLoaderToItem();
+ void sizeItemToLoader_data();
void sizeItemToLoader();
void noResize();
void networkRequestUrl();
@@ -108,6 +110,7 @@ private slots:
void statusChangeOnlyEmittedOnce();
void setSourceAndCheckStatus();
+ void loadComponentWithStates();
void asyncLoaderRace();
void noEngine();
@@ -119,7 +122,7 @@ private slots:
Q_DECLARE_METATYPE(QList<QQmlError>)
tst_QQuickLoader::tst_QQuickLoader()
- : QQmlDataTest(QT_QMLTEST_DATADIR)
+ : QQmlDataTest(QT_QMLTEST_DATADIR, FailOnWarningsPolicy::FailOnWarnings)
{
qmlRegisterType<SlowComponent>("LoaderTest", 1, 0, "SlowComponent");
qRegisterMetaType<QList<QQmlError>>();
@@ -376,8 +379,29 @@ void tst_QQuickLoader::sizeLoaderToItem()
QCOMPARE(rect->height(), 30.0);
}
+void tst_QQuickLoader::sizeItemToLoader_data()
+{
+ QTest::addColumn<QString>("property");
+ QTest::addColumn<int>("value");
+ QTest::addColumn<bool>("atOnce");
+
+ QTest::addRow("none_atonce") << "ignore" << 42 << true;
+ QTest::addRow("width_atonce") << "w" << 42 << true;
+ QTest::addRow("height_atonce") << "h" << 42 << true;
+ QTest::addRow("both_atonce") << "both" << 42 << true;
+
+
+ QTest::addRow("none") << "ignore" << 42 << false;
+ QTest::addRow("width") << "w" << 42 << false;
+ QTest::addRow("height") << "h" << 42 << false;
+ QTest::addRow("both") << "both" << 42 << false;
+}
+
void tst_QQuickLoader::sizeItemToLoader()
{
+ QFETCH(QString, property);
+ QFETCH(int, value);
+ QFETCH(bool, atOnce);
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("/SizeToLoader.qml"));
QScopedPointer<QQuickLoader> loader(qobject_cast<QQuickLoader*>(component.create()));
@@ -387,17 +411,25 @@ void tst_QQuickLoader::sizeItemToLoader()
QQuickItem *rect = qobject_cast<QQuickItem*>(loader->item());
QVERIFY(rect);
+ rect->setProperty(property.toUtf8(), value);
QCOMPARE(rect->width(), 200.0);
QCOMPARE(rect->height(), 80.0);
// Check resize
QSizeChangeListener sizeListener(rect);
const QSizeF size(180, 30);
- loader->setSize(size);
+ if (atOnce) {
+ loader->setSize(size);
+ } else {
+ loader->setWidth(size.width());
+ loader->setHeight(size.height());
+ }
QVERIFY2(!sizeListener.isEmpty(), "There should be at least one signal about the size changed");
- for (const QSizeF sizeOnGeometryChanged : sizeListener) {
- // Check that we have the correct size on all signals
- QCOMPARE(sizeOnGeometryChanged, size);
+ if (atOnce) {
+ for (const QSizeF sizeOnGeometryChanged : sizeListener) {
+ // Check that we have the correct size on all signals
+ QCOMPARE(sizeOnGeometryChanged, size);
+ }
}
QCOMPARE(rect->width(), size.width());
QCOMPARE(rect->height(), size.height());
@@ -704,7 +736,7 @@ void tst_QQuickLoader::initialPropertyValues()
ThreadedTestHTTPServer server(dataDirectory());
- foreach (const QString &warning, expectedWarnings)
+ for (const QString &warning : std::as_const(expectedWarnings))
QTest::ignoreMessage(QtWarningMsg, QRegularExpression(warning.toLatin1().constData()));
QQmlEngine engine;
@@ -750,8 +782,10 @@ void tst_QQuickLoader::initialPropertyValuesError_data()
QTest::newRow("nonexistent source url") << testFileUrl("initialPropertyValues.error.2.qml")
<< (QStringList() << QString(testFileUrl("NonexistentSourceComponent.qml").toString() + ": No such file or directory"));
- QTest::newRow("invalid source url") << testFileUrl("initialPropertyValues.error.3.qml")
- << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Expected token `:'"));
+ QTest::newRow("invalid source url")
+ << testFileUrl("initialPropertyValues.error.3.qml")
+ << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString()
+ + ":4:5: Incomplete binding, expected token `:` or `{`"));
QTest::newRow("invalid initial property values object with invalid property access") << testFileUrl("initialPropertyValues.error.4.qml")
<< (QStringList() << QString(testFileUrl("initialPropertyValues.error.4.qml").toString() + ":7:5: QML Loader: setSource: value is not an object")
@@ -763,7 +797,7 @@ void tst_QQuickLoader::initialPropertyValuesError()
QFETCH(QUrl, qmlFile);
QFETCH(QStringList, expectedWarnings);
- foreach (const QString &warning, expectedWarnings)
+ for (const QString &warning : std::as_const(expectedWarnings))
QTest::ignoreMessage(QtWarningMsg, warning.toUtf8().constData());
QQmlEngine engine;
@@ -896,8 +930,10 @@ void tst_QQuickLoader::asynchronous_data()
QTest::newRow("Non-existent component") << testFileUrl("IDoNotExist.qml")
<< (QStringList() << QString(testFileUrl("IDoNotExist.qml").toString() + ": No such file or directory"));
- QTest::newRow("Invalid component") << testFileUrl("InvalidSourceComponent.qml")
- << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Expected token `:'"));
+ QTest::newRow("Invalid component")
+ << testFileUrl("InvalidSourceComponent.qml")
+ << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString()
+ + ":4:5: Incomplete binding, expected token `:` or `{`"));
}
void tst_QQuickLoader::asynchronous()
@@ -918,7 +954,7 @@ void tst_QQuickLoader::asynchronous()
QQuickLoader *loader = root->findChild<QQuickLoader*>("loader");
QVERIFY(loader);
- foreach (const QString &warning, expectedWarnings)
+ for (const QString &warning : std::as_const(expectedWarnings))
QTest::ignoreMessage(QtWarningMsg, warning.toUtf8().constData());
QVERIFY(!loader->item());
@@ -1491,10 +1527,30 @@ void tst_QQuickLoader::setSourceAndCheckStatus()
QMetaObject::invokeMethod(loader, "load", Q_ARG(QVariant, QVariant::fromValue(QStringLiteral(""))));
QCOMPARE(loader->status(), QQuickLoader::Null);
- QMetaObject::invokeMethod(loader, "load", Q_ARG(QVariant, QVariant()));
+ QMetaObject::invokeMethod(loader, "load", Q_ARG(QVariant, QVariant(QUrl())));
QCOMPARE(loader->status(), QQuickLoader::Null);
}
+void tst_QQuickLoader::loadComponentWithStates()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(QByteArray("import QtQuick\n"
+ "Loader {\n"
+ "id: loader\n"
+ "property int createdObjCount: 0\n"
+ "states: [ State { when: true; PropertyChanges { target: loader; sourceComponent: myComp } } ]\n"
+ "Component { id: myComp; Item { Component.onCompleted: { ++createdObjCount } } }\n"
+ "}" )
+ , dataDirectoryUrl());
+ QScopedPointer<QQuickLoader> loader(qobject_cast<QQuickLoader*>(component.create()));
+ QTest::qWait(200);
+ QTRY_VERIFY(loader != nullptr);
+ QVERIFY(loader->item());
+ QCOMPARE(static_cast<QQuickItem*>(loader.data())->childItems().size(), 1);
+ QCOMPARE(loader->property("createdObjCount").toInt(), 1);
+}
+
void tst_QQuickLoader::asyncLoaderRace()
{
QQmlApplicationEngine engine;
diff --git a/tests/auto/quick/qquickmousearea/CMakeLists.txt b/tests/auto/quick/qquickmousearea/CMakeLists.txt
index d358dfb0e8..48262229fc 100644
--- a/tests/auto/quick/qquickmousearea/CMakeLists.txt
+++ b/tests/auto/quick/qquickmousearea/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickmousearea Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickmousearea LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickmousearea/data/clickThrough2.qml b/tests/auto/quick/qquickmousearea/data/clickThrough2.qml
index 2624108225..4e87b4eeb5 100644
--- a/tests/auto/quick/qquickmousearea/data/clickThrough2.qml
+++ b/tests/auto/quick/qquickmousearea/data/clickThrough2.qml
@@ -28,8 +28,8 @@ Item{
enabled: true
anchors.fill: parent
propagateComposedEvents: !noPropagation
- onClicked: mouse.accepted = !letThrough;
- onDoubleClicked: mouse.accepted = !letThrough;
- onPressAndHold: mouse.accepted = !letThrough;
+ onClicked: function (mouse) { mouse.accepted = !letThrough; }
+ onDoubleClicked: function (mouse) { mouse.accepted = !letThrough; }
+ onPressAndHold: function (mouse) { mouse.accepted = !letThrough; }
}
}
diff --git a/tests/auto/quick/qquickmousearea/data/containsMouseAndHoverDisabled.qml b/tests/auto/quick/qquickmousearea/data/containsMouseAndHoverDisabled.qml
new file mode 100644
index 0000000000..d98ef85c55
--- /dev/null
+++ b/tests/auto/quick/qquickmousearea/data/containsMouseAndHoverDisabled.qml
@@ -0,0 +1,15 @@
+import QtQuick
+
+Rectangle {
+ width: 200
+ height: 200
+ visible: true
+ MouseArea {
+ id: mouseArea
+ objectName: "mouseArea"
+ anchors.fill: parent
+ hoverEnabled: false
+ onPressed: function(mouse) { mouse.accepted = false }
+ }
+}
+
diff --git a/tests/auto/quick/qquickmousearea/data/cursorUpdating.qml b/tests/auto/quick/qquickmousearea/data/cursorUpdating.qml
new file mode 100644
index 0000000000..2d06543c78
--- /dev/null
+++ b/tests/auto/quick/qquickmousearea/data/cursorUpdating.qml
@@ -0,0 +1,71 @@
+import QtQuick
+
+Item {
+ width: 600
+ height: 600
+
+ ListModel {
+ id: cursorsModel
+ ListElement { cursorShape: Qt.ArrowCursor; text: "Arrow" }
+ ListElement { cursorShape: Qt.UpArrowCursor; text: "UpArrow" }
+ ListElement { cursorShape: Qt.CrossCursor; text: "Cross" }
+ ListElement { cursorShape: Qt.WaitCursor; text: "Wait" }
+ ListElement { cursorShape: Qt.IBeamCursor; text: "IBeam" }
+ ListElement { cursorShape: Qt.SizeVerCursor; text: "SizeVer" }
+ ListElement { cursorShape: Qt.SizeHorCursor; text: "SizeHor" }
+ ListElement { cursorShape: Qt.SizeBDiagCursor; text: "SizeBDiag" }
+ ListElement { cursorShape: Qt.SizeFDiagCursor; text: "SizeFDiag" }
+ ListElement { cursorShape: Qt.SizeAllCursor; text: "SizeAll" }
+ ListElement { cursorShape: Qt.BlankCursor; text: "Blank" }
+ ListElement { cursorShape: Qt.SplitVCursor; text: "SplitV" }
+ ListElement { cursorShape: Qt.SplitHCursor; text: "SplitH" }
+ ListElement { cursorShape: Qt.PointingHandCursor; text: "PointingHand" }
+ ListElement { cursorShape: Qt.ForbiddenCursor; text: "Forbidden" }
+ ListElement { cursorShape: Qt.WhatsThisCursor; text: "WhatsThis" }
+ ListElement { cursorShape: Qt.BusyCursor; text: "Busy" }
+ ListElement { cursorShape: Qt.OpenHandCursor; text: "OpenHand" }
+ ListElement { cursorShape: Qt.ClosedHandCursor; text: "ClosedHand" }
+ ListElement { cursorShape: Qt.DragCopyCursor; text: "DragCopy" }
+ ListElement { cursorShape: Qt.DragMoveCursor; text: "DragMove" }
+ ListElement { cursorShape: Qt.DragLinkCursor; text: "DragLink" }
+ }
+
+ Flickable {
+ anchors.fill: parent
+ contentHeight: flow.height
+ Flow {
+ id: flow
+ width: parent.width
+ Repeater {
+ model: cursorsModel
+ Rectangle {
+ id: root
+ color: "white"
+ border.width: 5
+ border.color: "black"
+
+ width: 200
+ height: 200
+
+ Text {
+ id: textItem
+ anchors.fill: parent
+ anchors.margins: parent.width * 0.1
+ text: model.text
+ fontSizeMode: Text.Fit
+ minimumPixelSize: 10; font.pixelSize: height
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: model.cursorShape
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickmousearea/data/hoverAfterPress.qml b/tests/auto/quick/qquickmousearea/data/hoverAfterPress.qml
index 69ec8fbd47..97512d1106 100644
--- a/tests/auto/quick/qquickmousearea/data/hoverAfterPress.qml
+++ b/tests/auto/quick/qquickmousearea/data/hoverAfterPress.qml
@@ -16,7 +16,7 @@ Item {
objectName: "mouseArea"
anchors.fill: parent
hoverEnabled: true
- onPressed: mouse.accepted = false
+ onPressed: function (mouse) { mouse.accepted = false }
//onContainsMouseChanged: print("containsMouse changed =", containsMouse)
Rectangle {
diff --git a/tests/auto/quick/qquickmousearea/data/ignoreBySource.qml b/tests/auto/quick/qquickmousearea/data/ignoreBySource.qml
index a53cbf7b1d..bb20a317f7 100644
--- a/tests/auto/quick/qquickmousearea/data/ignoreBySource.qml
+++ b/tests/auto/quick/qquickmousearea/data/ignoreBySource.qml
@@ -21,7 +21,7 @@ Item {
MouseArea {
id: ma
objectName: "mousearea"
- onPressed: {
+ onPressed: function (mouse) {
root.lastEventSource = mouse.source
if (mouse.source !== root.allowedSource)
mouse.accepted = false
diff --git a/tests/auto/quick/qquickmousearea/data/mask.qml b/tests/auto/quick/qquickmousearea/data/mask.qml
index 1e8ae7c98a..ab8ecbf32d 100644
--- a/tests/auto/quick/qquickmousearea/data/mask.qml
+++ b/tests/auto/quick/qquickmousearea/data/mask.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 Ford Motor Company
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.11
import Test 1.0
diff --git a/tests/auto/quick/qquickmousearea/data/moveAndReleaseWithoutPress.qml b/tests/auto/quick/qquickmousearea/data/moveAndReleaseWithoutPress.qml
index 6c68f0c7c8..4b7324a98a 100644
--- a/tests/auto/quick/qquickmousearea/data/moveAndReleaseWithoutPress.qml
+++ b/tests/auto/quick/qquickmousearea/data/moveAndReleaseWithoutPress.qml
@@ -7,7 +7,7 @@ MouseArea {
property bool hadMove: false
property bool hadRelease: false
- onPressed: mouse.accepted = false
+ onPressed: function (mouse) { mouse.accepted = false }
onPositionChanged: hadMove = true
onReleased: hadRelease = true
}
diff --git a/tests/auto/quick/qquickmousearea/data/qtbug34368.qml b/tests/auto/quick/qquickmousearea/data/qtbug34368.qml
index 42d8ddd3b6..96e72a8edc 100644
--- a/tests/auto/quick/qquickmousearea/data/qtbug34368.qml
+++ b/tests/auto/quick/qquickmousearea/data/qtbug34368.qml
@@ -12,7 +12,7 @@ Rectangle {
anchors.fill: parent
propagateComposedEvents: true
z: 1
- onClicked: {
+ onClicked: function (mouse) {
mouse.accepted = false;
clicksEnabled += 1;
//console.log("Upper click");
@@ -23,7 +23,7 @@ Rectangle {
propagateComposedEvents: true
z: 0
enabled: !disableLower
- onClicked: {
+ onClicked: function (mouse) {
mouse.accepted = false;
clicksDisabled += 1;
//console.log("Lower click");
diff --git a/tests/auto/quick/qquickmousearea/data/qtbug49100.qml b/tests/auto/quick/qquickmousearea/data/qtbug49100.qml
index 39b293c8fa..d3dfe64d94 100644
--- a/tests/auto/quick/qquickmousearea/data/qtbug49100.qml
+++ b/tests/auto/quick/qquickmousearea/data/qtbug49100.qml
@@ -8,7 +8,7 @@ ListView {
delegate: Text {
text: index + 1
height: 30
- width: parent.width
+ width: ListView.view.width
MouseArea {
anchors.fill: parent
}
diff --git a/tests/auto/quick/qquickmousearea/data/rejectEvent.qml b/tests/auto/quick/qquickmousearea/data/rejectEvent.qml
index 48b68ee845..03a075300a 100644
--- a/tests/auto/quick/qquickmousearea/data/rejectEvent.qml
+++ b/tests/auto/quick/qquickmousearea/data/rejectEvent.qml
@@ -23,7 +23,7 @@ Rectangle {
id: mouseRegion2
objectName: "mouseRegion2"
width: 120; height: 120
- onPressed: { root.mr2_pressed = true; mouse.accepted = false }
+ onPressed: function (mouse) { root.mr2_pressed = true; mouse.accepted = false }
onReleased: { root.mr2_released = true }
onCanceled: { root.mr2_canceled = true }
}
diff --git a/tests/auto/quick/qquickmousearea/data/updateMousePosOnResize.qml b/tests/auto/quick/qquickmousearea/data/updateMousePosOnResize.qml
index 55af864060..a20f752864 100644
--- a/tests/auto/quick/qquickmousearea/data/updateMousePosOnResize.qml
+++ b/tests/auto/quick/qquickmousearea/data/updateMousePosOnResize.qml
@@ -22,19 +22,19 @@ Rectangle {
property bool mouseMatchesPos: true
anchors.fill: brother
- onPressed: {
+ onPressed: function (mouse) {
if (mouse.x != mouseX || mouse.y != mouseY)
mouseMatchesPos = false
x1 = mouseX; y1 = mouseY
anchors.fill = parent
}
onPositionChanged: { emitPositionChanged = true }
- onMouseXChanged: {
+ onMouseXChanged: function (mouse) {
if (mouse.x != mouseX || mouse.y != mouseY)
mouseMatchesPos = false
x2 = mouseX; y2 = mouseY
}
- onMouseYChanged: {
+ onMouseYChanged: function (mouse) {
if (mouse.x != mouseX || mouse.y != mouseY)
mouseMatchesPos = false
x2 = mouseX; y2 = mouseY
diff --git a/tests/auto/quick/qquickmousearea/data/wheel.qml b/tests/auto/quick/qquickmousearea/data/wheel.qml
index 3e0c0c2a48..6cd367b22f 100644
--- a/tests/auto/quick/qquickmousearea/data/wheel.qml
+++ b/tests/auto/quick/qquickmousearea/data/wheel.qml
@@ -14,7 +14,7 @@ Rectangle {
MouseArea {
anchors.fill: parent
- onWheel: {
+ onWheel: function (wheel) {
root.angleDeltaY = wheel.angleDelta.y;
root.mouseX = wheel.x;
root.mouseY = wheel.y;
diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
index fd2b442a63..37d8c910f5 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
@@ -23,6 +23,11 @@
Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
+static bool isPlatformWayland()
+{
+ return !QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive);
+}
+
class CircleMask : public QObject
{
Q_OBJECT
@@ -95,6 +100,7 @@ private slots:
void pressedCanceledOnWindowDeactivate();
void doubleClick_data() { acceptedButton_data(); }
void doubleClick();
+ void doubleTap();
void clickTwice_data() { acceptedButton_data(); }
void clickTwice();
void invalidClick_data() { rejectedButton_data(); }
@@ -120,6 +126,7 @@ private slots:
void changeAxis();
#if QT_CONFIG(cursor)
void cursorShape();
+ void cursorUpdating();
#endif
void moveAndReleaseWithoutPress();
void nestedStopAtBounds();
@@ -139,6 +146,7 @@ private slots:
void negativeZStackingOrder();
void containsMouseAndVisibility();
void containsMouseAndVisibilityMasked();
+ void containsMouseAndHoverDisabled();
void doubleClickToHide();
void releaseFirstTouchAfterSecond();
#if QT_CONFIG(tabletevent)
@@ -933,6 +941,61 @@ void tst_QQuickMouseArea::doubleClick()
QCOMPARE(window.rootObject()->property("released").toInt(), 2);
}
+void tst_QQuickMouseArea::doubleTap() // QTBUG-112434
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("doubleclick.qml")));
+
+ QQuickMouseArea *mouseArea = window.rootObject()->findChild<QQuickMouseArea *>("mousearea");
+ QVERIFY(mouseArea);
+ QPoint p1 = mouseArea->mapToScene(mouseArea->boundingRect().center()).toPoint();
+
+ QTest::touchEvent(&window, device).press(0, p1);
+ QQuickTouchUtils::flush(&window);
+ QTest::touchEvent(&window, device).release(0, p1);
+ QQuickTouchUtils::flush(&window);
+ QCOMPARE(window.rootObject()->property("released").toInt(), 1);
+ QCOMPARE(window.rootObject()->property("clicked").toInt(), 1);
+
+ p1 += QPoint(1, -1); // movement less than QPlatformTheme::TouchDoubleTapDistance
+ QTest::touchEvent(&window, device).press(1, p1); // touchpoint ID is different the second time
+ QQuickTouchUtils::flush(&window);
+ QCOMPARE(mouseArea->isPressed(), true);
+ // at this time QQuickDeliveryAgentPrivate::deliverTouchAsMouse() synthesizes the double-click event
+ QCOMPARE(window.rootObject()->property("doubleClicked").toInt(), 1);
+
+ QTest::touchEvent(&window, device).release(1, p1);
+ QQuickTouchUtils::flush(&window);
+ QCOMPARE(window.rootObject()->property("released").toInt(), 2);
+ QCOMPARE(mouseArea->isPressed(), false);
+ QCOMPARE(window.rootObject()->property("clicked").toInt(), 1);
+
+ // now tap with two fingers simultaneously: only one of them generates synth-mouse
+ QPoint p2 = p1 + QPoint(50, 5);
+ QTest::touchEvent(&window, device).press(2, p1).press(3, p2);
+ QQuickTouchUtils::flush(&window);
+ QCOMPARE(mouseArea->isPressed(), true);
+ QTest::touchEvent(&window, device).release(2, p1).release(3, p2);
+ QQuickTouchUtils::flush(&window);
+ QCOMPARE(window.rootObject()->property("released").toInt(), 3);
+ QCOMPARE(window.rootObject()->property("clicked").toInt(), 2);
+ QCOMPARE(window.rootObject()->property("doubleClicked").toInt(), 1);
+ QCOMPARE(mouseArea->isPressed(), false);
+
+ // tap with two fingers simultaneously again: get another double-click from one point
+ p1 -= QPoint(1, -1);
+ p2 += QPoint(1, -1);
+ QTest::touchEvent(&window, device).press(4, p1).press(5, p2);
+ QQuickTouchUtils::flush(&window);
+ QCOMPARE(mouseArea->isPressed(), true);
+ QTest::touchEvent(&window, device).release(4, p1).release(5, p2);
+ QQuickTouchUtils::flush(&window);
+ QCOMPARE(window.rootObject()->property("released").toInt(), 4);
+ QCOMPARE(window.rootObject()->property("clicked").toInt(), 2);
+ QCOMPARE(window.rootObject()->property("doubleClicked").toInt(), 2);
+ QCOMPARE(mouseArea->isPressed(), false); // make sure it doesn't get stuck
+}
+
// QTBUG-14832
void tst_QQuickMouseArea::clickTwice()
{
@@ -1563,11 +1626,11 @@ void tst_QQuickMouseArea::disableParentOnPress() // QTBUG-39806 and QTBUG-103788
QQuickTest::pointerPress(device, &window, 0, p);
QTRY_COMPARE(parentEnabledSpy.size(), 1);
- QCOMPARE(root->isEnabled(), false);
- QCOMPARE(mouseArea->isEnabled(), true); // enabled is independent, unfortunately (inverse of QTBUG-38364)
- QCOMPARE(QQuickItemPrivate::get(mouseArea)->effectiveEnable, false);
+ QVERIFY(!root->isEnabled());
+ QVERIFY(mouseArea->isEnabled()); // enabled is independent, unfortunately (inverse of QTBUG-38364)
+ QVERIFY(!QQuickItemPrivate::get(mouseArea)->effectiveEnable);
// bug fix: it knows it got effectively disabled, so now it's no longer pressed
- QCOMPARE(mouseArea->isPressed(), false);
+ QVERIFY(!mouseArea->isPressed());
QCOMPARE(canceledSpy.size(), 1); // ...because the press was canceled
QCOMPARE(pressedChangedSpy.size(), 2); // kerchunk
QQuickTest::pointerRelease(device, &window, 0, p);
@@ -1575,9 +1638,9 @@ void tst_QQuickMouseArea::disableParentOnPress() // QTBUG-39806 and QTBUG-103788
// now re-enable it and try again
root->setEnabled(true);
QQuickTest::pointerPress(device, &window, 0, p);
- QTRY_COMPARE(root->isEnabled(), false);
- QCOMPARE(QQuickItemPrivate::get(mouseArea)->effectiveEnable, false);
- QCOMPARE(mouseArea->isPressed(), false);
+ QTRY_VERIFY(!root->isEnabled());
+ QVERIFY(!QQuickItemPrivate::get(mouseArea)->effectiveEnable);
+ QVERIFY(!mouseArea->isPressed());
QCOMPARE(canceledSpy.size(), 2);
QCOMPARE(pressedChangedSpy.size(), 4);
QQuickTest::pointerRelease(device, &window, 0, p);
@@ -1844,6 +1907,38 @@ void tst_QQuickMouseArea::cursorShape()
QCOMPARE(mouseArea->cursor().shape(), Qt::WaitCursor);
QCOMPARE(spy.size(), 2);
}
+
+void tst_QQuickMouseArea::cursorUpdating()
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("cursorUpdating.qml")));
+ QQuickItem *root = window.rootObject();
+ QVERIFY(root);
+ QQuickFlickable *flickable = root->findChild<QQuickFlickable*>();
+ QVERIFY(flickable);
+ QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(root);
+ QVERIFY(rootPrivate->subtreeCursorEnabled);
+
+ QTest::mouseMove(&window, QPoint(40, 40));
+ QCOMPARE(window.cursor().shape(), Qt::ArrowCursor);
+
+ QTest::mouseMove(&window, QPoint(240, 40));
+ QCOMPARE(window.cursor().shape(), Qt::UpArrowCursor);
+
+ if (isPlatformWayland())
+ QSKIP("Wayland: QCursor::setPos() doesn't work.");
+
+ // QTBUG-53987: with the cursor physically hovering, use wheel to
+ // position a different item that requests a different cursor
+ const QPoint p(240, 40);
+ const QPoint pg = window.mapToGlobal(p);
+ QCursor::setPos(pg);
+ QWheelEvent wheelEvent(p, pg, QPoint(60, -400), QPoint(0, -600),
+ Qt::NoButton, Qt::ControlModifier, Qt::NoScrollPhase, false);
+ QGuiApplication::sendEvent(&window, &wheelEvent);
+ QTRY_VERIFY(flickable->contentY() > 300);
+ QCOMPARE(window.cursor().shape(), Qt::IBeamCursor);
+}
#endif
void tst_QQuickMouseArea::moveAndReleaseWithoutPress()
@@ -2508,6 +2603,20 @@ void tst_QQuickMouseArea::containsMouseAndVisibilityMasked()
QTRY_VERIFY(!mouseArea2->hovered());
}
+// QTBUG-110594
+void tst_QQuickMouseArea::containsMouseAndHoverDisabled()
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("containsMouseAndHoverDisabled.qml")));
+
+ QQuickMouseArea *mouseArea = window.rootObject()->findChild<QQuickMouseArea *>("mouseArea");
+ QVERIFY(mouseArea != nullptr);
+ QVERIFY(!mouseArea->hoverEnabled());
+
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100, 100));
+ QTRY_VERIFY(!mouseArea->hovered());
+}
+
// QTBUG-35995 and QTBUG-102158
void tst_QQuickMouseArea::doubleClickToHide()
{
diff --git a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
index 2488eff270..c79f4b6a29 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
+++ b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
@@ -4,3 +4,7 @@ ubuntu-22.04
[nested]
ubuntu-20.04
ubuntu-22.04
+
+# QTBUG-118065
+[mouseGestureStarted]
+opensuse-leap
diff --git a/tests/auto/quick/qquickmultipointtoucharea/CMakeLists.txt b/tests/auto/quick/qquickmultipointtoucharea/CMakeLists.txt
index 38e91d5683..277df556cc 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/CMakeLists.txt
+++ b/tests/auto/quick/qquickmultipointtoucharea/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickmultipointtoucharea Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickmultipointtoucharea LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/cancel.qml b/tests/auto/quick/qquickmultipointtoucharea/data/cancel.qml
index e108003bca..493257ac7e 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/data/cancel.qml
+++ b/tests/auto/quick/qquickmultipointtoucharea/data/cancel.qml
@@ -30,12 +30,12 @@ MultiPointTouchArea {
property int touchCount: 0
property bool touchUpdatedHandled: false
- onPressed: { touchPointPressCount = touchPoints.length }
- onUpdated: { touchPointUpdateCount = touchPoints.length }
- onReleased: { touchPointReleaseCount = touchPoints.length }
- onCanceled: { touchPointCancelCount = touchPoints.length }
- onTouchUpdated: {
- touchCount = touchPoints.length
+ onPressed: (points) => { touchPointPressCount = points.length }
+ onUpdated: (points) => { touchPointUpdateCount = points.length }
+ onReleased: (points) => { touchPointReleaseCount = v.length }
+ onCanceled: (points) => { touchPointCancelCount = points.length }
+ onTouchUpdated: (points) => {
+ touchCount = points.length
touchUpdatedHandled = true
}
}
diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/inFlickable.qml b/tests/auto/quick/qquickmultipointtoucharea/data/inFlickable.qml
index 32733613b3..e03ad43816 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/data/inFlickable.qml
+++ b/tests/auto/quick/qquickmultipointtoucharea/data/inFlickable.qml
@@ -32,7 +32,7 @@ Rectangle {
anchors.fill: parent
minimumTouchPoints: 2
maximumTouchPoints: 2
- onGestureStarted: {
+ onGestureStarted: (gesture) => {
if ((Math.abs(point2.x - point2.startX) > gesture.dragThreshold/2) &&
(Math.abs(point1.x - point1.startX) > gesture.dragThreshold/2)) {
gesture.grab()
@@ -43,8 +43,8 @@ Rectangle {
TouchPoint { id: point2; objectName: "point2" }
]
- onCanceled: root.cancelCount = touchPoints.length
- onTouchUpdated: root.touchCount = touchPoints.length
+ onCanceled: (touchPoints) => root.cancelCount = touchPoints.length
+ onTouchUpdated: (touchPoints) => root.touchCount = touchPoints.length
Text {
text: "â‘ "
diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml b/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml
index b0410dac4a..6b9dd5b7c7 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml
+++ b/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml
@@ -17,10 +17,10 @@ MultiPointTouchArea {
TouchPoint { objectName: "point2" }
]
- onPressed: { touchCount = touchPoints.length }
- onTouchUpdated: { touchCount = touchPoints.length }
- onCanceled: { cancelCount = touchPoints.length }
- onGestureStarted: {
+ onPressed: (points) => { touchCount = points.length }
+ onTouchUpdated: (points) => { touchCount = points.length }
+ onCanceled: (points) => { cancelCount = points.length }
+ onGestureStarted: (gesture) => {
gestureStartedX = gesture.touchPoints[0].startX
gestureStartedY = gesture.touchPoints[0].startY
if (grabGesture)
diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/nested.qml b/tests/auto/quick/qquickmultipointtoucharea/data/nested.qml
index 8ab10a6926..dca1ffa07b 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/data/nested.qml
+++ b/tests/auto/quick/qquickmultipointtoucharea/data/nested.qml
@@ -66,7 +66,7 @@ MultiPointTouchArea {
anchors.fill: parent
minimumTouchPoints: 3
maximumTouchPoints: 3
- onGestureStarted: if (grabInnerArea) gesture.grab()
+ onGestureStarted: (gesture) => { if (grabInnerArea) gesture.grab() }
touchPoints: [
TouchPoint { id: point21; objectName: "point21" },
TouchPoint { id: point22; objectName: "point22" },
diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/nestedTouchPosCheck.qml b/tests/auto/quick/qquickmultipointtoucharea/data/nestedTouchPosCheck.qml
new file mode 100644
index 0000000000..700f06a3ac
--- /dev/null
+++ b/tests/auto/quick/qquickmultipointtoucharea/data/nestedTouchPosCheck.qml
@@ -0,0 +1,52 @@
+import QtQuick
+import QtTest
+
+Item {
+ width: 300; height: 200
+ id: topLevelItem
+ MultiPointTouchArea {
+ objectName: "topMPTA"
+ anchors.fill: parent
+ Column {
+ width: parent.width
+ height: parent.height
+
+ Rectangle {
+ width: parent.width
+ height: 100
+ color: "green"
+ }
+ Rectangle {
+ id: rect
+ width: parent.width
+ height: 600
+ color: "red"
+
+ MultiPointTouchArea {
+
+ property var xPressed: 0
+ property var yPressed: 0
+ property var xReleased: 0
+ property var yReleased: 0
+
+ objectName: "bottomMPTA"
+ anchors.fill: parent
+ onPressed: (touchPoints) => {
+ for (let tp in touchPoints) {
+ let touch = touchPoints[tp]
+ xPressed = touch.x
+ yPressed = touch.y
+ }
+ }
+ onReleased: (touchPoints) => {
+ for (let tp in touchPoints) {
+ let touch = touchPoints[tp]
+ xReleased = touch.x
+ yReleased = touch.y
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/nonOverlapping.qml b/tests/auto/quick/qquickmultipointtoucharea/data/nonOverlapping.qml
index 027f90c7f4..4130bc8dde 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/data/nonOverlapping.qml
+++ b/tests/auto/quick/qquickmultipointtoucharea/data/nonOverlapping.qml
@@ -9,7 +9,7 @@ Rectangle {
height: 160
minimumTouchPoints: 2
maximumTouchPoints: 2
- onGestureStarted: gesture.grab()
+ onGestureStarted: (gesture) => gesture.grab()
touchPoints: [
TouchPoint { id: point11; objectName: "point11" },
TouchPoint { id: point12; objectName: "point12" }
@@ -34,7 +34,7 @@ Rectangle {
y: 160
minimumTouchPoints: 3
maximumTouchPoints: 3
- onGestureStarted: gesture.grab()
+ onGestureStarted: (gesture) => gesture.grab()
touchPoints: [
TouchPoint { id: point21; objectName: "point21" },
TouchPoint { id: point22; objectName: "point22" },
diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/signalTest.qml b/tests/auto/quick/qquickmultipointtoucharea/data/signalTest.qml
index 54b160c182..9ba3029193 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/data/signalTest.qml
+++ b/tests/auto/quick/qquickmultipointtoucharea/data/signalTest.qml
@@ -20,11 +20,17 @@ MultiPointTouchArea {
maximumTouchPoints: 5
- onPressed: { touchPointPressCount = touchPoints.length }
- onUpdated: { touchPointUpdateCount = touchPoints.length }
+ // recommended syntax for a signal handler
+ onPressed: (points) => { touchPointPressCount = points.length }
+
+ // one with "touchPoints" being the signal argument rather than the property
+ onUpdated: (touchPoints) => { touchPointUpdateCount = touchPoints.length }
+
+ // one without the formal parameter, to test that it still works (with a warning)
onReleased: { touchPointReleaseCount = touchPoints.length }
- onTouchUpdated: {
- touchCount = touchPoints.length
+
+ onTouchUpdated: (points) => {
+ touchCount = points.length
touchUpdatedHandled = true
}
}
diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/touchOverMouseArea.qml b/tests/auto/quick/qquickmultipointtoucharea/data/touchOverMouseArea.qml
new file mode 100644
index 0000000000..ffe3751ec3
--- /dev/null
+++ b/tests/auto/quick/qquickmultipointtoucharea/data/touchOverMouseArea.qml
@@ -0,0 +1,21 @@
+
+import QtQuick
+
+Rectangle {
+ x: 20
+ y: 20
+ width: 300
+ height: 200
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ }
+
+ MultiPointTouchArea {
+ id: touchArea
+ anchors.fill: parent
+ enabled: false
+ }
+}
diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/transformedMultiPointTouchArea.qml b/tests/auto/quick/qquickmultipointtoucharea/data/transformedMultiPointTouchArea.qml
index 296bf7996f..02985581e0 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/data/transformedMultiPointTouchArea.qml
+++ b/tests/auto/quick/qquickmultipointtoucharea/data/transformedMultiPointTouchArea.qml
@@ -19,8 +19,8 @@ Rectangle {
property int pointCount: 0
- onPressed: pointCount = touchPoints.length;
- onTouchUpdated: pointCount = touchPoints.length;
+ onPressed: (points) => pointCount = points.length;
+ onTouchUpdated: (points) => pointCount = points.length;
}
}
}
diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
index 509465b174..b233ed0232 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
+++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
@@ -19,6 +19,8 @@
Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
+using namespace Qt::StringLiterals;
+
class tst_QQuickMultiPointTouchArea : public QQmlDataTest
{
Q_OBJECT
@@ -34,6 +36,7 @@ private slots:
void reuse();
void nonOverlapping();
void nested();
+ void nestedTouchPosCheck();
void inFlickable();
void inFlickable2();
void inFlickableWithPressDelay();
@@ -50,6 +53,7 @@ private slots:
void stationaryTouchWithChangingPressure();
void touchFiltering();
void nestedPinchAreaMouse();
+ void disabledIgnoresHover();
private:
QQuickView *createAndShowView(const QString &file);
@@ -73,6 +77,12 @@ void tst_QQuickMultiPointTouchArea::properties()
void tst_QQuickMultiPointTouchArea::signalTest()
{
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ QTest::ignoreMessage(QtWarningMsg, QString(testFileUrl("signalTest.qml").toString() +
+ u":30:5 Parameter \"touchPoints\" is not declared. Injection of parameters into signal handlers "
+ "is deprecated. Use JavaScript functions with formal parameters instead."_s).toLatin1().constData());
+#endif
+
QScopedPointer<QQuickView> window(createAndShowView("signalTest.qml"));
QVERIFY(window->rootObject() != nullptr);
@@ -551,6 +561,30 @@ void tst_QQuickMultiPointTouchArea::nested()
QQuickTouchUtils::flush(window.data());
}
+
+void tst_QQuickMultiPointTouchArea::nestedTouchPosCheck()
+{
+ QScopedPointer<QQuickView> window(createAndShowView("nestedTouchPosCheck.qml"));
+ QVERIFY(window->rootObject() != nullptr);
+
+ auto *bottomMPTA = window->rootObject()->findChild<QQuickMultiPointTouchArea *>("bottomMPTA");
+ QVERIFY(bottomMPTA != nullptr);
+
+ QTest::QTouchEventSequence sequence = QTest::touchEvent(window.data(), device);
+
+ sequence.press(0, QPoint(10, 110)).commit();
+ QQuickTouchUtils::flush(window.data());
+
+ sequence.release(0, QPoint(10, 110)).commit();
+ QQuickTouchUtils::flush(window.data());
+
+ QCOMPARE(bottomMPTA->property("xPressed").toInt(), 10);
+ QCOMPARE(bottomMPTA->property("yPressed").toInt(), 10);
+ QCOMPARE(bottomMPTA->property("xReleased").toInt(), 10);
+ QCOMPARE(bottomMPTA->property("yReleased").toInt(), 10);
+
+}
+
void tst_QQuickMultiPointTouchArea::inFlickable()
{
QScopedPointer<QQuickView> window(createAndShowView("inFlickable.qml"));
@@ -571,7 +605,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
QPoint p1(20,100);
QPoint p2(40,100);
- // moving one point vertically
+ // moving one point vertically: flickable gets the grab
QTest::touchEvent(window.data(), device).press(0, p1);
QQuickTouchUtils::flush(window.data());
@@ -595,10 +629,14 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
QTRY_VERIFY(!flickable->isMoving());
- // moving two points vertically
+ // moving two points vertically: MPTAs handle them, Flickable ignores multi-touch.
+ // The stray mouse events simulate OS-level synth-from-touch, and should not interfere.
p1 = QPoint(20,100);
QTest::touchEvent(window.data(), device).press(0, p1).press(1, p2);
- QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, p1);
+ QWindowSystemInterface::handleMouseEvent(window.data(), device, p1, window->mapToGlobal(p1),
+ Qt::LeftButton, Qt::LeftButton, QEvent::MouseButtonPress,
+ Qt::NoModifier, Qt::MouseEventSynthesizedBySystem);
+ qApp->processEvents();
QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
@@ -611,20 +649,26 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
QTest::qWait(250);
p1 += delta; p2 += delta;
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
- QTest::mouseMove(window.data(), p1);
+ QWindowSystemInterface::handleMouseEvent(window.data(), device, p1, window->mapToGlobal(p1),
+ Qt::LeftButton, Qt::NoButton, QEvent::MouseMove,
+ Qt::NoModifier, Qt::MouseEventSynthesizedBySystem);
+ qApp->processEvents();
QQuickTouchUtils::flush(window.data());
qCDebug(lcTests, "after drags %d to %d,%d and %d,%d contentY is %lf",
i, p1.x(), p1.y(), p2.x(), p2.y(), flickable->contentY());
}
- QVERIFY(flickable->contentY() < 0);
- QCOMPARE(point11->pressed(), false);
- QCOMPARE(point12->pressed(), false);
- QCOMPARE(window->rootObject()->property("cancelCount").toInt(), 2);
- QCOMPARE(window->rootObject()->property("touchCount").toInt(), 0);
+ QCOMPARE(flickable->contentY(), 0);
+ QCOMPARE(point11->pressed(), true);
+ QCOMPARE(point12->pressed(), true);
+ QCOMPARE(window->rootObject()->property("cancelCount").toInt(), 0);
+ QCOMPARE(window->rootObject()->property("touchCount").toInt(), 2);
QTest::touchEvent(window.data(), device).release(0, p1).release(1, p2);
- QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, p1);
+ QWindowSystemInterface::handleMouseEvent(window.data(), device, p1, window->mapToGlobal(p1),
+ Qt::NoButton, Qt::LeftButton, QEvent::MouseButtonRelease,
+ Qt::NoModifier, Qt::MouseEventSynthesizedBySystem);
+ qApp->processEvents();
QQuickTouchUtils::flush(window.data());
QTRY_VERIFY(!flickable->isMoving());
@@ -634,10 +678,15 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
p2 = QPoint(40,100);
QTest::touchEvent(window.data(), device).press(0, p1).press(1, p2);
QQuickTouchUtils::flush(window.data());
+ QCOMPARE(point11->pressed(), true);
+ QCOMPARE(point12->pressed(), true);
// ensure that mouse events do not fall through to the Flickable
mpta->setMaximumTouchPoints(3);
mpta->setAcceptedMouseButtons(Qt::LeftButton);
- QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, p1);
+ QWindowSystemInterface::handleMouseEvent(window.data(), device, p1, window->mapToGlobal(p1),
+ Qt::LeftButton, Qt::LeftButton, QEvent::MouseButtonPress,
+ Qt::NoModifier, Qt::MouseEventSynthesizedBySystem);
+ qApp->processEvents();
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -650,32 +699,40 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
delta = QPoint(0, 15);
p1 += delta; p2 += delta;
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
- QTest::mouseMove(window.data(), p1);
+ QWindowSystemInterface::handleMouseEvent(window.data(), device, p1, window->mapToGlobal(p1),
+ Qt::LeftButton, Qt::NoButton, QEvent::MouseMove,
+ Qt::NoModifier, Qt::MouseEventSynthesizedBySystem);
+ qApp->processEvents();
QQuickTouchUtils::flush(window.data());
qCDebug(lcTests, "after drags %d to %d,%d and %d,%d contentY is %lf",
i, p1.x(), p1.y(), p2.x(), p2.y(), flickable->contentY());
}
- QEXPECT_FAIL("", "currently flickable does grab the actual mouse", Continue);
QCOMPARE(flickable->contentY(), qreal(0));
QCOMPARE(point11->pressed(), true);
- QEXPECT_FAIL("", "currently flickable does grab the actual mouse", Continue);
QCOMPARE(point12->pressed(), true);
QTest::touchEvent(window.data(), device).release(0, p1).release(1, p2);
- QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, p1);
+ QWindowSystemInterface::handleMouseEvent(window.data(), device, p1, window->mapToGlobal(p1),
+ Qt::NoButton, Qt::LeftButton, QEvent::MouseButtonRelease,
+ Qt::NoModifier, Qt::MouseEventSynthesizedBySystem);
+ qApp->processEvents();
QQuickTouchUtils::flush(window.data());
}
// test that dragging out of a Flickable containing a MPTA doesn't harm Flickable's state.
void tst_QQuickMultiPointTouchArea::inFlickable2()
{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
QScopedPointer<QQuickView> window(createAndShowView("inFlickable2.qml"));
QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
QVERIFY(flickable != nullptr);
+ QQuickMultiPointTouchArea *mpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>();
+ QVERIFY(mpta);
+
QQuickTouchPoint *point11 = window->rootObject()->findChild<QQuickTouchPoint*>("point1");
QVERIFY(point11);
@@ -688,25 +745,12 @@ void tst_QQuickMultiPointTouchArea::inFlickable2()
QQuickTouchUtils::flush(window.data());
QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, p1);
- p1 += QPoint(15,0);
- QTest::touchEvent(window.data(), device).move(0, p1);
- QQuickTouchUtils::flush(window.data());
- QTest::mouseMove(window.data(), p1);
-
- p1 += QPoint(15,0);
- QTest::touchEvent(window.data(), device).move(0, p1);
- QQuickTouchUtils::flush(window.data());
- QTest::mouseMove(window.data(), p1);
-
- p1 += QPoint(15,0);
- QTest::touchEvent(window.data(), device).move(0, p1);
- QQuickTouchUtils::flush(window.data());
- QTest::mouseMove(window.data(), p1);
-
- p1 += QPoint(15,0);
- QTest::touchEvent(window.data(), device).move(0, p1);
- QQuickTouchUtils::flush(window.data());
- QTest::mouseMove(window.data(), p1);
+ for (int i = 0; i < 4; ++i) {
+ p1 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
+ QTest::mouseMove(window.data(), p1);
+ }
QVERIFY(!flickable->isMoving());
QVERIFY(point11->pressed());
@@ -719,27 +763,21 @@ void tst_QQuickMultiPointTouchArea::inFlickable2()
QTRY_VERIFY(!flickable->isMoving());
// Check that we can still move the Flickable
+ QSignalSpy gestureStartedSpy(mpta, &QQuickMultiPointTouchArea::gestureStarted);
p1 = QPoint(50,100);
QTest::touchEvent(window.data(), device).press(0, p1);
QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
- p1 += QPoint(0,15);
- QTest::touchEvent(window.data(), device).move(0, p1);
- QQuickTouchUtils::flush(window.data());
-
- p1 += QPoint(0,15);
- QTest::touchEvent(window.data(), device).move(0, p1);
- QQuickTouchUtils::flush(window.data());
-
- p1 += QPoint(0,15);
- QTest::touchEvent(window.data(), device).move(0, p1);
- QQuickTouchUtils::flush(window.data());
-
- p1 += QPoint(0,15);
- QTest::touchEvent(window.data(), device).move(0, p1);
- QQuickTouchUtils::flush(window.data());
+ for (int i = 0; i < 4; ++i) {
+ p1 += QPoint(0, dragThreshold);
+ QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
+ // QTBUG-113653: gestureStarted is emitted when touch delta exceeds drag threshold,
+ // regardless of the filtering Flickable parent
+ QCOMPARE(gestureStartedSpy.size(), i > 0 ? 1 : 0);
+ }
QVERIFY(flickable->contentY() < 0);
QVERIFY(flickable->isMoving());
@@ -1239,7 +1277,7 @@ void tst_QQuickMultiPointTouchArea::mouseGestureStarted() // QTBUG-70258
area->setProperty("grabGesture", grabGesture);
QQuickTouchPoint *point1 = view->rootObject()->findChild<QQuickTouchPoint*>("point1");
QCOMPARE(point1->pressed(), false);
- QSignalSpy gestureStartedSpy(area, SIGNAL(gestureStarted(QQuickGrabGestureEvent *)));
+ QSignalSpy gestureStartedSpy(area, SIGNAL(gestureStarted(QQuickGrabGestureEvent*)));
QPoint p1 = QPoint(distanceFromOrigin, distanceFromOrigin);
QTest::mousePress(view.data(), Qt::LeftButton, Qt::NoModifier, p1);
@@ -1420,6 +1458,23 @@ void tst_QQuickMultiPointTouchArea::nestedPinchAreaMouse() // QTBUG-83662
QCOMPARE(mpta->property("releasedCount").toInt(), 1);
}
+/*
+ A disabled MultiPointTouchArea should not interfere with hover event
+ propagation to siblings underneath.
+*/
+void tst_QQuickMultiPointTouchArea::disabledIgnoresHover()
+{
+ QScopedPointer<QQuickView> window(createAndShowView("touchOverMouseArea.qml"));
+ QQuickItem *root = qobject_cast<QQuickItem *>(window->rootObject());
+ QVERIFY(root);
+
+ QQuickMouseArea *mouseArea = root->findChild<QQuickMouseArea *>();
+
+ QTest::mouseMove(window.data(), QPoint(40, 40));
+ QTest::mouseMove(window.data(), QPoint(50, 50));
+ QVERIFY(mouseArea->hovered());
+}
+
QTEST_MAIN(tst_QQuickMultiPointTouchArea)
#include "tst_qquickmultipointtoucharea.moc"
diff --git a/tests/auto/quick/qquickpainteditem/CMakeLists.txt b/tests/auto/quick/qquickpainteditem/CMakeLists.txt
index 01978dec5b..ef92df98e3 100644
--- a/tests/auto/quick/qquickpainteditem/CMakeLists.txt
+++ b/tests/auto/quick/qquickpainteditem/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickpainteditem Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpainteditem LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qquickpainteditem
SOURCES
tst_qquickpainteditem.cpp
diff --git a/tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp b/tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp
index 56ebfdbd48..eca935c258 100644
--- a/tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp
+++ b/tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
@@ -40,12 +40,14 @@ public:
: QQuickPaintedItem(parent)
, paintNode(nullptr)
, paintRequests(0)
+ , painterHadAA(false)
{
}
void paint(QPainter *painter) override
{
++paintRequests;
+ painterHadAA = painter->testRenderHint(QPainter::Antialiasing);
clipRect = painter->clipBoundingRect();
}
#if QT_CONFIG(opengl)
@@ -66,9 +68,12 @@ public:
QSGSoftwarePainterNode *paintNode;
#endif
int paintRequests;
+ bool painterHadAA;
QRectF clipRect;
};
+static bool hasDirtyAAFlag(QQuickItem *item) {
+ return QQuickItemPrivate::get(item)->dirtyAttributes & QQuickItemPrivate::Antialiasing; }
static bool hasDirtyContentFlag(QQuickItem *item) {
return QQuickItemPrivate::get(item)->dirtyAttributes & QQuickItemPrivate::Content; }
static void clearDirtyContentFlag(QQuickItem *item) {
@@ -167,32 +172,35 @@ void tst_QQuickPaintedItem::antialiasing()
item.setAntialiasing(false);
QCOMPARE(item.antialiasing(), false);
- QCOMPARE(hasDirtyContentFlag(&item), false);
+ QCOMPARE(hasDirtyAAFlag(&item), false);
item.update();
QTRY_COMPARE(hasDirtyContentFlag(&item), false);
QVERIFY(item.paintNode);
QCOMPARE(item.paintNode->smoothPainting(), false);
+ QCOMPARE(item.painterHadAA, false);
item.setAntialiasing(true);
QCOMPARE(item.antialiasing(), true);
- QCOMPARE(hasDirtyContentFlag(&item), true);
+ QCOMPARE(hasDirtyAAFlag(&item), true);
- QTRY_COMPARE(hasDirtyContentFlag(&item), false);
+ QTRY_COMPARE(hasDirtyAAFlag(&item), false);
QVERIFY(item.paintNode);
QCOMPARE(item.paintNode->smoothPainting(), true);
+ QCOMPARE(item.painterHadAA, true);
item.setAntialiasing(true);
QCOMPARE(item.antialiasing(), true);
- QCOMPARE(hasDirtyContentFlag(&item), false);
+ QCOMPARE(hasDirtyAAFlag(&item), false);
item.setAntialiasing(false);
QCOMPARE(item.antialiasing(), false);
- QCOMPARE(hasDirtyContentFlag(&item), true);
+ QCOMPARE(hasDirtyAAFlag(&item), true);
- QTRY_COMPARE(hasDirtyContentFlag(&item), false);
+ QTRY_COMPARE(hasDirtyAAFlag(&item), false);
QVERIFY(item.paintNode);
QCOMPARE(item.paintNode->smoothPainting(), false);
+ QCOMPARE(item.painterHadAA, false);
}
void tst_QQuickPaintedItem::mipmap()
diff --git a/tests/auto/quick/qquickpalette/CMakeLists.txt b/tests/auto/quick/qquickpalette/CMakeLists.txt
index 4e61f6b3b5..c938212d28 100644
--- a/tests/auto/quick/qquickpalette/CMakeLists.txt
+++ b/tests/auto/quick/qquickpalette/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpalette LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickpalette/data/palette-item-custom.qml b/tests/auto/quick/qquickpalette/data/palette-item-custom.qml
index 1e90b71b0a..a7a3a1d0b8 100644
--- a/tests/auto/quick/qquickpalette/data/palette-item-custom.qml
+++ b/tests/auto/quick/qquickpalette/data/palette-item-custom.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/qquickpalette/data/palette-item-default.qml b/tests/auto/quick/qquickpalette/data/palette-item-default.qml
index b6cc0a0656..3d60a51195 100644
--- a/tests/auto/quick/qquickpalette/data/palette-item-default.qml
+++ b/tests/auto/quick/qquickpalette/data/palette-item-default.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/qquickpalette/data/palette-window-custom.qml b/tests/auto/quick/qquickpalette/data/palette-window-custom.qml
index b92fe6f374..60bed45405 100644
--- a/tests/auto/quick/qquickpalette/data/palette-window-custom.qml
+++ b/tests/auto/quick/qquickpalette/data/palette-window-custom.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick.Window
diff --git a/tests/auto/quick/qquickpalette/data/palette-window-default.qml b/tests/auto/quick/qquickpalette/data/palette-window-default.qml
index e6a1c81033..cd0036ac64 100644
--- a/tests/auto/quick/qquickpalette/data/palette-window-default.qml
+++ b/tests/auto/quick/qquickpalette/data/palette-window-default.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick.Window
diff --git a/tests/auto/quick/qquickpalette/tst_qquickpalette.cpp b/tests/auto/quick/qquickpalette/tst_qquickpalette.cpp
index 53fa22dba5..7b7eace30b 100644
--- a/tests/auto/quick/qquickpalette/tst_qquickpalette.cpp
+++ b/tests/auto/quick/qquickpalette/tst_qquickpalette.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/QSignalSpy>
diff --git a/tests/auto/quick/qquickpath/CMakeLists.txt b/tests/auto/quick/qquickpath/CMakeLists.txt
index 40de1ce38d..80c6ed9980 100644
--- a/tests/auto/quick/qquickpath/CMakeLists.txt
+++ b/tests/auto/quick/qquickpath/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickpath Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpath LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickpath/tst_qquickpath.cpp b/tests/auto/quick/qquickpath/tst_qquickpath.cpp
index 2c21fe39df..3e02f63ea5 100644
--- a/tests/auto/quick/qquickpath/tst_qquickpath.cpp
+++ b/tests/auto/quick/qquickpath/tst_qquickpath.cpp
@@ -1,10 +1,11 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQuick/private/qquickpath_p.h>
+#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -21,6 +22,9 @@ private slots:
void closedCatmullRomCurve();
void svg();
void line();
+ void rectangle_data();
+ void rectangle();
+ void rectangleRadii();
private:
void arc(QSizeF scale);
@@ -29,6 +33,7 @@ private:
void closedCatmullRomCurve(QSizeF scale, const QVector<QPointF> &points);
void svg(QSizeF scale);
void line(QSizeF scale);
+ void rectangle(const QQuickPath *path, const QRectF &rect);
};
static void compare(const QPointF &point, const QSizeF &scale, int line, double x, double y)
@@ -318,6 +323,104 @@ void tst_QuickPath::line()
line(QSizeF(7.23,7.23));
}
+void tst_QuickPath::rectangle_data()
+{
+ QTest::addColumn<QByteArray>("pathqml");
+ QTest::addColumn<QRectF>("rect");
+
+ QTest::newRow("basic") << QByteArray("PathRectangle { width: 100; height: 100 }\n")
+ << QRectF(0, 0, 100, 100);
+
+ QTest::newRow("relative") << QByteArray("startX: -50; startY: -100\nPathRectangle {"
+ "relativeX: 100.2; relativeY: 200.3;"
+ "width: 10.5; height: 10.5 }\n")
+ << QRectF(50.2, 100.3, 10.5, 10.5);
+
+ QTest::newRow("stroke") << QByteArray("PathRectangle { x: 5; y: 10; width: 100; height: 100;"
+ "strokeAdjustment: 20 }\n")
+ << QRectF(5, 10, 100, 100).adjusted(10, 10, -10, -10);
+}
+
+void tst_QuickPath::rectangle(const QQuickPath *path, const QRectF &rect)
+{
+ QCOMPARE(path->pointAtPercent(0), rect.topLeft());
+ QCOMPARE(path->pointAtPercent(1), rect.topLeft());
+ QCOMPARE(path->pointAtPercent(1.0 / 8), QPointF(rect.center().x(), rect.top()));
+ QCOMPARE(path->pointAtPercent(3.0 / 8), QPointF(rect.right(), rect.center().y()));
+ QCOMPARE(path->pointAtPercent(5.0 / 8), QPointF(rect.center().x(), rect.bottom()));
+ QCOMPARE(path->pointAtPercent(7.0 / 8), QPointF(rect.left(), rect.center().y()));
+}
+
+void tst_QuickPath::rectangle()
+{
+ QFETCH(QByteArray, pathqml);
+ QFETCH(QRectF, rect);
+
+ QQmlEngine engine;
+ QQmlComponent c1(&engine);
+ c1.setData("import QtQuick\nPath {\n" + pathqml + "}", QUrl());
+ QScopedPointer<QObject> o1(c1.create());
+ QQuickPath *path = qobject_cast<QQuickPath *>(o1.data());
+ QVERIFY(path);
+ QCOMPARE(path->pointAtPercent(0), rect.topLeft());
+ QCOMPARE(path->pointAtPercent(1), rect.topLeft());
+ QCOMPARE(path->pointAtPercent(1.0 / 8), QPointF(rect.center().x(), rect.top()));
+ QCOMPARE(path->pointAtPercent(3.0 / 8), QPointF(rect.right(), rect.center().y()));
+ QCOMPARE(path->pointAtPercent(5.0 / 8), QPointF(rect.center().x(), rect.bottom()));
+ QCOMPARE(path->pointAtPercent(7.0 / 8), QPointF(rect.left(), rect.center().y()));
+}
+
+#define COMPARE_RADII(P, Q) \
+ QCOMPARE(P.radius(), Q->radius()); \
+ QCOMPARE(P.topLeftRadius(), Q->topLeftRadius()); \
+ QCOMPARE(P.topRightRadius(), Q->topRightRadius()); \
+ QCOMPARE(P.bottomLeftRadius(), Q->bottomLeftRadius()); \
+ QCOMPARE(P.bottomRightRadius(), Q->bottomRightRadius());
+
+void tst_QuickPath::rectangleRadii()
+{
+ // Test that the radius logic of PathRectangle is the same as Rectangle's
+ QQmlEngine engine;
+ QQmlComponent c1(&engine);
+ c1.setData("import QtQuick\n"
+ "Rectangle { x: 10; y: 20; width: 30; height: 40\n"
+ "}",
+ QUrl());
+ QScopedPointer<QObject> o1(c1.create());
+ QQuickRectangle *quickRectangle = qobject_cast<QQuickRectangle *>(o1.data());
+ QVERIFY(quickRectangle);
+ QQuickPathRectangle pathRectangle;
+ pathRectangle.setX(quickRectangle->x());
+ pathRectangle.setY(quickRectangle->y());
+ pathRectangle.setWidth(quickRectangle->width());
+ pathRectangle.setHeight(quickRectangle->height());
+ COMPARE_RADII(pathRectangle, quickRectangle);
+ pathRectangle.setRadius(5);
+ quickRectangle->setRadius(5);
+ COMPARE_RADII(pathRectangle, quickRectangle);
+ pathRectangle.setBottomLeftRadius(15);
+ quickRectangle->setBottomLeftRadius(15);
+ COMPARE_RADII(pathRectangle, quickRectangle);
+ pathRectangle.setRadius(-5);
+ quickRectangle->setRadius(-5);
+ COMPARE_RADII(pathRectangle, quickRectangle);
+ pathRectangle.setRadius(0);
+ quickRectangle->setRadius(0);
+ COMPARE_RADII(pathRectangle, quickRectangle);
+ pathRectangle.setTopLeftRadius(-7);
+ quickRectangle->setTopLeftRadius(-7);
+ COMPARE_RADII(pathRectangle, quickRectangle);
+ pathRectangle.setRadius(4);
+ quickRectangle->setRadius(4);
+ pathRectangle.resetBottomLeftRadius();
+ quickRectangle->resetBottomLeftRadius();
+ pathRectangle.setTopRightRadius(0);
+ quickRectangle->setTopRightRadius(0);
+ pathRectangle.setTopLeftRadius(200);
+ quickRectangle->setTopLeftRadius(200);
+ COMPARE_RADII(pathRectangle, quickRectangle);
+}
+
QTEST_MAIN(tst_QuickPath)
#include "tst_qquickpath.moc"
diff --git a/tests/auto/quick/qquickpathview/CMakeLists.txt b/tests/auto/quick/qquickpathview/CMakeLists.txt
index 998eba58f5..a7f74bafce 100644
--- a/tests/auto/quick/qquickpathview/CMakeLists.txt
+++ b/tests/auto/quick/qquickpathview/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickpathview Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpathview LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickpathview/data/flickableDelegate.qml b/tests/auto/quick/qquickpathview/data/flickableDelegate.qml
index 3243dc23dc..0cb42dcf86 100644
--- a/tests/auto/quick/qquickpathview/data/flickableDelegate.qml
+++ b/tests/auto/quick/qquickpathview/data/flickableDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickpathview/data/mousePressAfterFlick.qml b/tests/auto/quick/qquickpathview/data/mousePressAfterFlick.qml
new file mode 100644
index 0000000000..a30234127b
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/mousePressAfterFlick.qml
@@ -0,0 +1,61 @@
+import QtQuick
+
+Item {
+ id: root
+ width: 360
+ height: 900
+
+ MouseArea {
+ id: rootMouseArea
+ objectName: "rootMouseArea"
+ anchors.fill: parent
+ }
+
+ PathView {
+ id: pathView
+ objectName: "pathView"
+ anchors.centerIn: parent
+ width: 150
+ height: parent.height
+ dragMargin: Number.POSITIVE_INFINITY
+
+ preferredHighlightBegin: 0.5
+ preferredHighlightEnd: 0.5
+ pathItemCount: 9
+
+ Item {
+ anchors.fill: parent
+ }
+
+ model: 10
+
+ delegate: Rectangle {
+ id: delegate
+ width: parent.width
+ height: 120
+ color: "red"
+ Text {
+ anchors.fill: parent
+ horizontalAlignment: Qt.AlignHCenter
+ text: "Path element " + modelData
+ }
+ }
+
+ path: Path {
+ id: path
+ property int width: pathView.width
+ startX: path.width / 2
+ startY: 0
+
+ PathCurve {
+ x: path.width / 2
+ relativeY: 32
+ }
+ PathCurve {
+ x: path.width / 2
+ relativeY: pathView.height - 32
+ }
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qquickpathview/data/nestedInFlickable.qml b/tests/auto/quick/qquickpathview/data/nestedInFlickable.qml
index 36938d69b5..35f5b12d17 100644
--- a/tests/auto/quick/qquickpathview/data/nestedInFlickable.qml
+++ b/tests/auto/quick/qquickpathview/data/nestedInFlickable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickpathview/data/nestedmousearea2.qml b/tests/auto/quick/qquickpathview/data/nestedmousearea2.qml
index 5fa50ec3c1..985b53cd45 100644
--- a/tests/auto/quick/qquickpathview/data/nestedmousearea2.qml
+++ b/tests/auto/quick/qquickpathview/data/nestedmousearea2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickpathview/data/objectModelMove.qml b/tests/auto/quick/qquickpathview/data/objectModelMove.qml
index 7e87330b23..04102d0956 100644
--- a/tests/auto/quick/qquickpathview/data/objectModelMove.qml
+++ b/tests/auto/quick/qquickpathview/data/objectModelMove.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml.Models 2.11
import QtQuick 2.11
diff --git a/tests/auto/quick/qquickpathview/data/overcached.qml b/tests/auto/quick/qquickpathview/data/overcached.qml
new file mode 100644
index 0000000000..734b0cd7cf
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/overcached.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.0
+
+PathView {
+ id: view
+ property int delegatesCreated: 0
+ property int delegatesDestroyed: 0
+
+ anchors.fill: parent
+ preferredHighlightBegin: 0.5
+ preferredHighlightEnd: 0.5
+ pathItemCount: 10
+ interactive: true
+ model: 15
+ // Much bigger cache than model - pathItemCount
+ cacheItemCount: 100
+ delegate: Text {
+ text: modelData
+ Component.onCompleted: view.delegatesCreated++;
+ Component.onDestruction: view.delegatesDestroyed++;
+ }
+ path: Path {
+ PathLine {
+ x: 0
+ y: 400
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickpathview/data/qtbug37815.qml b/tests/auto/quick/qquickpathview/data/qtbug37815.qml
index ea12daec87..8854164b5c 100644
--- a/tests/auto/quick/qquickpathview/data/qtbug37815.qml
+++ b/tests/auto/quick/qquickpathview/data/qtbug37815.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Netris
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickpathview/data/qtbug46487.qml b/tests/auto/quick/qquickpathview/data/qtbug46487.qml
new file mode 100644
index 0000000000..840d77ffe4
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/qtbug46487.qml
@@ -0,0 +1,28 @@
+import QtQuick 2.0
+
+PathView {
+ id: view
+ property int delegatesCreated: 0
+ property int delegatesDestroyed: 0
+
+ width: 400
+ height: 400
+ preferredHighlightBegin: 0.5
+ preferredHighlightEnd: 0.5
+ pathItemCount: 5
+ currentIndex: 1
+ model: customModel
+ delegate: Text {
+ text: "item: " + index + " of: " + view.count
+ Component.onCompleted: view.delegatesCreated++;
+ Component.onDestruction: view.delegatesDestroyed++;
+ }
+ path: Path {
+ startX: 50
+ startY: 0
+ PathLine {
+ x: 50
+ y: 400
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickpathview/data/qtbug53464.qml b/tests/auto/quick/qquickpathview/data/qtbug53464.qml
index a2855c0fb5..df16763ccb 100644
--- a/tests/auto/quick/qquickpathview/data/qtbug53464.qml
+++ b/tests/auto/quick/qquickpathview/data/qtbug53464.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Netris
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickpathview/data/qtbug90479.qml b/tests/auto/quick/qquickpathview/data/qtbug90479.qml
new file mode 100644
index 0000000000..bfa4ab8243
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/qtbug90479.qml
@@ -0,0 +1,25 @@
+import QtQuick 2.0
+
+PathView {
+ id: view
+ property int delegatesCreated: 0
+ property int delegatesDestroyed: 0
+
+ anchors.fill: parent
+ preferredHighlightBegin: 0.5
+ preferredHighlightEnd: 0.5
+ pathItemCount: 6
+ interactive: true
+ model: 19
+ delegate: Text {
+ text: modelData
+ Component.onCompleted: view.delegatesCreated++;
+ Component.onDestruction: view.delegatesDestroyed++;
+ }
+ path: Path {
+ PathLine {
+ x: 0
+ y: 400
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
index 98085002ea..703d6e053d 100644
--- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
+++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuick/qquickview.h>
@@ -13,6 +13,7 @@
#include <QtQuick/private/qquickpath_p.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
+#include <QtQuick/private/qquickmousearea_p.h>
#include <QtQuickTest/QtQuickTest>
#include <QtQmlModels/private/qqmllistmodel_p.h>
#include <QtQml/private/qqmlvaluetype_p.h>
@@ -130,6 +131,10 @@ private slots:
void requiredPropertiesInDelegate();
void requiredPropertiesInDelegatePreventUnrelated();
void touchMove();
+ void mousePressAfterFlick();
+ void qtbug90479();
+ void overCached();
+ void qtbug46487();
private:
QScopedPointer<QPointingDevice> touchDevice = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
@@ -861,10 +866,9 @@ void tst_QQuickPathView::dataModel()
model.moveItem(3, 5);
QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").size(), 5);
- QList<QQuickItem*> items = findItems<QQuickItem>(pathview, "wrapper");
- foreach (QQuickItem *item, items) {
+ const QList<QQuickItem *> items = findItems<QQuickItem>(pathview, "wrapper");
+ for (QQuickItem *item : items)
QVERIFY(item->property("onPath").toBool());
- }
QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 1));
// QTBUG-14199
@@ -1375,7 +1379,7 @@ void tst_QQuickPathView::package()
QQuickPathView *pathView = window->rootObject()->findChild<QQuickPathView*>("photoPathView");
QVERIFY(pathView);
-#ifdef Q_OS_MAC
+#ifdef Q_OS_MACOS
QSKIP("QTBUG-27170 view does not reliably receive polish without a running animation");
#endif
@@ -2502,7 +2506,8 @@ void tst_QQuickPathView::qtbug37815()
const int pathItemCount = pathView->pathItemCount();
const int cacheItemCount = pathView->cacheItemCount();
int totalCount = 0;
- foreach (QQuickItem *item, pathView->childItems()) {
+ const auto childItems = pathView->childItems();
+ for (QQuickItem *item : childItems) {
if (item->objectName().startsWith(QLatin1String("delegate")))
++totalCount;
}
@@ -2571,7 +2576,8 @@ void tst_QQuickPathView::qtbug53464()
const int pathItemCount = pathView->pathItemCount();
int totalCount = 0;
- foreach (QQuickItem *item, pathView->childItems()) {
+ const auto childItems = pathView->childItems();
+ for (QQuickItem *item : childItems) {
if (item->objectName().startsWith(QLatin1String("delegate")))
++totalCount;
}
@@ -2851,6 +2857,147 @@ void tst_QQuickPathView::touchMove()
}
+void tst_QQuickPathView::mousePressAfterFlick() // QTBUG-115121
+{
+ QScopedPointer<QQuickView> window(createView());
+ QQuickVisualTestUtils::moveMouseAway(window.data());
+ window->setSource(testFileUrl("mousePressAfterFlick.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickPathView *pathview = window->rootObject()->findChild<QQuickPathView *>("pathView");
+ QVERIFY(pathview != nullptr);
+
+ QQuickMouseArea *mouseArea = window->rootObject()->findChild<QQuickMouseArea *>("rootMouseArea");
+ QVERIFY(mouseArea != nullptr);
+
+ QSignalSpy flickingSpy(pathview, SIGNAL(flickingChanged()));
+ QSignalSpy flickStartedSpy(pathview, SIGNAL(flickStarted()));
+ QSignalSpy flickEndedSpy(pathview, SIGNAL(flickEnded()));
+
+ QSignalSpy pressedSpy(mouseArea, &QQuickMouseArea::pressed);
+
+ flickingSpy.clear();
+ flickStartedSpy.clear();
+ flickEndedSpy.clear();
+
+ // Dragging the child mouse area should animate the PathView (MA has no drag target)
+ QPoint from = QPoint((window->width() / 2), (window->height() * 3 / 4));
+ QPoint to = QPoint((window->width() / 2), (window->height() / 4));
+ flick(window.data(), from, to, 100);
+ QVERIFY(pathview->isMoving());
+ QCOMPARE(flickingSpy.size(), 1);
+ QCOMPARE(flickStartedSpy.size(), 1);
+ QCOMPARE(flickEndedSpy.size(), 0);
+
+ // Now while it's still moving, click it.
+ // The PathView should stop at a position
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, window->height() / 4));
+ QTRY_VERIFY(!pathview->isMoving());
+ QCOMPARE(flickEndedSpy.size(), 1);
+ QCOMPARE(pressedSpy.size(), 0);
+}
+
+void tst_QQuickPathView::qtbug90479()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("qtbug90479.qml"));
+
+ window->show();
+ qApp->processEvents();
+
+ QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
+ QVERIFY(pathview);
+
+ // cache items will be created async. Let's wait...
+ QTest::qWait(1000);
+
+ // Should create just pathItemCount amount and not destroy any
+ QCOMPARE(pathview->property("delegatesCreated").toInt(), 6);
+ QCOMPARE(pathview->property("delegatesDestroyed").toInt(), 0);
+}
+
+void tst_QQuickPathView::overCached()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("overcached.qml"));
+
+ window->show();
+ qApp->processEvents();
+
+ QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
+ QVERIFY(pathview);
+
+ // cache items will be created async. Let's wait...
+ QTest::qWait(1000);
+
+ // Should create max model + 1 amount with the current implementation
+ QVERIFY(pathview->property("delegatesCreated").toInt() <= 16);
+ QVERIFY(pathview->property("delegatesDestroyed").toInt() <= 1);
+}
+
+class CustomModel : public QAbstractListModel
+{
+public:
+ CustomModel(QObject *parent = 0) : QAbstractListModel(parent) {
+ m_values << 0 << 1 << 2 << 3 << 4;
+ }
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const final {
+ Q_UNUSED(parent);
+ return m_values.count();
+ }
+ QVariant data(const QModelIndex &index, int) const final {
+ if (index.row() < 0 || m_values.count() <= index.row())
+ return QVariant();
+
+ return m_values[index.row()];
+ }
+
+ Q_INVOKABLE void shrink() {
+ beginResetModel();
+ m_values.takeLast();
+ m_values.takeLast();
+ endResetModel();
+ }
+
+private:
+ QList<int> m_values;
+};
+
+void tst_QQuickPathView::qtbug46487()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ CustomModel* model = new CustomModel;
+ QQmlContext *ctxt = window->rootContext();
+ ctxt->setContextProperty("customModel", model);
+
+ window->setSource(testFileUrl("qtbug46487.qml"));
+ window->show();
+ qApp->processEvents();
+
+ QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
+ QVERIFY(pathview);
+
+ QTest::qWait(500);
+
+ // Should create just pathItemCount amount and not destroy any
+ QCOMPARE(pathview->count(), 5);
+ QCOMPARE(pathview->property("delegatesCreated").toInt(), 5);
+ QCOMPARE(pathview->property("delegatesDestroyed").toInt(), 0);
+
+ // Resets the model and removes 2 items.
+ model->shrink();
+ QTest::qWait(500);
+
+ // Should destroy previous items (begin/endResetModel) and
+ // (re)create 3 new items.
+ QCOMPARE(pathview->count(), 3);
+ QCOMPARE(pathview->property("delegatesCreated").toInt(), 5 + 3);
+ QCOMPARE(pathview->property("delegatesDestroyed").toInt(), 5);
+}
+
QTEST_MAIN(tst_QQuickPathView)
#include "tst_qquickpathview.moc"
diff --git a/tests/auto/quick/qquickpincharea/CMakeLists.txt b/tests/auto/quick/qquickpincharea/CMakeLists.txt
index 8408a3f70e..4d0af2d3a0 100644
--- a/tests/auto/quick/qquickpincharea/CMakeLists.txt
+++ b/tests/auto/quick/qquickpincharea/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickpincharea Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpincharea LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
index 800d7211fb..1bab22c4e2 100644
--- a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
+++ b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/private/qvariantanimation_p.h>
#include <QtTest/QtTest>
@@ -15,6 +15,9 @@
#include <QtQml/qqmlcontext.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
+#include <QtQuickTestUtils/private/visualtestutils_p.h>
+
+using namespace QQuickVisualTestUtils;
class tst_QQuickPinchArea: public QQmlDataTest
{
@@ -622,20 +625,6 @@ void tst_QQuickPinchArea::dragTransformedPinchArea() // QTBUG-63673
QCOMPARE(pinchArea->pinch()->active(), false);
}
-template<typename F>
-void forEachLerpStep(int steps, F &&func)
-{
- for (int i = 0; i < steps; ++i) {
- const qreal t = qreal(i) / steps;
- func(t);
- }
-}
-
-QPoint lerpPoints(const QPoint &point1, const QPoint &point2, qreal t)
-{
- return QPoint(_q_interpolate(point1.x(), point2.x(), t), _q_interpolate(point1.y(), point2.y(), t));
-};
-
// QTBUG-105058
void tst_QQuickPinchArea::pinchAreaKeepsDragInView()
{
@@ -666,9 +655,10 @@ void tst_QQuickPinchArea::pinchAreaKeepsDragInView()
const int steps = 30;
QPoint point1End = point1Start + QPoint(-dragThreshold, dragThreshold);
QPoint point2End = point2Start + QPoint(dragThreshold, -dragThreshold);
- forEachLerpStep(steps, [&](qreal t) {
- pinchSequence.move(1, lerpPoints(point1Start, point1End, t), &view)
- .move(2, lerpPoints(point2Start, point2End, t), &view).commit();
+
+ forEachStep(steps, [&](qreal progress) {
+ pinchSequence.move(1, lerpPoints(point1Start, point1End, progress), &view)
+ .move(2, lerpPoints(point2Start, point2End, progress), &view).commit();
QQuickTouchUtils::flush(&view);
QTest::qWait(5);
});
@@ -691,9 +681,9 @@ void tst_QQuickPinchArea::pinchAreaKeepsDragInView()
point2Start = point2End;
point1End = point1Start + QPoint(100, 0);
point2End = point2Start + QPoint(100, 0);
- forEachLerpStep(steps, [&](qreal t) {
- pinchSequence.move(1, lerpPoints(point1Start, point1End, t), &view)
- .move(2, lerpPoints(point2Start, point2End, t), &view).commit();
+ forEachStep(steps, [&](qreal progress) {
+ pinchSequence.move(1, lerpPoints(point1Start, point1End, progress), &view)
+ .move(2, lerpPoints(point2Start, point2End, progress), &view).commit();
QQuickTouchUtils::flush(&view);
QTest::qWait(5);
});
diff --git a/tests/auto/quick/qquickpixmapcache/BLACKLIST b/tests/auto/quick/qquickpixmapcache/BLACKLIST
new file mode 100644
index 0000000000..00d8eb5619
--- /dev/null
+++ b/tests/auto/quick/qquickpixmapcache/BLACKLIST
@@ -0,0 +1,3 @@
+# QTBUG-118064
+[slowDevice]
+*
diff --git a/tests/auto/quick/qquickpixmapcache/CMakeLists.txt b/tests/auto/quick/qquickpixmapcache/CMakeLists.txt
index 2fbe3592c0..97735172f2 100644
--- a/tests/auto/quick/qquickpixmapcache/CMakeLists.txt
+++ b/tests/auto/quick/qquickpixmapcache/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickpixmapcache Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpixmapcache LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -16,8 +22,8 @@ list(APPEND test_data ${test_data_glob})
qt_internal_add_test(tst_qquickpixmapcache
SOURCES
tst_qquickpixmapcache.cpp
+ deviceloadingimage.h deviceloadingimage.cpp
LIBRARIES
- Qt::Concurrent
Qt::CorePrivate
Qt::Gui
Qt::GuiPrivate
@@ -40,3 +46,13 @@ qt_internal_extend_target(tst_qquickpixmapcache CONDITION NOT ANDROID AND NOT IO
DEFINES
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
)
+
+qt_internal_extend_target(tst_qquickpixmapcache CONDITION QT_FEATURE_concurrent
+ LIBRARIES
+ Qt::Concurrent
+)
+
+qt_policy(SET QTP0001 NEW)
+qt_add_qml_module(tst_qquickpixmapcache
+ URI PixmapCacheTest
+)
diff --git a/tests/auto/quick/qquickpixmapcache/data/slowLoading.qml b/tests/auto/quick/qquickpixmapcache/data/slowLoading.qml
new file mode 100644
index 0000000000..7ac98ae87b
--- /dev/null
+++ b/tests/auto/quick/qquickpixmapcache/data/slowLoading.qml
@@ -0,0 +1,13 @@
+import QtQuick
+import PixmapCacheTest
+
+DeviceLoadingImage {
+ id: root
+ width: 240
+ height: 240
+ sourceSize.width: width
+ sourceSize.height: height
+ source: "image://slow/200"
+ asynchronous: true
+ retainWhileLoading: true
+}
diff --git a/tests/auto/quick/qquickpixmapcache/data/tableViewWithDeviceLoadingImages.qml b/tests/auto/quick/qquickpixmapcache/data/tableViewWithDeviceLoadingImages.qml
new file mode 100644
index 0000000000..68119ac1a9
--- /dev/null
+++ b/tests/auto/quick/qquickpixmapcache/data/tableViewWithDeviceLoadingImages.qml
@@ -0,0 +1,45 @@
+import QtQuick
+import PixmapCacheTest
+
+TableView {
+ id: root
+ width: 640
+ height: 480
+ model: 100
+ rowSpacing: 6
+ property real size: 40
+ columnWidthProvider: function(col) { return root.size }
+ rowHeightProvider: function(col) { return root.size }
+
+ Timer {
+ interval: 200
+ repeat: true
+ running: true
+ onTriggered: {
+ root.size = Math.random() * 200
+ root.positionViewAtRow(Math.round(Math.random() * 100), TableView.Visible)
+ }
+ }
+
+ delegate: DeviceLoadingImage {
+ required property int index
+ width: root.size; height: root.size
+ asynchronous: true
+ source: "image://slow/" + index
+ sourceSize.width: width
+ sourceSize.height: height
+
+ Rectangle {
+ anchors.fill: parent
+ color: "transparent"
+ border.color: "red"
+ }
+
+ Text {
+ color: "red"
+ style: Text.Outline
+ styleColor: "white"
+ text: index + "\nsize " + root.size.toFixed(1)
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickpixmapcache/deviceloadingimage.cpp b/tests/auto/quick/qquickpixmapcache/deviceloadingimage.cpp
new file mode 100644
index 0000000000..bc7a3b4246
--- /dev/null
+++ b/tests/auto/quick/qquickpixmapcache/deviceloadingimage.cpp
@@ -0,0 +1,42 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "deviceloadingimage.h"
+
+#include <QtQuick/private/qquickimage_p_p.h>
+
+Q_DECLARE_LOGGING_CATEGORY(lcTests)
+
+void DeviceLoadingImage::load()
+{
+ auto *d = static_cast<QQuickImagePrivate *>(QQuickImagePrivate::get(this));
+ static int thisRequestFinished = -1;
+ if (thisRequestFinished == -1) {
+ thisRequestFinished =
+ QQuickImageBase::staticMetaObject.indexOfSlot("requestFinished()");
+ }
+ const QQmlContext *context = qmlContext(this);
+ Q_ASSERT(context);
+ QUrl resolved = context->resolvedUrl(d->url);
+ device = std::make_unique<QFile>(resolved.toLocalFile());
+ const bool statusChange = (d->status != Loading);
+ if (statusChange)
+ d->status = Loading;
+ d->pendingPix->loadImageFromDevice(qmlEngine(this), device.get(), context->resolvedUrl(d->url),
+ d->sourceClipRect.toRect(), d->sourcesize * d->devicePixelRatio,
+ QQuickImageProviderOptions(), d->currentFrame, d->frameCount);
+ connectSuccess &= d->pendingPix->connectFinished(this, thisRequestFinished);
+ connectSuccess &= d->pendingPix->connectFinished(this, SLOT(onRequestFinished()));
+ qCDebug(lcTests) << "loading page" << d->currentFrame << "of" << d->frameCount
+ << "statuses" << d->currentPix->status() << d->pendingPix->status()
+ << "waiting?" << connectSuccess;
+ if (statusChange)
+ emit statusChanged(d->status);
+}
+
+void DeviceLoadingImage::onRequestFinished()
+{
+ auto *d = static_cast<QQuickImagePrivate *>(QQuickImagePrivate::get(this));
+ qCDebug(lcTests) << "statuses" << d->currentPix->status() << d->pendingPix->status();
+ ++requestsFinished;
+}
diff --git a/tests/auto/quick/qquickpixmapcache/deviceloadingimage.h b/tests/auto/quick/qquickpixmapcache/deviceloadingimage.h
new file mode 100644
index 0000000000..c00b456b94
--- /dev/null
+++ b/tests/auto/quick/qquickpixmapcache/deviceloadingimage.h
@@ -0,0 +1,25 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtCore/QFile>
+#include <QtQuick/private/qquickimage_p.h>
+
+class DeviceLoadingImage : public QQuickImage
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(DeviceLoadingImage)
+
+public:
+ DeviceLoadingImage(QQuickItem *parent = nullptr) : QQuickImage(parent) { }
+
+protected:
+ void load() override;
+
+protected slots:
+ void onRequestFinished();
+
+public:
+ std::unique_ptr<QFile> device;
+ bool connectSuccess = true;
+ int requestsFinished = 0;
+};
diff --git a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
index 590f022e4e..fcd5265ec2 100644
--- a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
+++ b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
@@ -1,20 +1,54 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtTest/QtTest>
+#include <QtQuick/private/qquickimage_p_p.h>
#include <QtQuick/private/qquickpixmapcache_p.h>
#include <QtQml/qqmlengine.h>
#include <QtQuick/qquickimageprovider.h>
+#include <QtQuick/qquickview.h>
#include <QtQml/QQmlComponent>
#include <QNetworkReply>
+#include <QtGui/qpainter.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/testhttpserver_p.h>
+#include <QtQuickTestUtils/private/viewtestutils_p.h>
#if QT_CONFIG(concurrent)
#include <qtconcurrentrun.h>
#include <qfuture.h>
#endif
+#include "deviceloadingimage.h"
+
+Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
+
+class SlowProvider : public QQuickImageProvider
+{
+public:
+ SlowProvider() : QQuickImageProvider(Image) {}
+
+ QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize) override
+ {
+ const int row = id.toInt();
+ qCDebug(lcTests) << requestCount << QThread::currentThread() << "row" << row << requestedSize;
+ QImage image(requestedSize, QImage::Format_RGB888);
+ QPainter painter(&image);
+ const QColor c(128, row % 8 * 32, 64);
+ painter.fillRect(0, 0, requestedSize.width(), requestedSize.height(), c);
+ if (size)
+ *size = requestedSize;
+ ++requestCount;
+ QThread::currentThread()->msleep(row);
+ return image;
+ }
+
+ int requestCount = 0;
+};
+Q_DECLARE_METATYPE(SlowProvider*);
+
+QT_BEGIN_NAMESPACE
+
#define PIXMAP_DATA_LEAK_TEST 0
class tst_qquickpixmapcache : public QQmlDataTest
@@ -41,6 +75,8 @@ private slots:
#if PIXMAP_DATA_LEAK_TEST
void dataLeak();
#endif
+ void slowDevice();
+ void slowDeviceInterrupted();
private:
QQmlEngine engine;
TestHTTPServer server;
@@ -450,7 +486,6 @@ void tst_qquickpixmapcache::asynchronousNoCache()
QScopedPointer<QObject> root {component.create()}; // should not crash
}
-
#if PIXMAP_DATA_LEAK_TEST
// This test should not be enabled by default as it
// produces spurious output in the expected case.
@@ -460,9 +495,9 @@ class DataLeakView : public QQuickView
Q_OBJECT
public:
- explicit DataLeakView() : QQuickView()
+ explicit DataLeakView(const QUrl &src) : QQuickView()
{
- setSource(testFileUrl("dataLeak.qml"));
+ setSource(src);
}
void showFor2Seconds()
@@ -480,14 +515,14 @@ Q_GLOBAL_STATIC(QQuickPixmap, dataLeakPixmap)
void tst_qquickpixmapcache::dataLeak()
{
// Should not leak cached QQuickPixmapData.
- // Unfortunately, since the QQuickPixmapStore
- // is a global static, and it releases the cache
+ // Unfortunately, since the QQuickPixmapCache
+ // is a singleton, and it releases the cache
// entries on dtor (application exit), we must use
- // valgrind to determine whether it leaks or not.
+ // valgrind or ASAN to determine whether it leaks or not.
QQuickPixmap *p1 = new QQuickPixmap;
QQuickPixmap *p2 = new QQuickPixmap;
{
- QScopedPointer<DataLeakView> test(new DataLeakView);
+ QScopedPointer<DataLeakView> test(new DataLeakView(testFileUrl("dataLeak.qml")));
test->showFor2Seconds();
dataLeakPixmap()->load(test->engine(), testFileUrl("exists.png"));
p1->load(test->engine(), testFileUrl("exists.png"));
@@ -497,12 +532,85 @@ void tst_qquickpixmapcache::dataLeak()
// When the (global static) dataLeakPixmap is deleted, it
// shouldn't attempt to dereference a QQuickPixmapData
- // which has been deleted by the QQuickPixmapStore
+ // which has been deleted by the QQuickPixmapCache
// destructor.
}
#endif
#undef PIXMAP_DATA_LEAK_TEST
+/*!
+ Test lots of async QQuickPixmap::loadImageFromDevice() jobs with random
+ sizes and frames, so that cached images are seldom reused. Some jobs get
+ cancelled, some succeed. This should not lead to any cache leaks.
+ Similar to the QtPdf usecase in QTBUG-114953
+*/
+void tst_qquickpixmapcache::slowDevice()
+{
+ QSKIP("Crashes: QTBUG-126047");
+
+#ifdef QT_BUILD_INTERNAL
+ auto *provider = new SlowProvider;
+ engine.addImageProvider("slow", provider); // takes ownership
+
+ {
+ QQuickView window(&engine, nullptr);
+ QVERIFY(QQuickTest::showView(window, testFileUrl("tableViewWithDeviceLoadingImages.qml")));
+ // Timer generates 5 requests / sec; TableView shows multiple delegates (depending on size);
+ // so we should get 100 requests in some fraction of 20 sec. Give it 30 to be sure.
+ QTRY_COMPARE_GE_WITH_TIMEOUT(provider->requestCount, 100, 30000);
+ const int cacheCount = QQuickPixmapCache::instance()->m_cache.size();
+ qCDebug(lcTests) << "cached pixmaps" << cacheCount;
+ QCOMPARE_GT(cacheCount, 0);
+ } // window goes out of scope: all QQuickPixmapData instances should be eventually unreferenced
+
+ QTRY_COMPARE(QQuickPixmapCache::instance()->referencedCost(), 0);
+ const int leakedPixmaps = QQuickPixmapCache::instance()->destroyCache();
+ QCOMPARE(leakedPixmaps, 0);
+#else
+ QSKIP("This test relies on private APIs that are only exported in developer-builds");
+#endif
+}
+
+void tst_qquickpixmapcache::slowDeviceInterrupted()
+{
+#ifdef QT_BUILD_INTERNAL
+ auto *provider = new SlowProvider;
+ engine.addImageProvider("slow", provider); // takes ownership
+
+ const QColor secondExpectedColor(128, 50 % 8 * 32, 64);
+
+ {
+ QQuickView window(&engine, nullptr);
+ QVERIFY(QQuickTest::showView(window, testFileUrl("slowLoading.qml")));
+ DeviceLoadingImage *dlimg = qobject_cast<DeviceLoadingImage *>(window.rootObject());
+ QVERIFY(dlimg);
+ // the declared source: "image://slow/200" should take 200 ms to load
+ QTRY_COMPARE(dlimg->status(), QQuickImageBase::Loading);
+ QVERIFY(dlimg->connectSuccess);
+ dlimg->setSource(QUrl("image://slow/50"));
+ QTRY_COMPARE(dlimg->requestsFinished, 2);
+ QCOMPARE(provider->requestCount, 2);
+ QCOMPARE(dlimg->status(), QQuickImageBase::Ready);
+ auto *img_d = static_cast<QQuickImagePrivate *>(QQuickImagePrivate::get(dlimg));
+ QCOMPARE(img_d->currentPix->image().pixelColor({1, 1}), secondExpectedColor);
+ QCOMPARE(QQuickPixmapCache::instance()->m_cache.size(), 2);
+ // Unless CI paused at the wrong time for > 200 ms, we cancelled loading
+ // the first image and switched to the second, so QQuickImageBase::requestFinished()
+ // should have only called swap() once. But if this check ends up being flaky in CI,
+ // it can be be removed.
+ QCOMPARE(img_d->currentPix, &img_d->pix2);
+ } // window goes out of scope: all QQuickPixmapData instances should be eventually unreferenced
+
+ QTRY_COMPARE(QQuickPixmapCache::instance()->referencedCost(), 0);
+ const int leakedPixmaps = QQuickPixmapCache::instance()->destroyCache();
+ QCOMPARE_LE(leakedPixmaps, 0); // -1 if the cache is already destroyed
+#else
+ QSKIP("This test relies on private APIs that are only exported in developer-builds");
+#endif
+}
+
+QT_END_NAMESPACE
+
QTEST_MAIN(tst_qquickpixmapcache)
#include "tst_qquickpixmapcache.moc"
diff --git a/tests/auto/quick/qquickpositioners/CMakeLists.txt b/tests/auto/quick/qquickpositioners/CMakeLists.txt
index 3e563155b6..fb046e3d45 100644
--- a/tests/auto/quick/qquickpositioners/CMakeLists.txt
+++ b/tests/auto/quick/qquickpositioners/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickpositioners Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpositioners LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
index 317694f06c..c250fbf554 100644
--- a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
+++ b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <QtTest/QtTest>
#include <QtQuick/qquickview.h>
#include <qqmlengine.h>
@@ -1328,7 +1329,7 @@ void tst_qquickpositioners::checkItemPositions(QQuickItem *positioner, QaimModel
for (int i=0; i<model->count(); ++i) {
QQuickItem *item = findItem<QQuickItem>(positioner, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i)));
QCOMPARE(item->width(), currentSize);
QCOMPARE(item->height(), currentSize);
@@ -3757,7 +3758,7 @@ void tst_qquickpositioners::test_mirroring()
QList<QString> objectNames;
objectNames << "one" << "two" << "three" << "four" << "five";
- foreach (const QString qmlFile, qmlFiles) {
+ for (const QString &qmlFile : std::as_const(qmlFiles)) {
QScopedPointer<QQuickView> windowA(createView(testFile(qmlFile)));
QQuickItem *rootA = qobject_cast<QQuickItem*>(windowA->rootObject());
@@ -3770,7 +3771,7 @@ void tst_qquickpositioners::test_mirroring()
rootA->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft
// LTR != RTL
- foreach (const QString objectName, objectNames) {
+ for (const QString &objectName : std::as_const(objectNames)) {
// horizontal.qml and horizontal-padding.qml only have three items
if (qmlFile.startsWith(QString("horizontal")) && objectName == QString("four"))
break;
@@ -3785,7 +3786,7 @@ void tst_qquickpositioners::test_mirroring()
inheritProp.write(true);
// RTL == mirror
- foreach (const QString objectName, objectNames) {
+ for (const QString &objectName : std::as_const(objectNames)) {
// horizontal.qml and horizontal-padding.qml only have three items
if (qmlFile.startsWith(QString("horizontal")) && objectName == QString("four"))
break;
@@ -3806,7 +3807,7 @@ void tst_qquickpositioners::test_mirroring()
rootB->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft
// LTR == RTL + mirror
- foreach (const QString objectName, objectNames) {
+ for (const QString &objectName : std::as_const(objectNames)) {
// horizontal.qml and horizontal-padding.qml only have three items
if (qmlFile.startsWith(QString("horizontal")) && objectName == QString("four"))
break;
@@ -4027,7 +4028,7 @@ void tst_qquickpositioners::matchItemsAndIndexes(const QVariantMap &items, const
QCOMPARE(it.value().typeId(), QMetaType::Int);
QString name = it.key();
int itemIndex = it.value().toInt();
- QVERIFY2(expectedIndexes.contains(itemIndex), QTest::toString(QString("Index %1 not found in expectedIndexes").arg(itemIndex)));
+ QVERIFY2(expectedIndexes.contains(itemIndex), qPrintable(QString("Index %1 not found in expectedIndexes").arg(itemIndex)));
if (model.name(itemIndex) != name)
qDebug() << itemIndex;
QCOMPARE(model.name(itemIndex), name);
@@ -4042,8 +4043,8 @@ void tst_qquickpositioners::matchItemLists(const QVariantList &itemLists, const
QVariantList current = itemLists[i].toList();
for (int j=0; j<current.size(); j++) {
QQuickItem *o = qobject_cast<QQuickItem*>(current[j].value<QObject*>());
- QVERIFY2(o, QTest::toString(QString("Invalid actual item at %1").arg(j)));
- QVERIFY2(expectedItems.contains(o), QTest::toString(QString("Cannot match item %1").arg(j)));
+ QVERIFY2(o, qPrintable(QString("Invalid actual item at %1").arg(j)));
+ QVERIFY2(expectedItems.contains(o), qPrintable(QString("Cannot match item %1").arg(j)));
}
QCOMPARE(current.size(), expectedItems.size());
}
diff --git a/tests/auto/quick/qquickrectangle/CMakeLists.txt b/tests/auto/quick/qquickrectangle/CMakeLists.txt
index ab1ca8ca29..2d12b1df71 100644
--- a/tests/auto/quick/qquickrectangle/CMakeLists.txt
+++ b/tests/auto/quick/qquickrectangle/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickrectangle Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickrectangle LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickrectangle/data/multi-radius.qml b/tests/auto/quick/qquickrectangle/data/multi-radius.qml
new file mode 100644
index 0000000000..18c74a2dd9
--- /dev/null
+++ b/tests/auto/quick/qquickrectangle/data/multi-radius.qml
@@ -0,0 +1,27 @@
+import QtQuick
+
+Item {
+ property alias firstRectangle: r1
+ property alias secondRectangle: r2
+ property alias thirdRectangle: r3
+ Rectangle {
+ id: r1
+ anchors.fill: parent
+ radius: 5
+ topLeftRadius: 10
+ bottomRightRadius: 2
+ }
+ Rectangle {
+ id: r2
+ anchors.fill: parent
+ radius: 5
+ topRightRadius: 10
+ bottomLeftRadius: 2
+ }
+ Rectangle {
+ id: r3
+ anchors.fill: parent
+ radius: 5
+ }
+}
+
diff --git a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
index d5520de682..4472be7d17 100644
--- a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
+++ b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtTest/QSignalSpy>
@@ -26,6 +26,7 @@ private slots:
void gradient_multiple();
void gradient_preset();
void antialiasing();
+ void multiRadius();
private:
QQmlEngine engine;
@@ -231,6 +232,82 @@ void tst_qquickrectangle::antialiasing()
QCOMPARE(spy.size(), 7);
}
+void tst_qquickrectangle::multiRadius()
+{
+ QQuickView view;
+ view.setSource(testFileUrl("multi-radius.qml"));
+ view.show();
+
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ QQuickRectangle *firstRect = qobject_cast<QQuickRectangle*>(view.rootObject()->property("firstRectangle").value<QObject*>());
+ QQuickRectangle *secondRect = qobject_cast<QQuickRectangle*>(view.rootObject()->property("secondRectangle").value<QObject*>());
+ QQuickRectangle *thirdRect = qobject_cast<QQuickRectangle*>(view.rootObject()->property("thirdRectangle").value<QObject*>());
+ QVERIFY(firstRect);
+ QVERIFY(secondRect);
+ QVERIFY(thirdRect);
+
+ QCOMPARE(firstRect->topLeftRadius(), 10.);
+ QCOMPARE(firstRect->topRightRadius(), 5.);
+ QCOMPARE(firstRect->bottomLeftRadius(), 5.);
+ QCOMPARE(firstRect->bottomRightRadius(), 2.);
+
+ QSignalSpy spytl(firstRect, SIGNAL(topLeftRadiusChanged()));
+ QSignalSpy spytr(firstRect, SIGNAL(topRightRadiusChanged()));
+ QSignalSpy spybl(firstRect, SIGNAL(bottomLeftRadiusChanged()));
+ QSignalSpy spybr(firstRect, SIGNAL(bottomRightRadiusChanged()));
+
+ firstRect->setRadius(12);
+
+ QCOMPARE(firstRect->topLeftRadius(), 10.);
+ QCOMPARE(firstRect->topRightRadius(), 12.);
+ QCOMPARE(firstRect->bottomLeftRadius(), 12.);
+ QCOMPARE(firstRect->bottomRightRadius(), 2.);
+
+ QCOMPARE(spytl.size(), 0);
+ QCOMPARE(spytr.size(), 1);
+ QCOMPARE(spybl.size(), 1);
+ QCOMPARE(spybr.size(), 0);
+
+ firstRect->resetTopLeftRadius();
+ firstRect->resetBottomRightRadius();
+ QCOMPARE(firstRect->topRightRadius(), 12.);
+ QCOMPARE(firstRect->bottomLeftRadius(), 12.);
+
+ QCOMPARE(secondRect->topLeftRadius(), 5.);
+ QCOMPARE(secondRect->topRightRadius(), 10.);
+ QCOMPARE(secondRect->bottomLeftRadius(), 2.);
+ QCOMPARE(secondRect->bottomRightRadius(), 5.);
+
+ QSignalSpy spytl2(secondRect, SIGNAL(topLeftRadiusChanged()));
+ QSignalSpy spytr2(secondRect, SIGNAL(topRightRadiusChanged()));
+ QSignalSpy spybl2(secondRect, SIGNAL(bottomLeftRadiusChanged()));
+ QSignalSpy spybr2(secondRect, SIGNAL(bottomRightRadiusChanged()));
+
+ secondRect->setRadius(12);
+
+ QCOMPARE(secondRect->topLeftRadius(), 12.);
+ QCOMPARE(secondRect->topRightRadius(), 10.);
+ QCOMPARE(secondRect->bottomLeftRadius(), 2.);
+ QCOMPARE(secondRect->bottomRightRadius(), 12.);
+
+ QCOMPARE(spytl2.size(), 1);
+ QCOMPARE(spytr2.size(), 0);
+ QCOMPARE(spybl2.size(), 0);
+ QCOMPARE(spybr2.size(), 1);
+
+ secondRect->resetTopRightRadius();
+ secondRect->resetBottomLeftRadius();
+ QCOMPARE(secondRect->topRightRadius(), 12.);
+ QCOMPARE(secondRect->bottomLeftRadius(), 12.);
+
+ QCOMPARE(thirdRect->topLeftRadius(), 5.);
+ QCOMPARE(thirdRect->topRightRadius(), 5.);
+ QCOMPARE(thirdRect->bottomLeftRadius(), 5.);
+ QCOMPARE(thirdRect->bottomRightRadius(), 5.);
+
+}
+
QTEST_MAIN(tst_qquickrectangle)
#include "tst_qquickrectangle.moc"
diff --git a/tests/auto/quick/qquickrendercontrol/CMakeLists.txt b/tests/auto/quick/qquickrendercontrol/CMakeLists.txt
index ad4e89e184..3dd086f42b 100644
--- a/tests/auto/quick/qquickrendercontrol/CMakeLists.txt
+++ b/tests/auto/quick/qquickrendercontrol/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickrendercontrol Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickrendercontrol LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickrendercontrol/data/rect.qml b/tests/auto/quick/qquickrendercontrol/data/rect.qml
index 82aeccbff8..bd4d7c15af 100644
--- a/tests/auto/quick/qquickrendercontrol/data/rect.qml
+++ b/tests/auto/quick/qquickrendercontrol/data/rect.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/qquickrendercontrol/data/rect_depth.qml b/tests/auto/quick/qquickrendercontrol/data/rect_depth.qml
new file mode 100644
index 0000000000..49709aa0ae
--- /dev/null
+++ b/tests/auto/quick/qquickrendercontrol/data/rect_depth.qml
@@ -0,0 +1,28 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Rectangle {
+ width: 200
+ height: 200
+ color: "steelblue"
+ Rectangle {
+ id: r
+ width: 150
+ height: 150
+ anchors.centerIn: parent
+ color: "palegreen"
+ NumberAnimation on rotation { from: 0; to: 360; duration: 5000; loops: -1 }
+ }
+ Rectangle {
+ width: 100
+ height: 100
+ color: "red"
+ z: -1 // not visible as it is completely below, but this only works if depth testing works (and there's a depth buffer) since these are opaque items
+ }
+ Text {
+ text: "Hello World\n\nrotation=" + Math.round(r.rotation)
+ anchors.centerIn: parent
+ }
+}
diff --git a/tests/auto/quick/qquickrendercontrol/tst_qquickrendercontrol.cpp b/tests/auto/quick/qquickrendercontrol/tst_qquickrendercontrol.cpp
index 2d56312f9d..938f0a12b2 100644
--- a/tests/auto/quick/qquickrendercontrol/tst_qquickrendercontrol.cpp
+++ b/tests/auto/quick/qquickrendercontrol/tst_qquickrendercontrol.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
@@ -19,8 +19,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qpa/qplatformintegration.h>
-#include <QtGui/private/qrhi_p.h>
-#include <QtQuick/private/qquickrendercontrol_p.h>
+#include <rhi/qrhi.h>
#if QT_CONFIG(vulkan)
#include <QVulkanInstance>
@@ -63,6 +62,7 @@ private slots:
void renderAndReadBackWithRhi_data();
void renderAndReadBackWithRhi();
void renderAndReadBackWithVulkanNative();
+ void renderAndReadBackWithVulkanAndCustomDepthTexture();
private:
#if QT_CONFIG(vulkan)
@@ -105,30 +105,32 @@ void tst_RenderControl::renderAndReadBackWithRhi_data()
QTest::addColumn<QSGRendererInterface::GraphicsApi>("api");
#if QT_CONFIG(opengl)
- QTest::newRow("OpenGL") << QSGRendererInterface::OpenGLRhi;
+ QTest::newRow("OpenGL") << QSGRendererInterface::OpenGL;
#endif
#if QT_CONFIG(vulkan)
- QTest::newRow("Vulkan") << QSGRendererInterface::VulkanRhi;
+ QTest::newRow("Vulkan") << QSGRendererInterface::Vulkan;
#endif
#ifdef Q_OS_WIN
- QTest::newRow("D3D11") << QSGRendererInterface::Direct3D11Rhi;
+ QTest::newRow("D3D11") << QSGRendererInterface::Direct3D11;
+ QTest::newRow("D3D12") << QSGRendererInterface::Direct3D12;
#endif
-#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
- QTest::newRow("Metal") << QSGRendererInterface::MetalRhi;
+#if QT_CONFIG(metal)
+ QTest::newRow("Metal") << QSGRendererInterface::Metal;
#endif
}
void tst_RenderControl::renderAndReadBackWithRhi()
{
QFETCH(QSGRendererInterface::GraphicsApi, api);
+
#if QT_CONFIG(vulkan)
- if (api == QSGRendererInterface::VulkanRhi && !vulkanInstance.isValid())
+ if (api == QSGRendererInterface::Vulkan && !vulkanInstance.isValid())
QSKIP("Skipping Vulkan-based QRhi readback test due to failing to create a VkInstance");
#endif
#ifdef Q_OS_ANDROID
// QTBUG-102780
- if (api == QSGRendererInterface::VulkanRhi)
+ if (api == QSGRendererInterface::Vulkan)
QSKIP("Vulkan-based rendering tests on Android are flaky.");
#endif
@@ -142,7 +144,7 @@ void tst_RenderControl::renderAndReadBackWithRhi()
QScopedPointer<QQuickRenderControl> renderControl(new QQuickRenderControl);
QScopedPointer<QQuickWindow> quickWindow(new QQuickWindow(renderControl.data()));
#if QT_CONFIG(vulkan)
- if (api == QSGRendererInterface::VulkanRhi)
+ if (api == QSGRendererInterface::Vulkan)
quickWindow->setVulkanInstance(&vulkanInstance);
#endif
@@ -181,7 +183,7 @@ void tst_RenderControl::renderAndReadBackWithRhi()
// failed. The exception for now is OpenGL - that should (usually) work.
if (!initSuccess) {
#if QT_CONFIG(opengl)
- if (api != QSGRendererInterface::OpenGLRhi
+ if (api != QSGRendererInterface::OpenGL
|| !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL))
#endif
{
@@ -193,13 +195,7 @@ void tst_RenderControl::renderAndReadBackWithRhi()
QCOMPARE(quickWindow->rendererInterface()->graphicsApi(), api);
- // What comes now is technically cheating - as long as QRhi is not a public
- // API this is not something applications can follow doing. However, it
- // allows us to test out the pipeline without having to write 4 different
- // native (Vulkan, Metal, D3D11, OpenGL) implementations of all what's below.
-
- QQuickRenderControlPrivate *rd = QQuickRenderControlPrivate::get(renderControl.data());
- QRhi *rhi = rd->rhi;
+ QRhi *rhi = renderControl->rhi();
Q_ASSERT(rhi);
const QSize size = rootItem->size().toSize();
@@ -302,7 +298,7 @@ void tst_RenderControl::renderAndReadBackWithRhi()
};
QRhiResourceUpdateBatch *readbackBatch = rhi->nextResourceUpdateBatch();
readbackBatch->readBackTexture(tex.data(), &readResult);
- rd->cb->resourceUpdate(readbackBatch);
+ renderControl->commandBuffer()->resourceUpdate(readbackBatch);
// our frame is done, submit
renderControl->endFrame();
@@ -360,7 +356,7 @@ void tst_RenderControl::renderAndReadBackWithVulkanNative()
if (!vulkanInstance.isValid())
QSKIP("Skipping native Vulkan test due to failing to create a VkInstance");
- QQuickWindow::setGraphicsApi(QSGRendererInterface::VulkanRhi);
+ QQuickWindow::setGraphicsApi(QSGRendererInterface::Vulkan);
// We will create our own VkDevice and friends, which will then get used by
// Qt Quick as well (instead of creating its own objects), so this is a test
@@ -666,21 +662,6 @@ void tst_RenderControl::renderAndReadBackWithVulkanNative()
QVERIFY(qAbs(qGreen(background) - 130) < maxFuzz);
QVERIFY(qAbs(qBlue(background) - 180) < maxFuzz);
- // after about 1.25 seconds (animation time, one iteration is 16 ms
- // thanks to our custom animation driver) the rectangle reaches a 90
- // degree rotation, that should be frame 76
- if (frame <= 2 || (frame >= 76 && frame <= 80)) {
- QRgb c = img.pixel(28, 28); // rectangle
- QVERIFY(qAbs(qRed(c) - 152) < maxFuzz);
- QVERIFY(qAbs(qGreen(c) - 251) < maxFuzz);
- QVERIFY(qAbs(qBlue(c) - 152) < maxFuzz);
- } else {
- QRgb c = img.pixel(28, 28); // background because rectangle got rotated so this pixel is not covered by it
- QVERIFY(qAbs(qRed(c) - 70) < maxFuzz);
- QVERIFY(qAbs(qGreen(c) - 130) < maxFuzz);
- QVERIFY(qAbs(qBlue(c) - 180) < maxFuzz);
- }
-
img = QImage();
df->vkUnmapMemory(dev, bufMem);
}
@@ -702,6 +683,151 @@ void tst_RenderControl::renderAndReadBackWithVulkanNative()
#endif
}
+void tst_RenderControl::renderAndReadBackWithVulkanAndCustomDepthTexture()
+{
+#if QT_CONFIG(vulkan)
+ if (!vulkanInstance.isValid())
+ QSKIP("Skipping native Vulkan test due to failing to create a VkInstance");
+
+ QQuickWindow::setGraphicsApi(QSGRendererInterface::Vulkan);
+
+#ifdef Q_OS_ANDROID
+ if (QQuickWindow::graphicsApi() == QSGRendererInterface::Vulkan)
+ QSKIP("Vulkan support is broken in Android emulator, skipping");
+#endif
+
+ QScopedPointer<QQuickRenderControl> renderControl(new QQuickRenderControl);
+ QScopedPointer<QQuickWindow> quickWindow(new QQuickWindow(renderControl.data()));
+
+ quickWindow->setVulkanInstance(&vulkanInstance);
+
+ QScopedPointer<QQmlEngine> qmlEngine(new QQmlEngine);
+ QScopedPointer<QQmlComponent> qmlComponent(new QQmlComponent(qmlEngine.data(),
+ testFileUrl(QLatin1String("rect_depth.qml"))));
+ QVERIFY(!qmlComponent->isLoading());
+ if (qmlComponent->isError()) {
+ for (const QQmlError &error : qmlComponent->errors())
+ qWarning() << error.url() << error.line() << error;
+ }
+ QVERIFY(!qmlComponent->isError());
+
+ QObject *rootObject = qmlComponent->create();
+ if (qmlComponent->isError()) {
+ for (const QQmlError &error : qmlComponent->errors())
+ qWarning() << error.url() << error.line() << error;
+ }
+ QVERIFY(!qmlComponent->isError());
+
+ QQuickItem *rootItem = qobject_cast<QQuickItem *>(rootObject);
+ QVERIFY(rootItem);
+ static const QSize ITEM_SIZE = QSize(200, 200);
+ QCOMPARE(rootItem->size(), ITEM_SIZE);
+
+ quickWindow->contentItem()->setSize(rootItem->size());
+ quickWindow->setGeometry(0, 0, rootItem->width(), rootItem->height());
+
+ rootItem->setParentItem(quickWindow->contentItem());
+
+ const bool initSuccess = renderControl->initialize();
+
+ if (!initSuccess)
+ QSKIP("Could not initialize graphics, perhaps unsupported graphics API, skipping");
+
+ QRhi *rhi = renderControl->rhi();
+ Q_ASSERT(rhi);
+
+ const QSize size = rootItem->size().toSize();
+ QScopedPointer<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8, size, 1,
+ QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
+ QVERIFY(tex->create());
+
+ // In this test we use QRhiTexture to create resources but pull out the
+ // native VkImage and pass that in via fromVulkanImage(). This is to
+ // exercise additional features, such as setting a custom depth texture,
+ // which is not available (not relevant) when using fromRhiRenderTarget().
+ // In particular, this setup (fromVulkanImage + setDepthTexture) exercises
+ // what we get in Qt Quick 3D with OpenXR, where rendering happens into a
+ // XrSwapchain-provided color and depth texture. (granted, here we only
+ // exercise the non-multiview, non-MSAA case).
+
+ QScopedPointer<QRhiTexture> depthTex(rhi->newTexture(QRhiTexture::D24S8, size, 1, QRhiTexture::RenderTarget));
+ QVERIFY(depthTex->create());
+
+ QQuickRenderTarget rt = QQuickRenderTarget::fromVulkanImage(VkImage(tex->nativeTexture().object),
+ VkImageLayout(tex->nativeTexture().layout),
+ VK_FORMAT_R8G8B8A8_UNORM,
+ VK_FORMAT_R8G8B8A8_UNORM,
+ size,
+ 1,
+ 0,
+ {});
+ rt.setDepthTexture(depthTex.data());
+ quickWindow->setRenderTarget(rt);
+
+ QSize currentSize = size;
+
+ for (int frame = 0; frame < 100; ++frame) {
+ QCoreApplication::processEvents();
+
+ if (frame > 0)
+ animDriver->advance();
+
+ renderControl->polishItems();
+
+ renderControl->beginFrame();
+
+ renderControl->sync();
+ renderControl->render();
+
+ bool readCompleted = false;
+ QRhiReadbackResult readResult;
+ QImage result;
+ readResult.completed = [&readCompleted, &readResult, &result, &rhi] {
+ readCompleted = true;
+ QImage wrapperImage(reinterpret_cast<const uchar *>(readResult.data.constData()),
+ readResult.pixelSize.width(), readResult.pixelSize.height(),
+ QImage::Format_RGBA8888_Premultiplied);
+ if (rhi->isYUpInFramebuffer())
+ result = wrapperImage.mirrored();
+ else
+ result = wrapperImage.copy();
+ };
+ QRhiResourceUpdateBatch *readbackBatch = rhi->nextResourceUpdateBatch();
+ readbackBatch->readBackTexture(tex.data(), &readResult);
+ renderControl->commandBuffer()->resourceUpdate(readbackBatch);
+
+ renderControl->endFrame();
+
+ QVERIFY(readCompleted);
+
+ QImage img = result;
+ QVERIFY(!img.isNull());
+ QCOMPARE(img.size(), currentSize);
+
+ const int maxFuzz = 2;
+
+ // The scene is: background, rectangle, text
+ // where rectangle rotates
+
+ QRgb background = img.pixel(5, 5);
+
+ // with rect_depth.qml the following would not pass if the depth buffering
+ // was not functional (because the red rectangle with z: -1 would still
+ // go on top, not below)
+ QVERIFY(qAbs(qRed(background) - 70) < maxFuzz);
+ QVERIFY(qAbs(qGreen(background) - 130) < maxFuzz);
+ QVERIFY(qAbs(qBlue(background) - 180) < maxFuzz);
+
+ background = img.pixel(195, 195);
+ QVERIFY(qAbs(qRed(background) - 70) < maxFuzz);
+ QVERIFY(qAbs(qGreen(background) - 130) < maxFuzz);
+ QVERIFY(qAbs(qBlue(background) - 180) < maxFuzz);
+ }
+#else
+ QSKIP("No Vulkan support in Qt build, skipping native Vulkan test");
+#endif
+}
+
#include "tst_qquickrendercontrol.moc"
QTEST_MAIN(tst_RenderControl)
diff --git a/tests/auto/quick/qquickrepeater/CMakeLists.txt b/tests/auto/quick/qquickrepeater/CMakeLists.txt
index 473e58dd81..91a55a6609 100644
--- a/tests/auto/quick/qquickrepeater/CMakeLists.txt
+++ b/tests/auto/quick/qquickrepeater/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickrepeater Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickrepeater LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
index 5a6498a5d7..821770bae7 100644
--- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
+++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
@@ -94,12 +94,12 @@ tst_QQuickRepeater::tst_QQuickRepeater()
void tst_QQuickRepeater::numberModel()
{
- QQuickView *window = createView();
+ std::unique_ptr<QQuickView> window { createView() };
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testData", 5);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ std::unique_ptr<TestObject> testObject = std::make_unique<TestObject>();
+ ctxt->setContextProperty("testObject", testObject.get());
window->setSource(testFileUrl("intmodel.qml"));
qApp->processEvents();
@@ -121,9 +121,6 @@ void tst_QQuickRepeater::numberModel()
ctxt->setContextProperty("testData", -1234);
QCOMPARE(repeater->parentItem()->childItems().size(), 1);
-
- delete testObject;
- delete window;
}
void tst_QQuickRepeater::objectList_data()
@@ -149,8 +146,11 @@ public:
void tst_QQuickRepeater::objectList()
{
QFETCH(QUrl, filename);
- QQuickView *window = createView();
+ std::unique_ptr<QQuickView> window { createView() };
QObjectList data;
+ auto cleanup = qScopeGuard([&]() {
+ qDeleteAll(data);
+ });
for (int i=0; i<100; i++)
data << new MyObject(i);
@@ -175,9 +175,6 @@ void tst_QQuickRepeater::objectList()
ctxt->setContextProperty("testData", QVariant::fromValue(data));
QCOMPARE(addedSpy.size(), data.size());
QCOMPARE(removedSpy.size(), data.size());
-
- qDeleteAll(data);
- delete window;
}
/*
@@ -187,7 +184,7 @@ elements to test this.
*/
void tst_QQuickRepeater::stringList()
{
- QQuickView *window = createView();
+ std::unique_ptr<QQuickView> window { createView() };
QStringList data;
data << "One";
@@ -233,16 +230,14 @@ void tst_QQuickRepeater::stringList()
}
}
QVERIFY(saw_repeater);
-
- delete window;
}
void tst_QQuickRepeater::dataModel_adding()
{
- QQuickView *window = createView();
+ std::unique_ptr<QQuickView> window { createView() };
QQmlContext *ctxt = window->rootContext();
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ std::unique_ptr<TestObject> testObject = std::make_unique<TestObject>();
+ ctxt->setContextProperty("testObject", testObject.get());
QaimModel testModel;
ctxt->setContextProperty("testData", &testModel);
@@ -307,18 +302,17 @@ void tst_QQuickRepeater::dataModel_adding()
addedSpy.clear();
countSpy.clear();
- delete testObject;
+ testObject.reset();
addedSpy.clear();
countSpy.clear();
- delete window;
}
void tst_QQuickRepeater::dataModel_removing()
{
- QQuickView *window = createView();
+ std::unique_ptr<QQuickView> window { createView() };
QQmlContext *ctxt = window->rootContext();
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ auto testObject = std::make_unique<TestObject>();
+ ctxt->setContextProperty("testObject", testObject.get());
QaimModel testModel;
testModel.addItem("one", "1");
@@ -376,17 +370,14 @@ void tst_QQuickRepeater::dataModel_removing()
QCOMPARE(removedSpy.at(0).at(0).toInt(), 1);
QCOMPARE(removedSpy.at(0).at(1).value<QQuickItem*>(), item);
removedSpy.clear();
-
- delete testObject;
- delete window;
}
void tst_QQuickRepeater::dataModel_changes()
{
- QQuickView *window = createView();
+ std::unique_ptr<QQuickView> window { createView() };
QQmlContext *ctxt = window->rootContext();
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ auto testObject = std::make_unique<TestObject>();
+ ctxt->setContextProperty("testObject", testObject.get());
QaimModel testModel;
testModel.addItem("one", "1");
@@ -416,17 +407,14 @@ void tst_QQuickRepeater::dataModel_changes()
text = findItem<QQuickText>(window->rootObject(), "myNumber", 1);
QVERIFY(text);
QCOMPARE(text->text(), QString("_2"));
-
- delete testObject;
- delete window;
}
void tst_QQuickRepeater::itemModel()
{
- QQuickView *window = createView();
+ std::unique_ptr<QQuickView> window { createView() };
QQmlContext *ctxt = window->rootContext();
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ auto testObject = std::make_unique<TestObject>();
+ ctxt->setContextProperty("testObject", testObject.get());
window->setSource(testFileUrl("itemlist.qml"));
qApp->processEvents();
@@ -464,14 +452,11 @@ void tst_QQuickRepeater::itemModel()
testObject->setUseModel(false);
QCOMPARE(container->childItems().size(), 1);
-
- delete testObject;
- delete window;
}
void tst_QQuickRepeater::resetModel()
{
- QQuickView *window = createView();
+ std::unique_ptr<QQuickView> window { createView() };
QStringList dataA;
for (int i=0; i<10; i++)
@@ -533,8 +518,6 @@ void tst_QQuickRepeater::resetModel()
countSpy.clear();
removedSpy.clear();
addedSpy.clear();
-
- delete window;
}
// QTBUG-17156
@@ -543,7 +526,8 @@ void tst_QQuickRepeater::modelChanged()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("modelChanged.qml"));
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
+ std::unique_ptr<QObject> root { component.create() };
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(root.get());
QVERIFY(rootObject);
QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater");
QVERIFY(repeater);
@@ -557,8 +541,6 @@ void tst_QQuickRepeater::modelChanged()
QCOMPARE(repeater->count(), 10);
QCOMPARE(repeater->property("itemsCount").toInt(), 10);
QCOMPARE(repeater->property("itemsFound").toList().size(), 10);
-
- delete rootObject;
}
void tst_QQuickRepeater::modelReset()
@@ -645,7 +627,8 @@ void tst_QQuickRepeater::modelCleared()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("modelCleared.qml"));
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
+ std::unique_ptr<QObject> root { component.create() };
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(root.get());
QVERIFY(rootObject);
QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater");
@@ -655,8 +638,6 @@ void tst_QQuickRepeater::modelCleared()
QQmlTestMessageHandler messageHandler;
repeater->setModel(0);
QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
-
- delete rootObject;
}
void tst_QQuickRepeater::properties()
@@ -664,7 +645,8 @@ void tst_QQuickRepeater::properties()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("properties.qml"));
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
+ std::unique_ptr<QObject> root { component.create() };
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(root.get());
QVERIFY(rootObject);
QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater");
@@ -685,13 +667,11 @@ void tst_QQuickRepeater::properties()
QCOMPARE(delegateSpy.size(),1);
repeater->setDelegate(&rectComponent);
QCOMPARE(delegateSpy.size(),1);
-
- delete rootObject;
}
void tst_QQuickRepeater::asynchronous()
{
- QQuickView *window = createView();
+ std::unique_ptr<QQuickView> window { createView() };
window->show();
QQmlIncubationController controller;
window->engine()->setIncubationController(&controller);
@@ -742,8 +722,6 @@ void tst_QQuickRepeater::asynchronous()
QQuickItem *item = findItem<QQuickItem>(container, name);
QTRY_COMPARE(item->y(), i * 50.0);
}
-
- delete window;
}
void tst_QQuickRepeater::initParent()
@@ -751,7 +729,8 @@ void tst_QQuickRepeater::initParent()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("initparent.qml"));
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
+ std::unique_ptr<QObject> root { component.create() };
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(root.get());
QVERIFY(rootObject);
QCOMPARE(qvariant_cast<QQuickItem*>(rootObject->property("parentItem")), rootObject);
@@ -763,7 +742,8 @@ void tst_QQuickRepeater::dynamicModelCrash()
QQmlComponent component(&engine, testFileUrl("dynamicmodelcrash.qml"));
// Don't crash
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
+ std::unique_ptr<QObject> root { component.create() };
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(root.get());
QVERIFY(rootObject);
QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "rep");
@@ -776,10 +756,9 @@ void tst_QQuickRepeater::visualItemModelCrash()
// This used to crash because the model would get
// deleted before the repeater, leading to double-deletion
// of the items.
- QQuickView *window = createView();
+ std::unique_ptr<QQuickView> window { createView() };
window->setSource(testFileUrl("visualitemmodel.qml"));
qApp->processEvents();
- delete window;
}
class BadModel : public QAbstractListModel
@@ -859,7 +838,8 @@ void tst_QQuickRepeater::clearRemovalOrder()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("clearremovalorder.qml"));
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
+ std::unique_ptr<QObject> root { component.create() };
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(root.get());
QVERIFY(rootObject);
QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater");
@@ -883,8 +863,6 @@ void tst_QQuickRepeater::clearRemovalOrder()
QCOMPARE(removedSpy.at(0).at(0).toInt(), 2);
QCOMPARE(removedSpy.at(1).at(0).toInt(), 1);
QCOMPARE(removedSpy.at(2).at(0).toInt(), 0);
-
- delete rootObject;
}
void tst_QQuickRepeater::destroyCount()
@@ -892,7 +870,8 @@ void tst_QQuickRepeater::destroyCount()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("destroycount.qml"));
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
+ std::unique_ptr<QObject> root { component.create() };
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(root.get());
QVERIFY(rootObject);
QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater");
@@ -927,7 +906,8 @@ void tst_QQuickRepeater::stackingOrder()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("stackingorder.qml"));
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
+ std::unique_ptr<QObject> root { component.create() };
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(root.get());
QVERIFY(rootObject);
QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater");
@@ -956,7 +936,8 @@ void tst_QQuickRepeater::objectModel()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("objectmodel.qml"));
- QQuickItem *positioner = qobject_cast<QQuickItem *>(component.create());
+ std::unique_ptr<QObject> root { component.create() };
+ QQuickItem *positioner = qobject_cast<QQuickItem *>(root.get());
QVERIFY(positioner);
QQuickRepeater *repeater = findItem<QQuickRepeater>(positioner, "repeater");
@@ -994,8 +975,6 @@ void tst_QQuickRepeater::objectModel()
model->clear();
QCOMPARE(model->count(), 0);
QCOMPARE(repeater->count(), 0);
-
- delete positioner;
}
class Ctrl : public QObject
@@ -1012,7 +991,7 @@ public:
void tst_QQuickRepeater::QTBUG54859_asynchronousMove()
{
Ctrl ctrl;
- QQuickView* view = createView();
+ std::unique_ptr<QQuickView> view { createView() };
view->rootContext()->setContextProperty("ctrl", &ctrl);
view->setSource(testFileUrl("asynchronousMove.qml"));
view->show();
@@ -1077,8 +1056,7 @@ void tst_QQuickRepeater::ownership()
QVERIFY(!QQmlData::keepAliveDuringGarbageCollection(aim.get()));
- engine.collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+ gc(engine);
QVERIFY(modelGuard);
@@ -1096,8 +1074,7 @@ void tst_QQuickRepeater::ownership()
QVERIFY(!QQmlData::keepAliveDuringGarbageCollection(delegate.get()));
- engine.collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+ gc(engine);
QVERIFY(delegateGuard);
@@ -1110,8 +1087,7 @@ void tst_QQuickRepeater::ownership()
delegate.release();
aim.release();
- engine.collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+ gc(engine);
QVERIFY(!delegateGuard);
QVERIFY(!modelGuard);
diff --git a/tests/auto/quick/qquickitemrhiintegration/BLACKLIST b/tests/auto/quick/qquickrhiitem/BLACKLIST
index 03e5bc8c1d..03e5bc8c1d 100644
--- a/tests/auto/quick/qquickitemrhiintegration/BLACKLIST
+++ b/tests/auto/quick/qquickrhiitem/BLACKLIST
diff --git a/tests/auto/quick/qquickitemrhiintegration/CMakeLists.txt b/tests/auto/quick/qquickrhiitem/CMakeLists.txt
index 8f918dd753..ef9858ea6d 100644
--- a/tests/auto/quick/qquickitemrhiintegration/CMakeLists.txt
+++ b/tests/auto/quick/qquickrhiitem/CMakeLists.txt
@@ -1,16 +1,21 @@
-# Copyright (C) 2022 The Qt Company Ltd.
+# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickrhiitem LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
data/*)
list(APPEND test_data ${test_data_glob})
-qt_internal_add_test(tst_qquickitemrhiintegration
+qt_internal_add_test(tst_qquickrhiitem
SOURCES
- tst_qquickitemrhiintegration.cpp
- rhiitem.cpp rhiitem.h rhiitem_p.h
+ tst_qquickrhiitem.cpp
testrhiitem.cpp testrhiitem.h
LIBRARIES
Qt::CorePrivate
@@ -22,17 +27,17 @@ qt_internal_add_test(tst_qquickitemrhiintegration
TESTDATA ${test_data}
)
-qt_internal_extend_target(tst_qquickitemrhiintegration CONDITION ANDROID OR IOS
+qt_internal_extend_target(tst_qquickrhiitem CONDITION ANDROID OR IOS
DEFINES
QT_QMLTEST_DATADIR=":/data"
)
-qt_internal_extend_target(tst_qquickitemrhiintegration CONDITION NOT ANDROID AND NOT IOS
+qt_internal_extend_target(tst_qquickrhiitem CONDITION NOT ANDROID AND NOT IOS
DEFINES
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
)
-qt_internal_add_shaders(tst_qquickitemrhiintegration "shaders"
+qt_internal_add_shaders(tst_qquickrhiitem "shaders"
PREFIX
"/"
FILES
@@ -40,7 +45,8 @@ qt_internal_add_shaders(tst_qquickitemrhiintegration "shaders"
"texture.frag"
)
-qt_add_qml_module(tst_qquickitemrhiintegration
- URI TestQquickitemrhiintegration
- AUTO_RESOURCE_PREFIX
+qt_policy(SET QTP0001 NEW)
+
+qt_add_qml_module(tst_qquickrhiitem
+ URI Testqquickrhiitem
)
diff --git a/tests/auto/quick/qquickitemrhiintegration/data/test.qml b/tests/auto/quick/qquickrhiitem/data/test.qml
index 8ffbe0d6ed..92fbfdb016 100644
--- a/tests/auto/quick/qquickitemrhiintegration/data/test.qml
+++ b/tests/auto/quick/qquickrhiitem/data/test.qml
@@ -1,8 +1,8 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
-import TestQquickitemrhiintegration
+import Testqquickrhiitem
Item {
width: 640
@@ -14,13 +14,15 @@ Item {
font.pixelSize: 16
property int api: GraphicsInfo.api
text: {
- if (GraphicsInfo.api === GraphicsInfo.OpenGLRhi)
+ if (GraphicsInfo.api === GraphicsInfo.OpenGL)
"OpenGL on QRhi";
- else if (GraphicsInfo.api === GraphicsInfo.Direct3D11Rhi)
+ else if (GraphicsInfo.api === GraphicsInfo.Direct3D11)
"D3D11 on QRhi";
- else if (GraphicsInfo.api === GraphicsInfo.VulkanRhi)
+ else if (GraphicsInfo.api === GraphicsInfo.Direct3D12)
+ "D3D12 on QRhi";
+ else if (GraphicsInfo.api === GraphicsInfo.Vulkan)
"Vulkan on QRhi";
- else if (GraphicsInfo.api === GraphicsInfo.MetalRhi)
+ else if (GraphicsInfo.api === GraphicsInfo.Metal)
"Metal on QRhi";
else if (GraphicsInfo.api === GraphicsInfo.Null)
"Null on QRhi";
@@ -34,5 +36,6 @@ Item {
width: 400
height: 400
color: "red"
+ objectName: "rhiitem"
}
}
diff --git a/tests/auto/quick/qquickitemrhiintegration/testrhiitem.cpp b/tests/auto/quick/qquickrhiitem/testrhiitem.cpp
index 926bb53bcf..65fc329630 100644
--- a/tests/auto/quick/qquickitemrhiintegration/testrhiitem.cpp
+++ b/tests/auto/quick/qquickrhiitem/testrhiitem.cpp
@@ -1,41 +1,33 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testrhiitem.h"
#include <QFile>
static const QSize TEX_SIZE(512, 512);
-void TestRenderer::initialize(QRhi *rhi, QRhiTexture *outputTexture)
+void TestRenderer::initialize(QRhiCommandBuffer *)
{
- 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_rhi != rhi()) {
+ m_rhi = rhi();
+ scene = {};
}
- 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 (m_sampleCount != renderTarget()->sampleCount()) {
+ m_sampleCount = renderTarget()->sampleCount();
+ scene = {};
}
if (!scene.vbuf)
initScene();
- const QSize outputSize = m_output->pixelSize();
+ const QSize outputSize = renderTarget()->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());
+ scene.resourceUpdates->updateDynamicBuffer(scene.ubuf.get(), 0, 64, scene.mvp.constData());
}
static QShader getShader(const QString &name)
@@ -55,7 +47,7 @@ void TestRenderer::updateTexture()
if (!scene.resourceUpdates)
scene.resourceUpdates = m_rhi->nextResourceUpdateBatch();
- scene.resourceUpdates->uploadTexture(scene.tex.data(), img);
+ scene.resourceUpdates->uploadTexture(scene.tex.get(), img);
}
void TestRenderer::initScene()
@@ -70,13 +62,13 @@ void TestRenderer::initScene()
scene.vbuf->create();
scene.resourceUpdates = m_rhi->nextResourceUpdateBatch();
- scene.resourceUpdates->uploadStaticBuffer(scene.vbuf.data(), tri);
+ scene.resourceUpdates->uploadStaticBuffer(scene.vbuf.get(), 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.resourceUpdates->updateDynamicBuffer(scene.ubuf.get(), 64, 4, &flip);
scene.tex.reset(m_rhi->newTexture(QRhiTexture::RGBA8, TEX_SIZE));
scene.tex->create();
@@ -87,8 +79,8 @@ void TestRenderer::initScene()
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())
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, scene.ubuf.get()),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, scene.tex.get(), scene.sampler.get())
});
scene.srb->create();
@@ -115,12 +107,15 @@ void TestRenderer::initScene()
{ 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->setSampleCount(m_sampleCount);
+ scene.ps->setShaderResourceBindings(scene.srb.get());
+ scene.ps->setRenderPassDescriptor(renderTarget()->renderPassDescriptor());
scene.ps->create();
+
+ updateTexture();
}
-void TestRenderer::synchronize(RhiItem *rhiItem)
+void TestRenderer::synchronize(QQuickRhiItem *rhiItem)
{
TestRhiItem *item = static_cast<TestRhiItem *>(rhiItem);
if (item->color() != itemData.color) {
@@ -136,14 +131,14 @@ void TestRenderer::render(QRhiCommandBuffer *cb)
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->beginPass(renderTarget(), clearColor, { 1.0f, 0 }, rub);
- cb->setGraphicsPipeline(scene.ps.data());
- const QSize outputSize = m_output->pixelSize();
+ cb->setGraphicsPipeline(scene.ps.get());
+ const QSize outputSize = renderTarget()->pixelSize();
cb->setViewport(QRhiViewport(0, 0, outputSize.width(), outputSize.height()));
cb->setShaderResources();
const QRhiCommandBuffer::VertexInput vbufBindings[] = {
- { scene.vbuf.data(), 0 },
+ { scene.vbuf.get(), 0 },
};
cb->setVertexInput(0, 1, vbufBindings);
cb->draw(3);
diff --git a/tests/auto/quick/qquickrhiitem/testrhiitem.h b/tests/auto/quick/qquickrhiitem/testrhiitem.h
new file mode 100644
index 0000000000..6778f96d7b
--- /dev/null
+++ b/tests/auto/quick/qquickrhiitem/testrhiitem.h
@@ -0,0 +1,61 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TESTRHIITEM_H
+#define TESTRHIITEM_H
+
+#include <QQuickRhiItem>
+#include <rhi/qrhi.h>
+
+class TestRenderer : public QQuickRhiItemRenderer
+{
+protected:
+ void initialize(QRhiCommandBuffer *cb) override;
+ void synchronize(QQuickRhiItem *item) override;
+ void render(QRhiCommandBuffer *cb) override;
+
+private:
+ QRhi *m_rhi = nullptr;
+ int m_sampleCount = 1;
+
+ struct {
+ QRhiResourceUpdateBatch *resourceUpdates = nullptr;
+ std::unique_ptr<QRhiBuffer> vbuf;
+ std::unique_ptr<QRhiBuffer> ubuf;
+ std::unique_ptr<QRhiShaderResourceBindings> srb;
+ std::unique_ptr<QRhiGraphicsPipeline> ps;
+ std::unique_ptr<QRhiSampler> sampler;
+ std::unique_ptr<QRhiTexture> tex;
+ QMatrix4x4 mvp;
+ } scene;
+
+ struct {
+ QColor color;
+ } itemData;
+
+ void initScene();
+ void updateTexture();
+
+ friend class tst_QQuickRhiItem;
+};
+
+class TestRhiItem : public QQuickRhiItem
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(TestRhiItem)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+
+public:
+ QQuickRhiItemRenderer *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/qquickrhiitem/texture.frag
index a7b8bce0ad..a7b8bce0ad 100644
--- a/tests/auto/quick/qquickitemrhiintegration/texture.frag
+++ b/tests/auto/quick/qquickrhiitem/texture.frag
diff --git a/tests/auto/quick/qquickitemrhiintegration/texture.vert b/tests/auto/quick/qquickrhiitem/texture.vert
index bf678d1e9b..bf678d1e9b 100644
--- a/tests/auto/quick/qquickitemrhiintegration/texture.vert
+++ b/tests/auto/quick/qquickrhiitem/texture.vert
diff --git a/tests/auto/quick/qquickrhiitem/tst_qquickrhiitem.cpp b/tests/auto/quick/qquickrhiitem/tst_qquickrhiitem.cpp
new file mode 100644
index 0000000000..e6c5b079ca
--- /dev/null
+++ b/tests/auto/quick/qquickrhiitem/tst_qquickrhiitem.cpp
@@ -0,0 +1,150 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <qtest.h>
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QQuickView>
+#include <QSGRendererInterface>
+#include <private/qsgrhisupport_p.h>
+#include <private/qquickrhiitem_p.h>
+#include "testrhiitem.h"
+
+class tst_QQuickRhiItem : public QQmlDataTest
+{
+ Q_OBJECT
+
+public:
+ tst_QQuickRhiItem();
+
+private slots:
+ void initTestCase() override;
+ void cleanupTestCase();
+ void rhiItem();
+ void properties();
+};
+
+tst_QQuickRhiItem::tst_QQuickRhiItem()
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
+{
+}
+
+void tst_QQuickRhiItem::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ qDebug() << "RHI backend:" << QSGRhiSupport::instance()->rhiBackendName();
+}
+
+void tst_QQuickRhiItem::cleanupTestCase()
+{
+}
+
+void tst_QQuickRhiItem::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);
+}
+
+void tst_QQuickRhiItem::properties()
+{
+ if (QGuiApplication::platformName() == QLatin1String("offscreen")
+ || QGuiApplication::platformName() == QLatin1String("minimal"))
+ {
+ QSKIP("Skipping on offscreen/minimal");
+ }
+
+ 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");
+
+ QQuickRhiItem *item = view.rootObject()->findChild<QQuickRhiItem *>("rhiitem");
+ QVERIFY(item);
+
+ view.grabWindow(); // to ensure there's a frame
+ // not quite safe in theory (threads etc.) but we know it works in practice
+ QQuickRhiItemPrivate *d = QQuickRhiItemPrivate::get(item);
+ QVERIFY(d->node);
+ TestRenderer *r = static_cast<TestRenderer *>(d->node->m_renderer.get());
+ QVERIFY(r);
+ QRhi *rhi = r->rhi();
+ QVERIFY(rhi);
+
+ QVERIFY(r->colorTexture());
+ QVERIFY(!r->msaaColorBuffer());
+ QVERIFY(r->depthStencilBuffer());
+ QVERIFY(r->renderTarget());
+ QCOMPARE(item->effectiveColorBufferSize(), r->colorTexture()->pixelSize());
+
+ QCOMPARE(item->sampleCount(), 1);
+ item->setSampleCount(4);
+
+ view.grabWindow(); // just to ensure the render thread rendered with the changed properties
+
+ if (rhi->supportedSampleCounts().contains(4)) {
+ QVERIFY(!r->colorTexture());
+ QVERIFY(r->msaaColorBuffer());
+ QCOMPARE(r->msaaColorBuffer()->sampleCount(), 4);
+ QCOMPARE(r->depthStencilBuffer()->sampleCount(), 4);
+ QCOMPARE(item->effectiveColorBufferSize(), r->msaaColorBuffer()->pixelSize());
+ }
+
+ QCOMPARE(item->alphaBlending(), false);
+ item->setAlphaBlending(true);
+
+ QCOMPARE(item->isMirrorVerticallyEnabled(), false);
+ item->setMirrorVertically(true);
+
+ item->setSampleCount(1);
+ item->setFixedColorBufferWidth(123);
+ item->setFixedColorBufferHeight(456);
+ view.grabWindow();
+ QCOMPARE(r->colorTexture()->pixelSize(), QSize(123, 456));
+ QCOMPARE(item->fixedColorBufferWidth(), 123);
+ QCOMPARE(item->fixedColorBufferHeight(), 456);
+ QCOMPARE(item->effectiveColorBufferSize(), QSize(123, 456));
+
+ QImage result = view.grabWindow();
+ QVERIFY(!result.isNull());
+ const int tolerance = 5;
+ 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_qquickrhiitem.moc"
+
+QTEST_MAIN(tst_QQuickRhiItem)
diff --git a/tests/auto/quick/qquickscreen/CMakeLists.txt b/tests/auto/quick/qquickscreen/CMakeLists.txt
index 8586992d3d..0b269c736c 100644
--- a/tests/auto/quick/qquickscreen/CMakeLists.txt
+++ b/tests/auto/quick/qquickscreen/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickscreen Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickscreen LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp b/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp
index ccdf69facf..74d50eed22 100644
--- a/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp
+++ b/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
diff --git a/tests/auto/quick/qquickshadereffect/CMakeLists.txt b/tests/auto/quick/qquickshadereffect/CMakeLists.txt
index a87269d7a7..9aa9140337 100644
--- a/tests/auto/quick/qquickshadereffect/CMakeLists.txt
+++ b/tests/auto/quick/qquickshadereffect/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickshadereffect Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickshadereffect LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qquickshadereffect
SOURCES
tst_qquickshadereffect.cpp
diff --git a/tests/auto/quick/qquickshadereffect/data/MyIcon.qml b/tests/auto/quick/qquickshadereffect/data/MyIcon.qml
index b67f0cbc3f..f48b3698e1 100644
--- a/tests/auto/quick/qquickshadereffect/data/MyIcon.qml
+++ b/tests/auto/quick/qquickshadereffect/data/MyIcon.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
diff --git a/tests/auto/quick/qquickshadereffect/data/deleteShaderEffectSource.qml b/tests/auto/quick/qquickshadereffect/data/deleteShaderEffectSource.qml
index cac63d4903..eee1e212e7 100644
--- a/tests/auto/quick/qquickshadereffect/data/deleteShaderEffectSource.qml
+++ b/tests/auto/quick/qquickshadereffect/data/deleteShaderEffectSource.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/quick/qquickshadereffect/data/deleteSourceItem.qml b/tests/auto/quick/qquickshadereffect/data/deleteSourceItem.qml
index bf21d6a73b..88e44bab68 100644
--- a/tests/auto/quick/qquickshadereffect/data/deleteSourceItem.qml
+++ b/tests/auto/quick/qquickshadereffect/data/deleteSourceItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Particles 2.0
diff --git a/tests/auto/quick/qquickshadereffect/data/hideParent.qml b/tests/auto/quick/qquickshadereffect/data/hideParent.qml
index 57ff9ad2ae..2566cc276e 100644
--- a/tests/auto/quick/qquickshadereffect/data/hideParent.qml
+++ b/tests/auto/quick/qquickshadereffect/data/hideParent.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/qquickshadereffect/data/testProperties.qml b/tests/auto/quick/qquickshadereffect/data/testProperties.qml
index 3962e9507b..e513cf0406 100644
--- a/tests/auto/quick/qquickshadereffect/data/testProperties.qml
+++ b/tests/auto/quick/qquickshadereffect/data/testProperties.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml b/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml
index 023c8b39ae..b32dc7fbb6 100644
--- a/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml
+++ b/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
diff --git a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
index 8029e30e25..27cf89407a 100644
--- a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
+++ b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
diff --git a/tests/auto/quick/qquickshape/CMakeLists.txt b/tests/auto/quick/qquickshape/CMakeLists.txt
index f53f87b10f..b7b536e29d 100644
--- a/tests/auto/quick/qquickshape/CMakeLists.txt
+++ b/tests/auto/quick/qquickshape/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickshape Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickshape LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickshape/data/filltransform.qml b/tests/auto/quick/qquickshape/data/filltransform.qml
new file mode 100644
index 0000000000..4f83c04c43
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/filltransform.qml
@@ -0,0 +1,58 @@
+import QtQuick
+import QtQuick.Shapes
+import tst_qquickpathitem
+
+Rectangle {
+ width: 440
+ height: 220
+ color: "white"
+
+ Shape {
+ objectName: "shape1"
+ ShapePath {
+ id: path1
+ objectName: "path1"
+ fillGradient: RadialGradient {
+ centerX: path1.startX + 100
+ centerY: path1.startY + 100
+ centerRadius: 100
+ focalX: centerX
+ focalY: centerY
+ GradientStop { position: 0.0; color: "blue" }
+ GradientStop { position: 0.5; color: "cyan" }
+ GradientStop { position: 1.0; color: "blue" }
+ }
+
+ fillTransform: PlanarTransform.fromScale(2, 1);
+
+ startX: 10
+ startY: 10
+ PathLine { relativeX: 200; relativeY: 0 }
+ PathLine { relativeX: 0; relativeY: 200 }
+ PathLine { relativeX: -200; relativeY: 0 }
+ PathLine { relativeX: 0; relativeY: -200 }
+ }
+
+ ShapePath {
+ id: path2
+ objectName: "path2"
+ fillGradient: RadialGradient {
+ centerX: path2.startX + 100
+ centerY: path2.startY + 100
+ centerRadius: 100
+ focalX: centerX
+ focalY: centerY
+ GradientStop { position: 0.0; color: "blue" }
+ GradientStop { position: 0.5; color: "cyan" }
+ GradientStop { position: 1.0; color: "blue" }
+ }
+
+ startX: 220 + 10
+ startY: 10
+ PathLine { relativeX: 200; relativeY: 0 }
+ PathLine { relativeX: 0; relativeY: 200 }
+ PathLine { relativeX: -200; relativeY: 0 }
+ PathLine { relativeX: 0; relativeY: -200 }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickshape/data/multiline.qml b/tests/auto/quick/qquickshape/data/multiline.qml
index 0556a9c3d0..edf92057c2 100644
--- a/tests/auto/quick/qquickshape/data/multiline.qml
+++ b/tests/auto/quick/qquickshape/data/multiline.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.14
import QtQuick.Shapes 1.14
diff --git a/tests/auto/quick/qquickshape/data/multilineStronglyTyped.qml b/tests/auto/quick/qquickshape/data/multilineStronglyTyped.qml
index 631db82ba5..64c61f4331 100644
--- a/tests/auto/quick/qquickshape/data/multilineStronglyTyped.qml
+++ b/tests/auto/quick/qquickshape/data/multilineStronglyTyped.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.14
import QtQuick.Shapes 1.14
diff --git a/tests/auto/quick/qquickshape/data/pathitem7.qml b/tests/auto/quick/qquickshape/data/pathitem7.qml
index 0b6637bbf0..43b42ecabc 100644
--- a/tests/auto/quick/qquickshape/data/pathitem7.qml
+++ b/tests/auto/quick/qquickshape/data/pathitem7.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.14
import tst_qquickpathitem 1.0
diff --git a/tests/auto/quick/qquickshape/data/pathitem8.qml b/tests/auto/quick/qquickshape/data/pathitem8.qml
index faa73a0f2d..8b78dc9429 100644
--- a/tests/auto/quick/qquickshape/data/pathitem8.qml
+++ b/tests/auto/quick/qquickshape/data/pathitem8.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.14
import QtQuick.Shapes 1.14
diff --git a/tests/auto/quick/qquickshape/data/polyline.qml b/tests/auto/quick/qquickshape/data/polyline.qml
index cbb1822102..9c81bf4031 100644
--- a/tests/auto/quick/qquickshape/data/polyline.qml
+++ b/tests/auto/quick/qquickshape/data/polyline.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.14
import QtQuick.Shapes 1.14
diff --git a/tests/auto/quick/qquickshape/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
index a9e15939d3..707e0037f5 100644
--- a/tests/auto/quick/qquickshape/tst_qquickshape.cpp
+++ b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuick/qquickview.h>
@@ -62,6 +62,7 @@ private slots:
void multilineDataTypes_data();
void multilineDataTypes();
void multilineStronglyTyped();
+ void fillTransform();
private:
QVector<QPolygonF> m_lowPolyLogo;
@@ -247,6 +248,8 @@ void tst_QQuickShape::changeSignals()
QCOMPARE(vpChangeSpy.size(), 15);
qobject_cast<QQuickGradientStop *>(stopList.at(1))->setColor(Qt::black);
QCOMPARE(vpChangeSpy.size(), 16);
+ vp->setFillTransform(QMatrix4x4(QTransform::fromScale(3, 0.14)));
+ QCOMPARE(vpChangeSpy.size(), 17);
}
void tst_QQuickShape::render()
@@ -674,6 +677,40 @@ void tst_QQuickShape::multilineStronglyTyped()
}
}
+void tst_QQuickShape::fillTransform()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("filltransform.qml"));
+ qApp->processEvents();
+
+ QQuickShape *obj = findItem<QQuickShape>(window->rootObject(), "shape1");
+ QVERIFY(obj != nullptr);
+ QQmlListReference list(obj, "data");
+ QCOMPARE(list.count(), 2);
+
+ QQuickShapePath *p1 = qobject_cast<QQuickShapePath *>(list.at(0));
+ QVERIFY(p1 != nullptr);
+ QVERIFY(p1->objectName() == "path1");
+ QVERIFY(p1->fillTransform() == QMatrix4x4(2,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1));
+
+ QQuickShapePath *p2 = qobject_cast<QQuickShapePath *>(list.at(1));
+ QVERIFY(p2 != nullptr);
+ QVERIFY(p2->objectName() == "path2");
+ QVERIFY(p2->fillTransform().isIdentity());
+
+ QMatrix4x4 xf(QTransform::fromTranslate(-36, 0).shear(0.35, 0));
+ p1->setFillTransform(xf);
+ QVERIFY(p1->fillTransform() == xf);
+
+ QVERIFY(p2->fillTransform().isIdentity());
+ p2->setFillTransform(xf);
+ QVERIFY(p2->fillTransform() == xf);
+
+ p1->setFillTransform(QMatrix4x4{});
+ QVERIFY(p1->fillTransform().isIdentity());
+}
+
QTEST_MAIN(tst_QQuickShape)
#include "tst_qquickshape.moc"
diff --git a/tests/auto/quick/qquickshortcut/CMakeLists.txt b/tests/auto/quick/qquickshortcut/CMakeLists.txt
index 4541b08240..1056534634 100644
--- a/tests/auto/quick/qquickshortcut/CMakeLists.txt
+++ b/tests/auto/quick/qquickshortcut/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickshortcut Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickshortcut LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickshortcut/data/embedded.qml b/tests/auto/quick/qquickshortcut/data/embedded.qml
new file mode 100644
index 0000000000..4b80363b70
--- /dev/null
+++ b/tests/auto/quick/qquickshortcut/data/embedded.qml
@@ -0,0 +1,20 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+Rectangle {
+ id: root
+
+ width: 300
+ height: 300
+
+ property bool activated: false
+ property alias shortcut: shortcut
+
+ Shortcut {
+ id: shortcut
+ onActivated: root.activated = true
+ }
+}
diff --git a/tests/auto/quick/qquickshortcut/data/multiple.qml b/tests/auto/quick/qquickshortcut/data/multiple.qml
index 98554846c5..0ecfbc44fc 100644
--- a/tests/auto/quick/qquickshortcut/data/multiple.qml
+++ b/tests/auto/quick/qquickshortcut/data/multiple.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.9
import QtQuick.Window 2.2
diff --git a/tests/auto/quick/qquickshortcut/data/shortcuts.qml b/tests/auto/quick/qquickshortcut/data/shortcuts.qml
index 02759396fa..cf88c93eee 100644
--- a/tests/auto/quick/qquickshortcut/data/shortcuts.qml
+++ b/tests/auto/quick/qquickshortcut/data/shortcuts.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.5
import QtQuick.Window 2.2
diff --git a/tests/auto/quick/qquickshortcut/data/shortcutsRect.qml b/tests/auto/quick/qquickshortcut/data/shortcutsRect.qml
index c367021cf0..80d337aeda 100644
--- a/tests/auto/quick/qquickshortcut/data/shortcutsRect.qml
+++ b/tests/auto/quick/qquickshortcut/data/shortcutsRect.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.5
diff --git a/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp b/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp
index 6ed18c2ee1..312f77e99a 100644
--- a/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp
+++ b/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp
@@ -1,11 +1,15 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtQuick/qquickwindow.h>
#include <QtQml/qqmlapplicationengine.h>
#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickview.h>
#include <QtTest/qsignalspy.h>
+#ifdef QT_WIDGETS_LIB
+#include <QtWidgets/qboxlayout.h>
+#endif
#ifdef QT_QUICKWIDGETS_LIB
#include <QtQuickWidgets/qquickwidget.h>
#endif
@@ -34,6 +38,8 @@ private slots:
void matcher();
void multiple_data();
void multiple();
+ void embedded_data();
+ void embedded();
#ifdef QT_QUICKWIDGETS_LIB
void quickWidgetShortcuts_data();
void quickWidgetShortcuts();
@@ -577,6 +583,87 @@ void tst_QQuickShortcut::contextChange()
QCOMPARE(inactiveWindow->property("activated").toBool(), activated);
}
+void tst_QQuickShortcut::embedded_data()
+{
+ QTest::addColumn<Qt::Key>("testKey");
+ QTest::addColumn<Qt::KeyboardModifiers>("testModifiers");
+ QTest::addColumn<QString>("windowShortcutSequence");
+ QTest::addColumn<bool>("windowShortcutActivated");
+
+ QTest::newRow("windowActivated") << Qt::Key_W << (Qt::ControlModifier|Qt::AltModifier)
+ << "Ctrl+Alt+W" << true;
+}
+
+void tst_QQuickShortcut::embedded()
+{
+#ifndef QT_WIDGETS_LIB
+ QSKIP("Skipping due to QT_WIDGETS_LIB is not defined");
+#else
+ QFETCH(Qt::Key, testKey);
+ QFETCH(Qt::KeyboardModifiers, testModifiers);
+ QFETCH(QString, windowShortcutSequence);
+ QFETCH(bool, windowShortcutActivated);
+
+ QWidget window;
+ QVBoxLayout *layout = new QVBoxLayout {&window};
+ QQuickView *quickView = new QQuickView;
+ quickView->setResizeMode(QQuickView::SizeRootObjectToView);
+ quickView->setSource(testFileUrl("embedded.qml"));
+
+ QWidget *container = QWidget::createWindowContainer(quickView);
+ container->setMinimumSize(quickView->size());
+ container->setFocusPolicy(Qt::TabFocus);
+
+ QWidget *widget = new QWidget;
+ // We will set focus to the widget and its default is NoFocus.
+ widget->setFocusPolicy(Qt::FocusPolicy::StrongFocus);
+
+ layout->addWidget(widget);
+ layout->addWidget(container);
+
+ window.show();
+ QTRY_VERIFY(window.isVisible());
+ // The widget can get focused only when the including window has exposed.
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ widget->setFocus();
+ QTRY_VERIFY(widget->hasFocus());
+
+ // If the window-context shortcut is expected to be activated,
+ // then the QuickView window needs to be active.
+ // On Linux, the embedded QuickView window is active immediately
+ // after the containing window is active, but on Windows,
+ // the embedded QuickView window is activated after a delay
+ // once the containing window is active.
+ if (windowShortcutActivated)
+ QVERIFY(QTest::qWaitForWindowActive(quickView));
+
+ QQuickItem *item = quickView->rootObject();
+ QVERIFY(item);
+
+ QObject *windowShortcut = item->property("shortcut").value<QObject *>();
+ QVERIFY(windowShortcut);
+
+ windowShortcut->setProperty("context", Qt::WindowShortcut);
+ windowShortcut->setProperty("sequence", windowShortcutSequence);
+
+ QTest::keyPress(&window, testKey, testModifiers);
+ QTest::keyRelease(&window, testKey, testModifiers);
+ QCOMPARE(item->property("activated").toBool(), windowShortcutActivated);
+
+ quickView->requestActivate();
+ QTRY_VERIFY(quickView->isActive());
+ QVERIFY(quickView->isActive());
+
+ item->setProperty("activated", false);
+ QVERIFY(!item->property("activated").toBool());
+
+ QTest::keyPress(&window, testKey, testModifiers);
+ QTest::keyRelease(&window, testKey, testModifiers);
+ QCOMPARE(item->property("activated").toBool(), true);
+#endif
+}
+
#ifdef QT_QUICKWIDGETS_LIB
void tst_QQuickShortcut::quickWidgetShortcuts_data()
{
diff --git a/tests/auto/quick/qquicksmoothedanimation/CMakeLists.txt b/tests/auto/quick/qquicksmoothedanimation/CMakeLists.txt
index 8854ef2081..2a277441c4 100644
--- a/tests/auto/quick/qquicksmoothedanimation/CMakeLists.txt
+++ b/tests/auto/quick/qquicksmoothedanimation/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicksmoothedanimation Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicksmoothedanimation LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp b/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp
index 8fed114b26..7bd1b09d0f 100644
--- a/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp
+++ b/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
diff --git a/tests/auto/quick/qquickspringanimation/CMakeLists.txt b/tests/auto/quick/qquickspringanimation/CMakeLists.txt
index 5faedbfb87..0fa7b717c5 100644
--- a/tests/auto/quick/qquickspringanimation/CMakeLists.txt
+++ b/tests/auto/quick/qquickspringanimation/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickspringanimation Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickspringanimation LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp b/tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp
index 65b4ecacc0..f78157ab26 100644
--- a/tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp
+++ b/tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
diff --git a/tests/auto/quick/qquickspritesequence/CMakeLists.txt b/tests/auto/quick/qquickspritesequence/CMakeLists.txt
index 619e8c2f9d..c492a16183 100644
--- a/tests/auto/quick/qquickspritesequence/CMakeLists.txt
+++ b/tests/auto/quick/qquickspritesequence/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickspritesequence Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickspritesequence LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickspritesequence/data/advance.qml b/tests/auto/quick/qquickspritesequence/data/advance.qml
index a12db397ad..2242c28705 100644
--- a/tests/auto/quick/qquickspritesequence/data/advance.qml
+++ b/tests/auto/quick/qquickspritesequence/data/advance.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickspritesequence/data/basic.qml b/tests/auto/quick/qquickspritesequence/data/basic.qml
index b01085f3ed..c2caad4f6e 100644
--- a/tests/auto/quick/qquickspritesequence/data/basic.qml
+++ b/tests/auto/quick/qquickspritesequence/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickspritesequence/data/crashonstart.qml b/tests/auto/quick/qquickspritesequence/data/crashonstart.qml
index 37bc137133..cee94fdf91 100644
--- a/tests/auto/quick/qquickspritesequence/data/crashonstart.qml
+++ b/tests/auto/quick/qquickspritesequence/data/crashonstart.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
//QTBUG-24797
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickspritesequence/data/huge.qml b/tests/auto/quick/qquickspritesequence/data/huge.qml
index c30d493459..58d365ec84 100644
--- a/tests/auto/quick/qquickspritesequence/data/huge.qml
+++ b/tests/auto/quick/qquickspritesequence/data/huge.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickspritesequence/data/spriteaftergoal.qml b/tests/auto/quick/qquickspritesequence/data/spriteaftergoal.qml
index 7d8c8a78cc..eeee289b54 100644
--- a/tests/auto/quick/qquickspritesequence/data/spriteaftergoal.qml
+++ b/tests/auto/quick/qquickspritesequence/data/spriteaftergoal.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// QTBUG-40595
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickspritesequence/data/spritebeforegoal.qml b/tests/auto/quick/qquickspritesequence/data/spritebeforegoal.qml
index 2d6a18e1e7..b1695ff820 100644
--- a/tests/auto/quick/qquickspritesequence/data/spritebeforegoal.qml
+++ b/tests/auto/quick/qquickspritesequence/data/spritebeforegoal.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// QTBUG-40595
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp b/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp
index cdfbe7707f..ffaa45449f 100644
--- a/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp
+++ b/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuick/qquickview.h>
diff --git a/tests/auto/quick/qquickstates/CMakeLists.txt b/tests/auto/quick/qquickstates/CMakeLists.txt
index 672d30ff69..20141a489b 100644
--- a/tests/auto/quick/qquickstates/CMakeLists.txt
+++ b/tests/auto/quick/qquickstates/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickstates Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickstates LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -26,6 +32,21 @@ qt_internal_add_test(tst_qquickstates
TESTDATA ${test_data}
)
+qt_internal_add_test(tst_qquickstates_no_deferred_properties
+ SOURCES
+ tst_qquickstates.cpp
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::Gui
+ Qt::GuiPrivate
+ Qt::QmlPrivate
+ Qt::QuickPrivate
+ Qt::QuickTestUtilsPrivate
+ TESTDATA ${test_data}
+ DEFINES
+ QML_DISABLE_INTERNAL_DEFERRED_PROPERTIES
+)
+
## Scopes:
#####################################################################
@@ -38,3 +59,13 @@ qt_internal_extend_target(tst_qquickstates CONDITION NOT ANDROID AND NOT IOS
DEFINES
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
)
+
+qt_internal_extend_target(tst_qquickstates_no_deferred_properties CONDITION ANDROID OR IOS
+ DEFINES
+ QT_QMLTEST_DATADIR=":/data"
+)
+
+qt_internal_extend_target(tst_qquickstates_no_deferred_properties CONDITION NOT ANDROID AND NOT IOS
+ DEFINES
+ QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+)
diff --git a/tests/auto/quick/qquickstates/data/anchorRewindSize.qml b/tests/auto/quick/qquickstates/data/anchorRewindSize.qml
new file mode 100644
index 0000000000..8fbae05c6d
--- /dev/null
+++ b/tests/auto/quick/qquickstates/data/anchorRewindSize.qml
@@ -0,0 +1,30 @@
+import QtQuick
+
+Item {
+ id: root
+ width: 400
+ height: 400
+ property bool changeState: false
+ Item {
+ id: outer
+ anchors.fill: parent
+ Item {
+ id: inner
+ width: 100
+ height: 100
+ anchors.left: outer.left
+ anchors.top: outer.top
+ }
+ states: [
+ State {
+ when: root.changeState
+ AnchorChanges {
+ target: inner
+ anchors.right: outer.right
+ anchors.bottom: outer.bottom
+ }
+ }
+ ]
+ }
+}
+
diff --git a/tests/auto/quick/qquickstates/data/broken.qml b/tests/auto/quick/qquickstates/data/broken.qml
new file mode 100644
index 0000000000..8813c8bb39
--- /dev/null
+++ b/tests/auto/quick/qquickstates/data/broken.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ states: ["test"]
+}
diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
index 44187d2b65..3bdbe29d1e 100644
--- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -119,7 +119,12 @@ class tst_qquickstates : public QQmlDataTest
{
Q_OBJECT
public:
- tst_qquickstates() : QQmlDataTest(QT_QMLTEST_DATADIR) {}
+ tst_qquickstates() : QQmlDataTest(QT_QMLTEST_DATADIR)
+ {
+#ifdef QML_DISABLE_INTERNAL_DEFERRED_PROPERTIES
+ qputenv("QML_DISABLE_INTERNAL_DEFERRED_PROPERTIES", "1");
+#endif
+ }
private:
QByteArray fullDataPath(const QString &path) const;
@@ -184,7 +189,9 @@ private slots:
void parentChangeInvolvingBindings();
void deferredProperties();
void rewindAnchorChange();
+ void rewindAnchorChangeSize();
void bindingProperlyRemovedWithTransition();
+ void doNotCrashOnBroken();
};
void tst_qquickstates::initTestCase()
@@ -1650,7 +1657,7 @@ static int getRefCount(const QQmlAnyBinding &binding)
} else {
// this temporarily adds a refcount because we construc a new untypedpropertybinding
// thus -1
- return QPropertyBindingPrivate::get(binding.asUntypedPropertyBinding())->ref - 1;
+ return QPropertyBindingPrivate::get(binding.asUntypedPropertyBinding())->refCount() - 1;
}
}
@@ -1975,6 +1982,41 @@ void tst_qquickstates::rewindAnchorChange()
QTRY_COMPARE(innerRect->height(), 200);
}
+void tst_qquickstates::rewindAnchorChangeSize()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("anchorRewindSize.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ std::unique_ptr<QObject> root(c.create());
+ QVERIFY(root);
+
+ QQmlContext *context = qmlContext(root.get());
+ QVERIFY(context);
+
+ QObject *inner = context->objectForName(QStringLiteral("inner"));
+ QVERIFY(inner);
+
+ QQuickItem *innerRect = qobject_cast<QQuickItem *>(inner);
+ QVERIFY(innerRect);
+
+ QCOMPARE(innerRect->x(), 0);
+ QCOMPARE(innerRect->y(), 0);
+ QCOMPARE(innerRect->width(), 100);
+ QCOMPARE(innerRect->height(), 100);
+
+ root->setProperty("changeState", true);
+ QCOMPARE(innerRect->x(), 0);
+ QCOMPARE(innerRect->y(), 0);
+ QCOMPARE(innerRect->width(), 400);
+ QCOMPARE(innerRect->height(), 400);
+
+ root->setProperty("changeState", false);
+ QCOMPARE(innerRect->x(), 0);
+ QCOMPARE(innerRect->y(), 0);
+ QCOMPARE(innerRect->width(), 100);
+ QCOMPARE(innerRect->height(), 100);
+}
+
void tst_qquickstates::bindingProperlyRemovedWithTransition()
{
QQmlEngine engine;
@@ -1995,6 +2037,21 @@ void tst_qquickstates::bindingProperlyRemovedWithTransition()
QTRY_COMPARE(item->width(), 100);
}
+void tst_qquickstates::doNotCrashOnBroken()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("broken.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> root(c.create());
+ QVERIFY(root);
+ QQuickItem *item = qobject_cast<QQuickItem *>(root.get());
+ QVERIFY(item);
+
+ QQmlListReference states(item, "states");
+ QCOMPARE(states.size(), 1);
+ QCOMPARE(states.at(0), nullptr);
+}
+
QTEST_MAIN(tst_qquickstates)
#include "tst_qquickstates.moc"
diff --git a/tests/auto/quick/qquickstyledtext/CMakeLists.txt b/tests/auto/quick/qquickstyledtext/CMakeLists.txt
index 2e36a647c0..9cac845e6d 100644
--- a/tests/auto/quick/qquickstyledtext/CMakeLists.txt
+++ b/tests/auto/quick/qquickstyledtext/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickstyledtext Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickstyledtext LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qquickstyledtext
SOURCES
tst_qquickstyledtext.cpp
diff --git a/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp b/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
index aebd9990f7..f0367e27f5 100644
--- a/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
+++ b/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtTest/QtTest>
#include <QtGui/QTextLayout>
@@ -127,6 +127,7 @@ void tst_qquickstyledtext::textOutput_data()
QTest::newRow("space leading bold") << "this is<b> bold</b>" << "this is bold" << (FormatList() << Format(Format::Bold, 7, 5)) << false;
QTest::newRow("space trailing bold") << "this is <b>bold </b>" << "this is bold " << (FormatList() << Format(Format::Bold, 8, 5)) << false;
QTest::newRow("img") << "a<img src=\"blah.png\"/>b" << "a b" << FormatList() << false;
+ QTest::newRow("img") << "a<img />b" << "a b" << FormatList() << false;
QTest::newRow("tag mix") << "<f6>ds<b></img><pro>gfh</b><w><w>ghj</stron><ql><sl><pl>dfg</j6><img><bol><r><prp>dfg<bkj></b><up><string>ewrq</al><bl>jklhj<zl>" << "dsgfhghjdfgdfgewrqjklhj" << (FormatList() << Format(Format::Bold, 2, 3)) << false;
QTest::newRow("named html entities") << "&gt; &lt; &amp; &quot; &nbsp;" << QLatin1String("> < & \" ") + QChar(QChar::Nbsp) << FormatList() << false;
QTest::newRow("invalid html entities") << "a &hello & a &goodbye;" << "a &hello & a " << FormatList() << false;
diff --git a/tests/auto/quick/qquicksystempalette/CMakeLists.txt b/tests/auto/quick/qquicksystempalette/CMakeLists.txt
index bb99fbefc4..b747b51978 100644
--- a/tests/auto/quick/qquicksystempalette/CMakeLists.txt
+++ b/tests/auto/quick/qquicksystempalette/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicksystempalette Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicksystempalette LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquicksystempalette/tst_qquicksystempalette.cpp b/tests/auto/quick/qquicksystempalette/tst_qquicksystempalette.cpp
index b9e79051bb..e9b6054130 100644
--- a/tests/auto/quick/qquicksystempalette/tst_qquicksystempalette.cpp
+++ b/tests/auto/quick/qquicksystempalette/tst_qquicksystempalette.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
@@ -52,6 +52,8 @@ void tst_qquicksystempalette::activePalette()
QCOMPARE(palette.shadow().color(), object->shadow());
QCOMPARE(palette.highlight().color(), object->highlight());
QCOMPARE(palette.highlightedText().color(), object->highlightedText());
+ QCOMPARE(palette.placeholderText().color(), object->placeholderText());
+ QCOMPARE(palette.accent().color(), object->accent());
delete object;
}
@@ -80,6 +82,8 @@ void tst_qquicksystempalette::inactivePalette()
QCOMPARE(palette.shadow().color(), object->shadow());
QCOMPARE(palette.highlight().color(), object->highlight());
QCOMPARE(palette.highlightedText().color(), object->highlightedText());
+ QCOMPARE(palette.placeholderText().color(), object->placeholderText());
+ QCOMPARE(palette.accent().color(), object->accent());
delete object;
}
@@ -108,6 +112,8 @@ void tst_qquicksystempalette::disabledPalette()
QCOMPARE(palette.shadow().color(), object->shadow());
QCOMPARE(palette.highlight().color(), object->highlight());
QCOMPARE(palette.highlightedText().color(), object->highlightedText());
+ QCOMPARE(palette.placeholderText().color(), object->placeholderText());
+ QCOMPARE(palette.accent().color(), object->accent());
delete object;
}
diff --git a/tests/auto/quick/qquicktableview/CMakeLists.txt b/tests/auto/quick/qquicktableview/CMakeLists.txt
index 9fa59ca827..77c7f5f06a 100644
--- a/tests/auto/quick/qquicktableview/CMakeLists.txt
+++ b/tests/auto/quick/qquicktableview/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicktableview Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicktableview LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquicktableview/data/alternatingrowheightcolumnwidth.qml b/tests/auto/quick/qquicktableview/data/alternatingrowheightcolumnwidth.qml
index c23394b3d5..106a95de7f 100644
--- a/tests/auto/quick/qquicktableview/data/alternatingrowheightcolumnwidth.qml
+++ b/tests/auto/quick/qquicktableview/data/alternatingrowheightcolumnwidth.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/asyncloader.qml b/tests/auto/quick/qquicktableview/data/asyncloader.qml
index 8e87b60b0f..ac901323f1 100644
--- a/tests/auto/quick/qquicktableview/data/asyncloader.qml
+++ b/tests/auto/quick/qquicktableview/data/asyncloader.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/qquicktableview/data/asyncplain.qml b/tests/auto/quick/qquicktableview/data/asyncplain.qml
index eba13e72a4..25eb14b016 100644
--- a/tests/auto/quick/qquicktableview/data/asyncplain.qml
+++ b/tests/auto/quick/qquicktableview/data/asyncplain.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/changemodelfromdelegate.qml b/tests/auto/quick/qquicktableview/data/changemodelfromdelegate.qml
index e20b099ae9..60b02bc245 100644
--- a/tests/auto/quick/qquicktableview/data/changemodelfromdelegate.qml
+++ b/tests/auto/quick/qquicktableview/data/changemodelfromdelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/changemodelordelegateduringupdate.qml b/tests/auto/quick/qquicktableview/data/changemodelordelegateduringupdate.qml
index bcb310814c..f0c7814186 100644
--- a/tests/auto/quick/qquicktableview/data/changemodelordelegateduringupdate.qml
+++ b/tests/auto/quick/qquicktableview/data/changemodelordelegateduringupdate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/checkalwaysemit.qml b/tests/auto/quick/qquicktableview/data/checkalwaysemit.qml
index 600e120a12..463e21342c 100644
--- a/tests/auto/quick/qquicktableview/data/checkalwaysemit.qml
+++ b/tests/auto/quick/qquicktableview/data/checkalwaysemit.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/checkmodelpropertyrevision.qml b/tests/auto/quick/qquicktableview/data/checkmodelpropertyrevision.qml
index 560429308c..f89fff8de1 100644
--- a/tests/auto/quick/qquicktableview/data/checkmodelpropertyrevision.qml
+++ b/tests/auto/quick/qquicktableview/data/checkmodelpropertyrevision.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.12
diff --git a/tests/auto/quick/qquicktableview/data/checkrowandcolumnnotchanged.qml b/tests/auto/quick/qquicktableview/data/checkrowandcolumnnotchanged.qml
index bf62a0e393..fa15f2f54b 100644
--- a/tests/auto/quick/qquicktableview/data/checkrowandcolumnnotchanged.qml
+++ b/tests/auto/quick/qquicktableview/data/checkrowandcolumnnotchanged.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/columnwidthboundtoviewwidth.qml b/tests/auto/quick/qquicktableview/data/columnwidthboundtoviewwidth.qml
index bbbdf74d4e..eaf0cd692d 100644
--- a/tests/auto/quick/qquicktableview/data/columnwidthboundtoviewwidth.qml
+++ b/tests/auto/quick/qquicktableview/data/columnwidthboundtoviewwidth.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/contentwidthheight.qml b/tests/auto/quick/qquicktableview/data/contentwidthheight.qml
index 12cf58d5c4..f6ae474bf4 100644
--- a/tests/auto/quick/qquicktableview/data/contentwidthheight.qml
+++ b/tests/auto/quick/qquicktableview/data/contentwidthheight.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/countingtableview.qml b/tests/auto/quick/qquicktableview/data/countingtableview.qml
index 31cd7ec849..a73cb6e4cf 100644
--- a/tests/auto/quick/qquicktableview/data/countingtableview.qml
+++ b/tests/auto/quick/qquicktableview/data/countingtableview.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/delegateWithRequired.qml b/tests/auto/quick/qquicktableview/data/delegateWithRequired.qml
index 27dff1aadd..728de37266 100644
--- a/tests/auto/quick/qquicktableview/data/delegateWithRequired.qml
+++ b/tests/auto/quick/qquicktableview/data/delegateWithRequired.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/delegatewithRequiredUnset.qml b/tests/auto/quick/qquicktableview/data/delegatewithRequiredUnset.qml
index 13afd88522..43a1eed402 100644
--- a/tests/auto/quick/qquicktableview/data/delegatewithRequiredUnset.qml
+++ b/tests/auto/quick/qquicktableview/data/delegatewithRequiredUnset.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/delegatewithanchors.qml b/tests/auto/quick/qquicktableview/data/delegatewithanchors.qml
index 6354d8d1ed..8b192e0b9e 100644
--- a/tests/auto/quick/qquicktableview/data/delegatewithanchors.qml
+++ b/tests/auto/quick/qquicktableview/data/delegatewithanchors.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/editdelegate.qml b/tests/auto/quick/qquicktableview/data/editdelegate.qml
index 8219aaa3b0..0c8bee2b27 100644
--- a/tests/auto/quick/qquicktableview/data/editdelegate.qml
+++ b/tests/auto/quick/qquicktableview/data/editdelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
@@ -45,13 +45,13 @@ Item {
Component.onCompleted: {
tableView.editItem = editRoot
- tableView.editIndex = tableView.modelIndex(row, column)
+ tableView.editIndex = tableView.index(row, column)
selectAll()
}
Component.onDestruction: {
tableView.editItem = null
- tableView.editIndex = tableView.modelIndex(-1, -1)
+ tableView.editIndex = tableView.index(-1, -1)
}
}
}
diff --git a/tests/auto/quick/qquicktableview/data/editdelegate_combobox.qml b/tests/auto/quick/qquicktableview/data/editdelegate_combobox.qml
index b7de4cd406..c1344575ff 100644
--- a/tests/auto/quick/qquicktableview/data/editdelegate_combobox.qml
+++ b/tests/auto/quick/qquicktableview/data/editdelegate_combobox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
@@ -47,12 +47,12 @@ Item {
Component.onCompleted: {
tableView.editItem = editRoot
- tableView.editIndex = tableView.modelIndex(row, column)
+ tableView.editIndex = tableView.index(row, column)
}
Component.onDestruction: {
tableView.editItem = null
- tableView.editIndex = tableView.modelIndex(-1, -1)
+ tableView.editIndex = tableView.index(-1, -1)
}
ComboBox {
diff --git a/tests/auto/quick/qquicktableview/data/forcelayout.qml b/tests/auto/quick/qquicktableview/data/forcelayout.qml
index d15587cb36..5beaf2bd25 100644
--- a/tests/auto/quick/qquicktableview/data/forcelayout.qml
+++ b/tests/auto/quick/qquicktableview/data/forcelayout.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/hiderowsandcolumns.qml b/tests/auto/quick/qquicktableview/data/hiderowsandcolumns.qml
index d0f5f06fcc..1a2737ad28 100644
--- a/tests/auto/quick/qquicktableview/data/hiderowsandcolumns.qml
+++ b/tests/auto/quick/qquicktableview/data/hiderowsandcolumns.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/iscolumnloaded.qml b/tests/auto/quick/qquicktableview/data/iscolumnloaded.qml
index df0b9d3bd2..84cbe981bd 100644
--- a/tests/auto/quick/qquicktableview/data/iscolumnloaded.qml
+++ b/tests/auto/quick/qquicktableview/data/iscolumnloaded.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quick/qquicktableview/data/plaintableview.qml b/tests/auto/quick/qquicktableview/data/plaintableview.qml
index 840ef3c5d5..a18b1c03eb 100644
--- a/tests/auto/quick/qquicktableview/data/plaintableview.qml
+++ b/tests/auto/quick/qquicktableview/data/plaintableview.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/qquicktableview/data/positionlast.qml b/tests/auto/quick/qquicktableview/data/positionlast.qml
new file mode 100644
index 0000000000..fcc2f34fae
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/positionlast.qml
@@ -0,0 +1,52 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ width: 300
+ height: 300
+
+ property alias tableView: tableView
+ property bool positionOnRowsChanged: false
+ property bool positionOnColumnsChanged: false
+ property bool positionOnContentHeightChanged: false
+ property bool positionOnContentWidthChanged: false
+
+ TableView {
+ id: tableView
+ anchors.fill: parent
+ clip: true
+
+ delegate: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 100
+ Text {
+ anchors.centerIn: parent
+ text: "row:" + row + "\ncol:" + column
+ font.pixelSize: 10
+ }
+ }
+
+ onRowsChanged: {
+ if (positionOnRowsChanged)
+ positionViewAtRow(rows - 1, TableView.AlignBottom)
+ }
+
+ onColumnsChanged: {
+ if (positionOnColumnsChanged)
+ positionViewAtColumn(columns - 1, TableView.AlignRight)
+ }
+
+ onContentHeightChanged: {
+ if (positionOnContentHeightChanged)
+ positionViewAtRow(rows - 1, TableView.AlignBottom)
+ }
+
+ onContentWidthChanged: {
+ if (positionOnContentWidthChanged)
+ positionViewAtColumn(columns - 1, TableView.AlignRight)
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/qqmllistpropertymodel.qml b/tests/auto/quick/qquicktableview/data/qqmllistpropertymodel.qml
index 66887d8c6b..851fcb7310 100644
--- a/tests/auto/quick/qquicktableview/data/qqmllistpropertymodel.qml
+++ b/tests/auto/quick/qquicktableview/data/qqmllistpropertymodel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/reordertableview.qml b/tests/auto/quick/qquicktableview/data/reordertableview.qml
new file mode 100644
index 0000000000..704126180f
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/reordertableview.qml
@@ -0,0 +1,52 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+ property real delegateWidth: 100
+ property real delegateHeight: 50
+ property Component delegate: tableViewDelegate
+ property bool delegateParentSetBeforeCompleted: false
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ columnSpacing: 1
+ rowSpacing: 1
+ animate: false
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ required property int column
+ required property int row
+ objectName: "tableViewDelegate" + column + row
+ implicitWidth: delegateWidth
+ implicitHeight: delegateHeight
+ color: "lightgray"
+ border.width: 1
+
+ property string modelDataBinding: modelData
+
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+
+ Component.onCompleted: {
+ delegateParentSetBeforeCompleted = parent != null;
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/resetJsModelData.qml b/tests/auto/quick/qquicktableview/data/resetJsModelData.qml
new file mode 100644
index 0000000000..def5346147
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/resetJsModelData.qml
@@ -0,0 +1,19 @@
+import QtQuick
+
+Item {
+ width: 100
+ height: 300
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ anchors.fill: parent
+ property int modelUpdated: 0
+ onModelChanged: { ++modelUpdated }
+ delegate: Item {
+ implicitHeight: 10
+ implicitWidth: 10
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktableview/data/resetModelData.qml b/tests/auto/quick/qquicktableview/data/resetModelData.qml
new file mode 100644
index 0000000000..f7b3ec3009
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/resetModelData.qml
@@ -0,0 +1,25 @@
+import QtQuick
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ anchors.fill: parent
+ height: 300
+ width: 200
+
+ property bool success: false
+
+ delegate: Rectangle {
+ required property var model
+ implicitWidth: 100
+ implicitHeight: 50
+ property var mydata: model?.custom ?? model.display
+ onMydataChanged: tableView.success = mydata === 42
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktableview/data/setcontentpos.qml b/tests/auto/quick/qquicktableview/data/setcontentpos.qml
index d1dc53bb98..69cf73164f 100644
--- a/tests/auto/quick/qquicktableview/data/setcontentpos.qml
+++ b/tests/auto/quick/qquicktableview/data/setcontentpos.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/sizefromdelegate.qml b/tests/auto/quick/qquicktableview/data/sizefromdelegate.qml
index 4a1ee32cdd..deb6b81f8e 100644
--- a/tests/auto/quick/qquicktableview/data/sizefromdelegate.qml
+++ b/tests/auto/quick/qquicktableview/data/sizefromdelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/syncviewsimple.qml b/tests/auto/quick/qquicktableview/data/syncviewsimple.qml
index 880554b129..0fc2e6a819 100644
--- a/tests/auto/quick/qquicktableview/data/syncviewsimple.qml
+++ b/tests/auto/quick/qquicktableview/data/syncviewsimple.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.14
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/tableviewdefaultspacing.qml b/tests/auto/quick/qquicktableview/data/tableviewdefaultspacing.qml
index 6ab66984e7..f3563500c9 100644
--- a/tests/auto/quick/qquicktableview/data/tableviewdefaultspacing.qml
+++ b/tests/auto/quick/qquicktableview/data/tableviewdefaultspacing.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/tableviewfocus.qml b/tests/auto/quick/qquicktableview/data/tableviewfocus.qml
index 4bda963673..3bb7040e7f 100644
--- a/tests/auto/quick/qquicktableview/data/tableviewfocus.qml
+++ b/tests/auto/quick/qquicktableview/data/tableviewfocus.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/tableviewimplicitsize.qml b/tests/auto/quick/qquicktableview/data/tableviewimplicitsize.qml
index 8a0647f460..54414b6a71 100644
--- a/tests/auto/quick/qquicktableview/data/tableviewimplicitsize.qml
+++ b/tests/auto/quick/qquicktableview/data/tableviewimplicitsize.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/tableviewinteractive.qml b/tests/auto/quick/qquicktableview/data/tableviewinteractive.qml
new file mode 100644
index 0000000000..526313dc24
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/tableviewinteractive.qml
@@ -0,0 +1,32 @@
+import QtQuick
+import QtQuick.Controls
+
+Item {
+ id: rootItem
+
+ width: 200
+ height: 200
+ visible: true
+
+ property int eventCount: 0
+ property alias tableView: tableView
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: function(mouse) {
+ ++eventCount
+ }
+ }
+
+ TableView {
+ id: tableView
+ objectName: "tableView"
+ anchors.fill: parent
+ model: 1
+ delegate: Rectangle {
+ color: "red"
+ implicitWidth: 200
+ implicitHeight: 200
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktableview/data/tableviewwithselected1.qml b/tests/auto/quick/qquicktableview/data/tableviewwithselected1.qml
index 0e0b8f20bb..f0396c2c34 100644
--- a/tests/auto/quick/qquicktableview/data/tableviewwithselected1.qml
+++ b/tests/auto/quick/qquicktableview/data/tableviewwithselected1.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quick/qquicktableview/data/tableviewwithselected2.qml b/tests/auto/quick/qquicktableview/data/tableviewwithselected2.qml
index 5892a72be4..489a00b3f8 100644
--- a/tests/auto/quick/qquicktableview/data/tableviewwithselected2.qml
+++ b/tests/auto/quick/qquicktableview/data/tableviewwithselected2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quick/qquicktableview/data/tweakimplicitsize.qml b/tests/auto/quick/qquicktableview/data/tweakimplicitsize.qml
index d60e9d0b1e..e0e9c01908 100644
--- a/tests/auto/quick/qquicktableview/data/tweakimplicitsize.qml
+++ b/tests/auto/quick/qquicktableview/data/tweakimplicitsize.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/unloadheader.qml b/tests/auto/quick/qquicktableview/data/unloadheader.qml
new file mode 100644
index 0000000000..5b15e4c752
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/unloadheader.qml
@@ -0,0 +1,43 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import Qt.labs.qmlmodels
+
+Item {
+ width: 640
+ height: 480
+
+ property alias tableView: tableView
+ property alias loader: verticalHeaderLoader
+
+ Loader {
+ id: verticalHeaderLoader
+ x: 0
+ width: item ? item.contentWidth : 0
+ height: parent.height
+ sourceComponent: TableView {
+ model: 5
+ syncView: tableView
+ syncDirection: Qt.Vertical
+ delegate: Text {
+ text: index
+ }
+ }
+ }
+
+ TableView {
+ id: tableView
+ anchors {
+ left: verticalHeaderLoader.right
+ right: parent.right
+ top: parent.top
+ bottom: parent.bottom
+ }
+
+ model: 5
+ delegate: Text {
+ text: index
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktableview/data/usechooserwithoutdefault.qml b/tests/auto/quick/qquicktableview/data/usechooserwithoutdefault.qml
index 48d28b0766..4ff2a7401f 100644
--- a/tests/auto/quick/qquicktableview/data/usechooserwithoutdefault.qml
+++ b/tests/auto/quick/qquicktableview/data/usechooserwithoutdefault.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/usefaultyrowcolumnprovider.qml b/tests/auto/quick/qquicktableview/data/usefaultyrowcolumnprovider.qml
index c118077b14..65d918e072 100644
--- a/tests/auto/quick/qquicktableview/data/usefaultyrowcolumnprovider.qml
+++ b/tests/auto/quick/qquicktableview/data/usefaultyrowcolumnprovider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/userowcolumnprovider.qml b/tests/auto/quick/qquicktableview/data/userowcolumnprovider.qml
index 3e3ed9ab94..686bed12d0 100644
--- a/tests/auto/quick/qquicktableview/data/userowcolumnprovider.qml
+++ b/tests/auto/quick/qquicktableview/data/userowcolumnprovider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Window 2.3
diff --git a/tests/auto/quick/qquicktableview/data/zerosizedtableview.qml b/tests/auto/quick/qquicktableview/data/zerosizedtableview.qml
index c8d6168b81..b885684b18 100644
--- a/tests/auto/quick/qquicktableview/data/zerosizedtableview.qml
+++ b/tests/auto/quick/qquicktableview/data/zerosizedtableview.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
@@ -15,6 +15,14 @@ Item {
width: 0
height: 0
delegate: tableViewDelegate
+
+ Component.onCompleted: {
+ positionViewAtCell(
+ Qt.point(0,0),
+ TableView.AlignHCenter,
+ Qt.point(-5,-5)
+ );
+ }
}
Component {
diff --git a/tests/auto/quick/qquicktableview/data/zerosizedviewport.qml b/tests/auto/quick/qquicktableview/data/zerosizedviewport.qml
new file mode 100644
index 0000000000..f32c7bd3b2
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/zerosizedviewport.qml
@@ -0,0 +1,31 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Window
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.bottom: parent.bottom
+ width: contentWidth
+ delegate: tableViewDelegate
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ implicitWidth: tableView.width
+ implicitHeight: 50
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/testmodel.h b/tests/auto/quick/qquicktableview/testmodel.h
index 02a3478bdd..21ed7e03a5 100644
--- a/tests/auto/quick/qquicktableview/testmodel.h
+++ b/tests/auto/quick/qquicktableview/testmodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QtCore>
#include <QtGui/QStandardItemModel>
@@ -36,13 +36,27 @@ public:
QVariant data(const QModelIndex &index, int role) const override
{
- if (!index.isValid() || role != Qt::DisplayRole)
+ if (!index.isValid())
return QVariant();
- int serializedIndex = index.row() + (index.column() * m_columns);
- if (modelData.contains(serializedIndex))
- return modelData.value(serializedIndex);
- return QStringLiteral("%1").arg(index.row());
+ QVariant ret;
+
+ switch (role) {
+ case Qt::UserRole:
+ ret = 42;
+ break;
+ case Qt::DisplayRole: {
+ int serializedIndex = index.row() + (index.column() * m_columns);
+ if (modelData.contains(serializedIndex))
+ ret = modelData.value(serializedIndex);
+ else
+ ret = QStringLiteral("%1").arg(index.row()); }
+ break;
+ default:
+ break;
+ }
+
+ return ret;
}
Q_INVOKABLE QVariant dataFromSerializedIndex(int index) const
@@ -54,9 +68,18 @@ public:
QHash<int, QByteArray> roleNames() const override
{
+ if (m_useCustomRoleNames)
+ return { { Qt::UserRole, "custom"} };
return { {Qt::DisplayRole, "display"} };
}
+ Q_INVOKABLE void useCustomRoleNames(bool use)
+ {
+ beginResetModel();
+ m_useCustomRoleNames = use;
+ endResetModel();
+ }
+
Q_INVOKABLE void setModelData(const QPoint &cell, const QSize &span, const QString &string)
{
for (int c = 0; c < span.width(); ++c) {
@@ -159,6 +182,11 @@ public:
insertRow(row, QModelIndex());
}
+ Q_INVOKABLE void addColumn(int column)
+ {
+ insertColumn(column, QModelIndex());
+ }
+
Qt::ItemFlags flags(const QModelIndex &index) const override
{
Q_UNUSED(index)
@@ -178,6 +206,7 @@ private:
int m_rows = 0;
int m_columns = 0;
bool m_dataCanBeFetched = false;
+ bool m_useCustomRoleNames = false;
QHash<int, QString> modelData;
Qt::ItemFlags m_flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
};
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index ecea4adfd5..56dee4b585 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuickTest/quicktest.h>
@@ -87,6 +87,7 @@ private slots:
void checkZeroSizedDelegate();
void checkImplicitSizeDelegate();
void checkZeroSizedTableView();
+ void checkZeroSizedViewPort();
void checkColumnWidthWithoutProvider();
void checkColumnWidthAndRowHeightFunctions();
void checkDelegateWithAnchors();
@@ -103,7 +104,7 @@ private slots:
void isColumnLoadedAndIsRowLoaded();
void checkForceLayoutFunction();
void checkForceLayoutEndUpDoingALayout();
- void checkForceLayoutDuringModelChange();
+ void checkForceLayoutInbetweenAddingRowsToModel();
void checkForceLayoutWhenAllItemsAreHidden();
void checkLayoutChangedSignal();
void checkContentWidthAndHeight();
@@ -167,6 +168,7 @@ private slots:
void checkSyncView_pageFlicking();
void checkSyncView_emptyModel();
void checkSyncView_topLeftChanged();
+ void checkSyncView_unloadHeader();
void delegateWithRequiredProperties();
void checkThatFetchMoreIsCalledWhenScrolledToTheEndOfTable();
void replaceModel();
@@ -188,6 +190,10 @@ private slots:
void positionViewAtCellForLargeCells_data();
void positionViewAtCellForLargeCells();
void positionViewAtCellForLargeCellsUsingSubrect();
+ void positionViewAtLastRow_data();
+ void positionViewAtLastRow();
+ void positionViewAtLastColumn_data();
+ void positionViewAtLastColumn();
void itemAtCell_data();
void itemAtCell();
void leftRightTopBottomProperties_data();
@@ -208,6 +214,7 @@ private slots:
void testSelectableStartPosEndPosOutsideView();
void testSelectableScrollTowardsPos();
void setCurrentIndexFromSelectionModel();
+ void clearSelectionOnTap_data();
void clearSelectionOnTap();
void moveCurrentIndexUsingArrowKeys();
void moveCurrentIndexUsingHomeAndEndKeys();
@@ -244,6 +251,7 @@ private slots:
void deletedDelegate();
void columnResizing_data();
void columnResizing();
+ void tableViewInteractive();
void rowResizing_data();
void rowResizing();
void rowAndColumnResizing_data();
@@ -267,6 +275,17 @@ private slots:
void editWarning_nonEditableModelItem();
void attachedPropertiesOnEditDelegate();
void requiredPropertiesOnEditDelegate();
+ void resettingRolesRespected();
+ void checkScroll_data();
+ void checkScroll();
+ void checkRebuildJsModel();
+
+ // Row and column reordering
+ void checkVisualRowColumnAfterReorder();
+ void checkColumnRowSizeAfterReorder();
+ void checkCellModelIdxAfterReorder();
+ void checkEditAfterReorder();
+ void checkSelectionAfterReorder();
};
tst_QQuickTableView::tst_QQuickTableView()
@@ -300,6 +319,18 @@ QPoint tst_QQuickTableView::getContextRowAndColumn(const QQuickItem *item) const
return QPoint(column, row);
}
+static void sendWheelEvent(QQuickWindow *window, QPoint pos, QPoint angleDelta,
+ QPoint pixelDelta,
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier,
+ Qt::ScrollPhase phase = Qt::NoScrollPhase,
+ bool inverted = false) {
+ QWheelEvent wheelEvent(pos, window->mapToGlobal(pos), pixelDelta,
+ angleDelta, Qt::NoButton, modifiers, phase,
+ inverted);
+ QGuiApplication::sendEvent(window, &wheelEvent);
+ qApp->processEvents();
+}
+
void tst_QQuickTableView::setAndGetModel_data()
{
QTest::addColumn<QVariant>("model");
@@ -443,7 +474,7 @@ void tst_QQuickTableView::checkZeroSizedTableView()
WAIT_UNTIL_POLISHED;
QCOMPARE(tableViewPrivate->loadedItems.size(), 2);
- const auto item = tableView->itemAtCell(0, 0);
+ const auto item = tableView->itemAtIndex(tableView->index(0, 0));
QVERIFY(item);
QCOMPARE(item->width(), 200);
@@ -457,6 +488,17 @@ void tst_QQuickTableView::checkZeroSizedTableView()
QCOMPARE(tableViewPrivate->loadedItems.size(), 1);
}
+void tst_QQuickTableView::checkZeroSizedViewPort()
+{
+ LOAD_TABLEVIEW("zerosizedviewport.qml");
+
+ auto model = TestModelAsVariant(20, 20);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ QVERIFY(!tableViewPrivate->loadedItems.isEmpty());
+}
void tst_QQuickTableView::checkColumnWidthWithoutProvider()
{
@@ -794,10 +836,11 @@ void tst_QQuickTableView::checkForceLayoutEndUpDoingALayout()
QCOMPARE(tableView->contentHeight(), (9 * (newDelegateSize + rowSpacing)) - rowSpacing);
}
-void tst_QQuickTableView::checkForceLayoutDuringModelChange()
+void tst_QQuickTableView::checkForceLayoutInbetweenAddingRowsToModel()
{
- // Check that TableView doesn't assert if we call
- // forceLayout() in the middle of a model change.
+ // Check that TableView doesn't assert if we call forceLayout() while waiting
+ // for a callback from the model that the row count has changed. Also make sure
+ // that we don't move the contentItem while doing so.
LOAD_TABLEVIEW("plaintableview.qml");
const int initialRowCount = 10;
@@ -812,9 +855,13 @@ void tst_QQuickTableView::checkForceLayoutDuringModelChange()
WAIT_UNTIL_POLISHED;
+ const int contentY = 10;
+ tableView->setContentY(contentY);
QCOMPARE(tableView->rows(), initialRowCount);
+ QCOMPARE(tableView->contentY(), contentY);
model.addRow(0);
QCOMPARE(tableView->rows(), initialRowCount + 1);
+ QCOMPARE(tableView->contentY(), contentY);
}
void tst_QQuickTableView::checkForceLayoutWhenAllItemsAreHidden()
@@ -2451,7 +2498,7 @@ void tst_QQuickTableView::checkChangingModelFromDelegate()
// And since the QML code tried to add another row as well, we
// expect rebuildScheduled to be true, and a polish event to be pending.
QVERIFY(tableViewPrivate->scheduledRebuildOptions);
- QCOMPARE(tableViewPrivate->polishScheduled, true);
+ QVERIFY(tableViewPrivate->polishScheduled);
WAIT_UNTIL_POLISHED;
// After handling the polish event, we expect also the third row to now be added
@@ -3253,6 +3300,21 @@ void tst_QQuickTableView::checkSyncView_emptyModel()
QCOMPARE(tableViewVPrivate->loadedTableOuterRect.left(), 0);
}
+void tst_QQuickTableView::checkSyncView_unloadHeader()
+{
+ // Check that we don't get a crash in TableView if one
+ // of the sync children is suddenly deleted (from e.g a Loader).
+ LOAD_TABLEVIEW("unloadheader.qml");
+
+ const auto loader = view->rootObject()->property("loader").value<QQuickLoader *>();
+ QVERIFY(loader);
+ QVERIFY(loader->item());
+ loader->setActive(false);
+ QVERIFY(!loader->item());
+ gc(*qmlEngine(tableView));
+ tableView->forceLayout();
+}
+
void tst_QQuickTableView::checkSyncView_topLeftChanged()
{
LOAD_TABLEVIEW("syncviewsimple.qml");
@@ -3770,14 +3832,15 @@ void tst_QQuickTableView::positionViewAtCellWithAnimation()
QPoint cell(tableView->rightColumn(), tableView->bottomRow());
const QRectF cellGeometry = tableViewPrivate->loadedTableItem(cell)->geometry();
- const int modelIndex = tableViewPrivate->modelIndexAtCell(cell);
+ const int serializedIndex = tableViewPrivate->modelIndexAtCell(cell);
+ const QModelIndex index = tableView->index(cell.y(), cell.x());
- QVERIFY(tableViewPrivate->loadedItems.contains(modelIndex));
+ QVERIFY(tableViewPrivate->loadedItems.contains(serializedIndex));
QVERIFY(!tableViewPrivate->positionXAnimation.isRunning());
QVERIFY(!tableViewPrivate->positionYAnimation.isRunning());
// Animate the cell to the top left location in the view
- tableView->positionViewAtCell(cell, QQuickTableView::AlignTop | QQuickTableView::AlignLeft);
+ tableView->positionViewAtIndex(index, QQuickTableView::AlignTop | QQuickTableView::AlignLeft);
// Wait for animation to finish
QVERIFY(tableViewPrivate->positionXAnimation.isRunning());
@@ -3786,13 +3849,13 @@ void tst_QQuickTableView::positionViewAtCellWithAnimation()
QTRY_COMPARE(tableViewPrivate->positionYAnimation.isRunning(), false);
// Check that the cell is now placed in the top left corner
- QVERIFY(tableViewPrivate->loadedItems.contains(modelIndex));
+ QVERIFY(tableViewPrivate->loadedItems.contains(serializedIndex));
QPointF expectedPos = tableView->mapToItem(tableView->contentItem(), QPointF(0, 0));
QCOMPARE(cellGeometry.x(), expectedPos.x());
QCOMPARE(cellGeometry.y(), expectedPos.y());
// Animate the cell to the top right location in the view
- tableView->positionViewAtCell(cell, QQuickTableView::AlignTop | QQuickTableView::AlignRight);
+ tableView->positionViewAtIndex(index, QQuickTableView::AlignTop | QQuickTableView::AlignRight);
// Wait for animation to finish
QVERIFY(tableViewPrivate->positionXAnimation.isRunning());
@@ -3800,13 +3863,13 @@ void tst_QQuickTableView::positionViewAtCellWithAnimation()
QTRY_COMPARE(tableViewPrivate->positionXAnimation.isRunning(), false);
// Check that the cell is now placed in the top right corner
- QVERIFY(tableViewPrivate->loadedItems.contains(modelIndex));
+ QVERIFY(tableViewPrivate->loadedItems.contains(serializedIndex));
expectedPos = tableView->mapToItem(tableView->contentItem(), QPointF(tableView->width(), 0));
QCOMPARE(cellGeometry.right(), expectedPos.x());
QCOMPARE(cellGeometry.y(), expectedPos.y());
// Animate the cell to the bottom left location in the view
- tableView->positionViewAtCell(cell, QQuickTableView::AlignBottom | QQuickTableView::AlignLeft);
+ tableView->positionViewAtIndex(index, QQuickTableView::AlignBottom | QQuickTableView::AlignLeft);
// Wait for animation to finish
QVERIFY(tableViewPrivate->positionXAnimation.isRunning());
@@ -3815,7 +3878,7 @@ void tst_QQuickTableView::positionViewAtCellWithAnimation()
QTRY_COMPARE(tableViewPrivate->positionYAnimation.isRunning(), false);
// Check that the cell is now placed in the bottom left corner
- QVERIFY(tableViewPrivate->loadedItems.contains(modelIndex));
+ QVERIFY(tableViewPrivate->loadedItems.contains(serializedIndex));
expectedPos = tableView->mapToItem(tableView->contentItem(), QPointF(0, tableView->height()));
QCOMPARE(cellGeometry.x(), expectedPos.x());
QCOMPARE(cellGeometry.bottom(), expectedPos.y());
@@ -3829,7 +3892,7 @@ void tst_QQuickTableView::positionViewAtCellWithAnimation()
QTRY_COMPARE(tableViewPrivate->positionXAnimation.isRunning(), false);
// Check that the cell is now placed in the bottom right corner
- QVERIFY(tableViewPrivate->loadedItems.contains(modelIndex));
+ QVERIFY(tableViewPrivate->loadedItems.contains(serializedIndex));
expectedPos = tableView->mapToItem(tableView->contentItem(), QPointF(tableView->width(), tableView->height()));
QCOMPARE(cellGeometry.right(), expectedPos.x());
QCOMPARE(cellGeometry.bottom(), expectedPos.y());
@@ -4070,6 +4133,122 @@ void tst_QQuickTableView::positionViewAtCellForLargeCellsUsingSubrect()
QCOMPARE(tableView->contentY(), -(tableView->height() - subRect.bottom()));
}
+void tst_QQuickTableView::positionViewAtLastRow_data()
+{
+ QTest::addColumn<QString>("signalToTest");
+ QTest::addColumn<bool>("animate");
+
+ QTest::newRow("positionOnRowsChanged, animate=false") << "positionOnRowsChanged" << false;
+ QTest::newRow("positionOnRowsChanged, animate=true") << "positionOnRowsChanged" << true;
+ QTest::newRow("positionOnContentHeightChanged, animate=false") << "positionOnContentHeightChanged" << false;
+ QTest::newRow("positionOnContentHeightChanged, animate=true") << "positionOnContentHeightChanged" << true;
+}
+
+void tst_QQuickTableView::positionViewAtLastRow()
+{
+ // Check that we can make TableView always scroll to the
+ // last row in the model by positioning the view upon
+ // a rowsChanged callback
+ QFETCH(QString, signalToTest);
+ QFETCH(bool, animate);
+
+ LOAD_TABLEVIEW("positionlast.qml");
+
+ // Use a very large model to indirectly test that we "fast-flick" to
+ // the end at start-up (instead of loading and unloading rows, which
+ // would take forever).
+ TestModel model(2000000, 2000000);
+ tableView->setModel(QVariant::fromValue(&model));
+ tableView->setAnimate(animate);
+
+ view->rootObject()->setProperty(signalToTest.toUtf8().constData(), true);
+
+ WAIT_UNTIL_POLISHED;
+
+ const qreal delegateSize = 100.;
+ const qreal viewportRowCount = tableView->height() / delegateSize;
+
+ // Check that the viewport is positioned at the last row at start-up
+ QCOMPARE(tableView->rows(), model.rowCount());
+ QCOMPARE(tableView->bottomRow(), model.rowCount() - 1);
+ QCOMPARE(tableView->contentY(), (model.rowCount() - viewportRowCount) * delegateSize);
+
+ // Check that the viewport is positioned at the last
+ // row after more rows are added.
+ for (int row = 0; row < 2; ++row) {
+ model.addRow(model.rowCount() - 1);
+
+ WAIT_UNTIL_POLISHED;
+
+ if (tableView->animate()) {
+ QVERIFY(tableViewPrivate->positionYAnimation.isRunning());
+ QTRY_VERIFY(!tableViewPrivate->positionYAnimation.isRunning());
+ }
+
+ QCOMPARE(tableView->rows(), model.rowCount());
+ QCOMPARE(tableView->bottomRow(), model.rowCount() - 1);
+ QCOMPARE(tableView->contentY(), (model.rowCount() - viewportRowCount) * delegateSize);
+ }
+}
+
+void tst_QQuickTableView::positionViewAtLastColumn_data()
+{
+ QTest::addColumn<QString>("signalToTest");
+ QTest::addColumn<bool>("animate");
+
+ QTest::newRow("positionOnColumnsChanged, animate=false") << "positionOnColumnsChanged" << false;
+ QTest::newRow("positionOnColumnsChanged, animate=true") << "positionOnColumnsChanged" << true;
+ QTest::newRow("positionOnContentWidthChanged, animate=false") << "positionOnContentWidthChanged" << false;
+ QTest::newRow("positionOnContentWidthChanged, animate=true") << "positionOnContentWidthChanged" << true;
+}
+
+void tst_QQuickTableView::positionViewAtLastColumn()
+{
+ // Check that we can make TableView always scroll to the
+ // last column in the model by positioning the view upon
+ // a columnsChanged callback
+ QFETCH(QString, signalToTest);
+ QFETCH(bool, animate);
+
+ LOAD_TABLEVIEW("positionlast.qml");
+
+ // Use a very large model to indirectly test that we "fast-flick" to
+ // the end at start-up (instead of loading and unloading columns, which
+ // would take forever).
+ TestModel model(2000000, 2000000);
+ tableView->setModel(QVariant::fromValue(&model));
+ tableView->setAnimate(animate);
+
+ view->rootObject()->setProperty(signalToTest.toUtf8().constData(), true);
+
+ WAIT_UNTIL_POLISHED;
+
+ const qreal delegateSize = 100.;
+ const qreal viewportColumnCount = tableView->width() / delegateSize;
+
+ // Check that the viewport is positioned at the last column at start-up
+ QCOMPARE(tableView->columns(), model.columnCount());
+ QCOMPARE(tableView->rightColumn(), model.columnCount() - 1);
+ QCOMPARE(tableView->contentX(), (model.columnCount() - viewportColumnCount) * delegateSize);
+
+ // Check that the viewport is positioned at the last
+ // column after more columns are added.
+ for (int column = 0; column < 2; ++column) {
+ model.addColumn(model.columnCount() - 1);
+
+ WAIT_UNTIL_POLISHED;
+
+ if (tableView->animate()) {
+ QVERIFY(tableViewPrivate->positionXAnimation.isRunning());
+ QTRY_VERIFY(!tableViewPrivate->positionXAnimation.isRunning());
+ }
+
+ QCOMPARE(tableView->columns(), model.columnCount());
+ QCOMPARE(tableView->rightColumn(), model.columnCount() - 1);
+ QCOMPARE(tableView->contentX(), (model.columnCount() - viewportColumnCount) * delegateSize);
+ }
+}
+
void tst_QQuickTableView::itemAtCell_data()
{
QTest::addColumn<QPoint>("cell");
@@ -4378,7 +4557,7 @@ void tst_QQuickTableView::warnOnWrongModelInSelectionModel()
selectionModel.setModel(&model2);
// And change currentIndex. This will produce a warning.
- QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*model differs.*"));
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*TableView.selectionModel.model.*"));
selectionModel.setCurrentIndex(model2.index(0, 0), QItemSelectionModel::NoUpdate);
}
@@ -4410,9 +4589,10 @@ void tst_QQuickTableView::selectionBehaviorCells_data()
void tst_QQuickTableView::selectionBehaviorCells()
{
- // Check that the TableView implement QQuickSelectableInterface setSelectionStartPos, setSelectionEndPos
- // and clearSelection correctly. Do this by calling setSelectionStartPos/setSelectionEndPos on top of
- // different cells, and see that we end up with the expected selections.
+ // Check that the TableView implement QQuickSelectableInterface startSelection,
+ // setSelectionStartPos, setSelectionEndPos and clearSelection correctly. Do this by
+ // calling setSelectionStartPos/setSelectionEndPos on top of different cells, and see
+ // that we end up with the expected selections.
QFETCH(QPoint, endCellDist);
LOAD_TABLEVIEW("tableviewwithselected1.qml");
@@ -4442,6 +4622,7 @@ void tst_QQuickTableView::selectionBehaviorCells()
const QPointF endPos(endItem->x(), endItem->y());
const QPointF endPosWrapped(endItemWrapped->x(), endItemWrapped->y());
+ QVERIFY(tableViewPrivate->startSelection(startPos, Qt::NoModifier));
tableViewPrivate->setSelectionStartPos(startPos);
tableViewPrivate->setSelectionEndPos(endPos);
@@ -4482,8 +4663,9 @@ void tst_QQuickTableView::selectionBehaviorCells()
void tst_QQuickTableView::selectionBehaviorRows()
{
- // Check that the TableView implement QQuickSelectableInterface setSelectionStartPos, setSelectionEndPos
- // and clearSelection correctly for QQuickTableView::SelectRows.
+ // Check that the TableView implement QQuickSelectableInterface startSelection,
+ // setSelectionStartPos, setSelectionEndPos and clearSelection correctly for
+ // QQuickTableView::SelectRows.
LOAD_TABLEVIEW("tableviewwithselected1.qml");
TestModel model(10, 10);
@@ -4498,6 +4680,7 @@ void tst_QQuickTableView::selectionBehaviorRows()
QCOMPARE(selectionModel.hasSelection(), false);
// Drag from row 0 to row 3
+ QVERIFY(tableViewPrivate->startSelection(QPointF(0, 0), Qt::NoModifier));
tableViewPrivate->setSelectionStartPos(QPointF(0, 0));
tableViewPrivate->setSelectionEndPos(QPointF(60, 60));
@@ -4518,6 +4701,7 @@ void tst_QQuickTableView::selectionBehaviorRows()
QCOMPARE(selectionModel.hasSelection(), false);
// Drag from row 3 to row 0 (and overshoot mouse)
+ QVERIFY(tableViewPrivate->startSelection(QPointF(60, 60), Qt::NoModifier));
tableViewPrivate->setSelectionStartPos(QPointF(60, 60));
tableViewPrivate->setSelectionEndPos(QPointF(-10, -10));
@@ -4536,8 +4720,9 @@ void tst_QQuickTableView::selectionBehaviorRows()
void tst_QQuickTableView::selectionBehaviorColumns()
{
- // Check that the TableView implement QQuickSelectableInterface setSelectionStartPos, setSelectionEndPos
- // and clearSelection correctly for QQuickTableView::SelectColumns.
+ // Check that the TableView implement QQuickSelectableInterface startSelection,
+ // setSelectionStartPos, setSelectionEndPos and clearSelection correctly for
+ // QQuickTableView::SelectColumns.
LOAD_TABLEVIEW("tableviewwithselected1.qml");
TestModel model(10, 10);
@@ -4552,6 +4737,7 @@ void tst_QQuickTableView::selectionBehaviorColumns()
QCOMPARE(selectionModel.hasSelection(), false);
// Drag from column 0 to column 3
+ QVERIFY(tableViewPrivate->startSelection(QPointF(60, 60), Qt::NoModifier));
tableViewPrivate->setSelectionStartPos(QPointF(0, 0));
tableViewPrivate->setSelectionEndPos(QPointF(60, 60));
@@ -4572,6 +4758,7 @@ void tst_QQuickTableView::selectionBehaviorColumns()
QCOMPARE(selectionModel.hasSelection(), false);
// Drag from column 3 to column 0 (and overshoot mouse)
+ QVERIFY(tableViewPrivate->startSelection(QPointF(60, 60), Qt::NoModifier));
tableViewPrivate->setSelectionStartPos(QPointF(60, 60));
tableViewPrivate->setSelectionEndPos(QPointF(-10, -10));
@@ -4590,8 +4777,8 @@ void tst_QQuickTableView::selectionBehaviorColumns()
void tst_QQuickTableView::selectionBehaviorDisabled()
{
- // Check that the TableView implement QQuickSelectableInterface setSelectionStartPos, setSelectionEndPos
- // and clearSelection correctly for QQuickTableView::SelectionDisabled.
+ // Check that the TableView implement QQuickSelectableInterface startSelection
+ // correctly for QQuickTableView::SelectionDisabled.
LOAD_TABLEVIEW("tableviewwithselected1.qml");
TestModel model(10, 10);
@@ -4605,18 +4792,18 @@ void tst_QQuickTableView::selectionBehaviorDisabled()
QCOMPARE(selectionModel.hasSelection(), false);
- // Drag from column 0 to column 3
- tableViewPrivate->setSelectionStartPos(QPointF(0, 0));
- tableViewPrivate->setSelectionEndPos(QPointF(60, 60));
+ // Try to start a selection
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*TableView.SelectionDisabled"));
+ QVERIFY(!tableViewPrivate->startSelection(QPointF(0, 0), Qt::NoModifier));
QCOMPARE(selectionModel.hasSelection(), false);
}
void tst_QQuickTableView::testSelectableStartPosEndPosOutsideView()
{
- // Call setSelectionStartPos and setSelectionEndPos with positions outside the view.
- // This should first of all not crash, but instead just clamp the selection to the
- // cells that are visible inside the view.
+ // Call startSelection, setSelectionStartPos and setSelectionEndPos with positions
+ // outside the view. This should first of all not crash, but instead just clamp the
+ // selection to the cells that are visible inside the view.
LOAD_TABLEVIEW("tableviewwithselected1.qml");
TestModel model(10, 10);
@@ -4637,6 +4824,7 @@ void tst_QQuickTableView::testSelectableStartPosEndPosOutsideView()
const QPointF outsideTop(centerPos.x(), -100);
const QPointF outsideBottom(centerPos.x(), tableView->height() + 100);
+ QVERIFY(tableViewPrivate->startSelection(centerPos, Qt::NoModifier));
tableViewPrivate->setSelectionStartPos(centerPos);
tableViewPrivate->setSelectionEndPos(outsideLeft);
@@ -4687,23 +4875,23 @@ void tst_QQuickTableView::testSelectableScrollTowardsPos()
const QPointF bottomLeft(-100, tableView->height() + 100);
const QPointF bottomRight(tableView->width() + 100, tableView->height() + 100);
- tableViewPrivate->scrollTowardsSelectionPoint(topRight, step);
+ tableViewPrivate->scrollTowardsPoint(topRight, step);
QCOMPARE(tableView->contentX(), step.width());
QCOMPARE(tableView->contentY(), 0);
- tableViewPrivate->scrollTowardsSelectionPoint(bottomRight, step);
+ tableViewPrivate->scrollTowardsPoint(bottomRight, step);
QCOMPARE(tableView->contentX(), step.width() * 2);
QCOMPARE(tableView->contentY(), step.height());
- tableViewPrivate->scrollTowardsSelectionPoint(bottomLeft, step);
+ tableViewPrivate->scrollTowardsPoint(bottomLeft, step);
QCOMPARE(tableView->contentX(), step.width());
QCOMPARE(tableView->contentY(), step.height() * 2);
- tableViewPrivate->scrollTowardsSelectionPoint(topLeft, step);
+ tableViewPrivate->scrollTowardsPoint(topLeft, step);
QCOMPARE(tableView->contentX(), 0);
QCOMPARE(tableView->contentY(), step.height());
- tableViewPrivate->scrollTowardsSelectionPoint(topLeft, step);
+ tableViewPrivate->scrollTowardsPoint(topLeft, step);
QCOMPARE(tableView->contentX(), 0);
QCOMPARE(tableView->contentY(), 0);
}
@@ -4743,12 +4931,25 @@ void tst_QQuickTableView::setCurrentIndexFromSelectionModel()
QVERIFY(tableView->itemAtCell(cellAtEnd)->property(kCurrent).toBool());
}
+void tst_QQuickTableView::clearSelectionOnTap_data()
+{
+ QTest::addColumn<bool>("selectionEnabled");
+ QTest::newRow("selections enabled") << true;
+ QTest::newRow("selections disabled") << false;
+}
+
void tst_QQuickTableView::clearSelectionOnTap()
{
+ // Check that we clear the current selection when tapping
+ // inside TableView. But only if TableView has selections
+ // enabled. Otherwise, TableView should not touch the selection model.
+ QFETCH(bool, selectionEnabled);
LOAD_TABLEVIEW("tableviewwithselected2.qml");
TestModel model(40, 40);
tableView->setModel(QVariant::fromValue(&model));
+ if (!selectionEnabled)
+ tableView->setSelectionBehavior(QQuickTableView::SelectionDisabled);
WAIT_UNTIL_POLISHED;
@@ -4757,13 +4958,14 @@ void tst_QQuickTableView::clearSelectionOnTap()
tableView->selectionModel()->select(index, QItemSelectionModel::Select);
QCOMPARE(tableView->selectionModel()->selectedIndexes().size(), 1);
- // Click on a cell. This should remove the selection
- const auto item = tableView->itemAtCell(0, 0);
+ // Click on a cell
+ const auto item = tableView->itemAtIndex(tableView->index(0, 0));
QVERIFY(item);
QPoint localPos = QPoint(item->width() / 2, item->height() / 2);
QPoint pos = item->window()->contentItem()->mapFromItem(item, localPos).toPoint();
QTest::mouseClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos);
- QCOMPARE(tableView->selectionModel()->selectedIndexes().size(), 0);
+
+ QCOMPARE(tableView->selectionModel()->hasSelection(), !selectionEnabled);
}
void tst_QQuickTableView::moveCurrentIndexUsingArrowKeys()
@@ -5358,7 +5560,7 @@ void tst_QQuickTableView::disablePointerNavigation()
// Enable navigation, and try again
tableView->setPointerNavigationEnabled(true);
QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, pos);
- QCOMPARE(selectionModel.currentIndex(), tableView->modelIndex(0, 0));
+ QCOMPARE(selectionModel.currentIndex(), tableView->index(0, 0));
QVERIFY(item0_0->property("current").toBool());
QCOMPARE(tableView->currentColumn(), cell0_0.x());
QCOMPARE(tableView->currentRow(), cell0_0.y());
@@ -5754,7 +5956,7 @@ void tst_QQuickTableView::boundDelegateComponent()
QVERIFY(inner != nullptr);
QQuickTableView *tableView = qobject_cast<QQuickTableView *>(inner);
QVERIFY(tableView != nullptr);
- QObject *item = tableView->itemAtCell(0, 0);
+ QObject *item = tableView->itemAtCell({0, 0});
QVERIFY(item);
QCOMPARE(item->objectName(), QLatin1String("fooouterundefined"));
@@ -5762,7 +5964,7 @@ void tst_QQuickTableView::boundDelegateComponent()
QVERIFY(inner2 != nullptr);
QQuickTableView *tableView2 = qobject_cast<QQuickTableView *>(inner2);
QVERIFY(tableView2 != nullptr);
- QObject *item2 = tableView2->itemAtCell(0, 0);
+ QObject *item2 = tableView2->itemAtCell({0, 0});
QVERIFY(item2);
QCOMPARE(item2->objectName(), QLatin1String("fooouter0"));
@@ -5784,7 +5986,7 @@ void tst_QQuickTableView::boundDelegateComponent()
QVERIFY(innerTableView != nullptr);
QCOMPARE(innerTableView->rows(), 3);
for (int i = 0; i < 3; ++i)
- QVERIFY(innerTableView->itemAtCell(0, i)->objectName().isEmpty());
+ QVERIFY(innerTableView->itemAtIndex(innerTableView->index(i, 0))->objectName().isEmpty());
}
void tst_QQuickTableView::setColumnWidth_data()
@@ -6127,6 +6329,47 @@ void tst_QQuickTableView::deletedDelegate()
QTRY_COMPARE(tv->delegate(), nullptr);
}
+void tst_QQuickTableView::tableViewInteractive()
+{
+ LOAD_TABLEVIEW("tableviewinteractive.qml");
+
+ auto *root = view->rootObject();
+ QVERIFY(root);
+ auto *window = root->window();
+ QVERIFY(window);
+
+ int eventCount = root->property("eventCount").toInt();
+ QCOMPARE(eventCount, 0);
+
+ // Event though we make 'interactive' as false, the TableView has
+ // pointerNacigationEnabled set as true by default, which allows it to consume
+ // mouse events and thus, eventCount still be zero
+ tableView->setInteractive(false);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(100, 100));
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(100, 100));
+ eventCount = root->property("eventCount").toInt();
+ QCOMPARE(eventCount, 0);
+
+ // Making both 'interactive' and 'pointerNavigationEnabled' as false, doesn't
+ // allow TableView (and its parent Flickable) to consume mouse event and it
+ // passes to the below visual item
+ tableView->setInteractive(false);
+ tableView->setPointerNavigationEnabled(false);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(100, 100));
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(100, 100));
+ eventCount = root->property("eventCount").toInt();
+ QCOMPARE(eventCount, 1);
+
+ // Making 'interactive' as true and 'pointerNavigationEnabled' as false,
+ // allows parent of TableView (i.e. Flickable) to consume mouse events
+ tableView->setInteractive(true);
+ tableView->setPointerNavigationEnabled(false);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(100, 100));
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(100, 100));
+ eventCount = root->property("eventCount").toInt();
+ QCOMPARE(eventCount, 1);
+}
+
void tst_QQuickTableView::columnResizing_data()
{
QTest::addColumn<int>("column");
@@ -6161,7 +6404,7 @@ void tst_QQuickTableView::columnResizing()
QSignalSpy currentIndexSpy(tableView->selectionModel(), &QItemSelectionModel::currentChanged);
QSignalSpy selectionSpy(tableView->selectionModel(), &QItemSelectionModel::selectionChanged);
- const auto item = tableView->itemAtCell(column, 0);
+ const auto item = tableView->itemAtIndex(tableView->index(0, column));
QQuickWindow *window = item->window();
const qreal columnStartWidth = tableView->columnWidth(column);
@@ -6212,7 +6455,7 @@ void tst_QQuickTableView::rowResizing()
QSignalSpy currentIndexSpy(tableView->selectionModel(), &QItemSelectionModel::currentChanged);
QSignalSpy selectionSpy(tableView->selectionModel(), &QItemSelectionModel::selectionChanged);
- const auto item = tableView->itemAtCell(0, row);
+ const auto item = tableView->itemAtIndex(tableView->index(row, 0));
QQuickWindow *window = item->window();
const qreal rowStartHeight = tableView->rowHeight(row);
@@ -6265,7 +6508,7 @@ void tst_QQuickTableView::rowAndColumnResizing()
QCOMPARE(tableView->explicitColumnWidth(rowAndColumn), -1);
QCOMPARE(tableView->explicitRowHeight(rowAndColumn), -1);
- const auto item = tableView->itemAtCell(rowAndColumn, rowAndColumn);
+ const auto item = tableView->itemAtIndex(tableView->index(rowAndColumn, rowAndColumn));
QVERIFY(item);
if (addDelegateDragHandler) {
@@ -6320,7 +6563,7 @@ void tst_QQuickTableView::columnResizingDisabled()
const int row = 1;
QCOMPARE(tableView->explicitRowHeight(row), -1);
- const auto item = tableView->itemAtCell(0, row);
+ const auto item = tableView->itemAtIndex(tableView->index(row, 0));
QQuickWindow *window = item->window();
const QPoint localPos = QPoint(item->width() / 2, item->height());
@@ -6357,7 +6600,7 @@ void tst_QQuickTableView::rowResizingDisabled()
const int row = 1;
QCOMPARE(tableView->explicitRowHeight(row), -1);
- const auto item = tableView->itemAtCell(0, row);
+ const auto item = tableView->itemAtIndex(tableView->index(row, 0));
QQuickWindow *window = item->window();
const QPoint localPos = QPoint(item->width() / 2, item->height());
@@ -6395,7 +6638,7 @@ void tst_QQuickTableView::dragFromCellCenter()
const int row = 1;
QCOMPARE(tableView->explicitRowHeight(row), -1);
- const auto item = tableView->itemAtCell(0, row);
+ const auto item = tableView->itemAtIndex(tableView->index(row, 0));
QQuickWindow *window = item->window();
const QPoint localPos = QPoint(item->width() / 2, item->height() / 2);
@@ -6590,7 +6833,7 @@ void tst_QQuickTableView::editUsingEditTriggers()
if (editTriggers & QQuickTableView::SelectedTapped) {
// select cell first, then tap on it
- tableView->selectionModel()->setCurrentIndex(index1, QItemSelectionModel::NoUpdate);
+ tableView->selectionModel()->setCurrentIndex(index1, QItemSelectionModel::Select);
QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos1);
QCOMPARE(tableView->selectionModel()->currentIndex(), index1);
const auto editItem1 = tableView->property(kEditItem).value<QQuickItem *>();
@@ -6611,6 +6854,11 @@ void tst_QQuickTableView::editUsingEditTriggers()
QVERIFY(!tableView->property(kEditItem).value<QQuickItem *>());
QVERIFY(!tableView->property(kEditIndex).value<QModelIndex>().isValid());
QCOMPARE(tableView->selectionModel()->currentIndex(), index2);
+
+ // tap on the current cell. This alone should not start an edit (unless it's also selected)
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos1);
+ QVERIFY(!tableView->property(kEditItem).value<QQuickItem *>());
+ QVERIFY(!tableView->property(kEditIndex).value<QModelIndex>().isValid());
}
if (editTriggers & QQuickTableView::EditKeyPressed) {
@@ -7075,7 +7323,7 @@ void tst_QQuickTableView::editWarning_noEditDelegate()
WAIT_UNTIL_POLISHED;
QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*cannot edit: no TableView.editDelegate set!"));
- tableView->edit(tableView->modelIndex(1, 1));
+ tableView->edit(tableView->index(1, 1));
}
void tst_QQuickTableView::editWarning_invalidIndex()
@@ -7090,7 +7338,7 @@ void tst_QQuickTableView::editWarning_invalidIndex()
WAIT_UNTIL_POLISHED;
QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*cannot edit: index is not valid!"));
- tableView->edit(tableView->modelIndex(-1, -1));
+ tableView->edit(tableView->index(-1, -1));
}
void tst_QQuickTableView::editWarning_nonEditableModelItem()
@@ -7108,7 +7356,7 @@ void tst_QQuickTableView::editWarning_nonEditableModelItem()
WAIT_UNTIL_POLISHED;
QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*cannot edit:.*flags.*Qt::ItemIsEditable"));
- tableView->edit(tableView->modelIndex(1, 1));
+ tableView->edit(tableView->index(1, 1));
}
void tst_QQuickTableView::attachedPropertiesOnEditDelegate()
@@ -7214,7 +7462,7 @@ void tst_QQuickTableView::requiredPropertiesOnEditDelegate()
const QPoint cell(1, 1);
const QModelIndex index1 = tableView->modelIndex(cell);
- const QModelIndex index2 = tableView->modelIndex(2, 2);
+ const QModelIndex index2 = tableView->index(2, 2);
tableView->edit(index1);
@@ -7232,6 +7480,311 @@ void tst_QQuickTableView::requiredPropertiesOnEditDelegate()
QCOMPARE(textInput->property("current").toBool(), false);
}
+void tst_QQuickTableView::resettingRolesRespected()
+{
+ LOAD_TABLEVIEW("resetModelData.qml");
+
+ TestModel model(1, 1);
+ tableView->setModel(QVariant::fromValue(&model));
+
+ WAIT_UNTIL_POLISHED;
+
+ QVERIFY(!tableView->property("success").toBool());
+ model.useCustomRoleNames(true);
+ QTRY_VERIFY(tableView->property("success").toBool());
+}
+
+void tst_QQuickTableView::checkScroll_data()
+{
+ QTest::addColumn<bool>("resizableColumns");
+ QTest::addColumn<bool>("resizableRows");
+ QTest::newRow("T, T") << true << true;
+ QTest::newRow("T, F") << true << false;
+ QTest::newRow("F, T") << false << true;
+ QTest::newRow("F, F") << false << false;
+}
+
+/*!
+ Make sure that the TableView is scrollable regardless
+ of the values of resizableColumns and resizableRows.
+*/
+void tst_QQuickTableView::checkScroll() // QTBUG-116566
+{
+ QFETCH(bool, resizableColumns);
+ QFETCH(bool, resizableRows);
+ LOAD_TABLEVIEW("plaintableview.qml"); // gives us 'tableView' variable
+
+ tableView->setResizableColumns(resizableColumns);
+ tableView->setResizableRows(resizableRows);
+
+ auto model = TestModelAsVariant(20, 10);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ // Scroll with the mouse wheel
+ sendWheelEvent(view, {10, 10}, {0, -120}, {0, -120});
+
+ // Check that scrolling succeeded
+ QTRY_COMPARE_GT(tableView->contentY(), 20);
+}
+
+void tst_QQuickTableView::checkRebuildJsModel()
+{
+ LOAD_TABLEVIEW("resetJsModelData.qml"); // gives us 'tableView' variable
+
+ // Generate javascript model
+ const int size = 5;
+ const char* modelUpdated = "modelUpdated";
+
+ QJSEngine jsEngine;
+ QJSValue jsArray;
+ jsArray = jsEngine.newArray(size);
+ for (int i = 0; i < size; ++i)
+ jsArray.setProperty(i, QRandomGenerator::global()->generate());
+
+ QVariant jsModel = QVariant::fromValue(jsArray);
+ tableView->setModel(jsModel);
+ WAIT_UNTIL_POLISHED;
+
+ // Model change would be triggered for the first time
+ QCOMPARE(tableView->property(modelUpdated).toInt(), 1);
+
+ // Set the same model once again and check if model changes
+ tableView->setModel(jsModel);
+ QCOMPARE(tableView->property(modelUpdated).toInt(), 1);
+}
+
+void tst_QQuickTableView::checkVisualRowColumnAfterReorder()
+{
+ LOAD_TABLEVIEW("reordertableview.qml"); // gives us 'tableView' variable
+ auto model = TestModelAsVariant(3, 3);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ QSignalSpy columnMovedSpy(tableView, &QQuickTableView::columnMoved);
+ QSignalSpy rowMovedSpy(tableView, &QQuickTableView::rowMoved);
+
+ // Move row and column
+ tableView->moveColumn(0, 2);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(columnMovedSpy.size(), 3);
+
+ tableView->moveRow(1, 0);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(rowMovedSpy.size(), 2);
+
+ QVariantList firstColumnVar = columnMovedSpy.takeFirst();
+ QCOMPARE(firstColumnVar.at(0), 0); // Logical index
+ QCOMPARE(firstColumnVar.at(1), 0); // Old visual index
+ QCOMPARE(firstColumnVar.at(2), 2); // New visual index
+
+ QVariantList firstRowVar = rowMovedSpy.takeFirst();
+ QCOMPARE(firstRowVar.at(0), 0); // Logical index
+ QCOMPARE(firstRowVar.at(1), 0); // Old visual index
+ QCOMPARE(firstRowVar.at(2), 1); // New visual index
+}
+
+void tst_QQuickTableView::checkColumnRowSizeAfterReorder()
+{
+ LOAD_TABLEVIEW("reordertableview.qml"); // gives us 'tableView' variable
+ auto model = TestModelAsVariant(3, 3);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ const QSignalSpy columMovedSpy(tableView, &QQuickTableView::columnMoved);
+ const QSignalSpy rowMovedSpy(tableView, &QQuickTableView::rowMoved);
+
+ for (int index = 0, minSize = 10; index < tableView->columns(); index++, minSize+=10) {
+ tableView->setColumnWidth(index, minSize);
+ tableView->setRowHeight(index, minSize);
+ }
+ WAIT_UNTIL_POLISHED;
+
+ // Move row and column
+ tableView->moveColumn(0, 2);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(columMovedSpy.size(), 3);
+
+ tableView->moveRow(0, 2);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(rowMovedSpy.size(), 3);
+
+ QCOMPARE(tableView->columnWidth(0), 20);
+ QCOMPARE(tableView->columnWidth(1), 30);
+ QCOMPARE(tableView->columnWidth(2), 10);
+
+ QCOMPARE(tableView->rowHeight(0), 20);
+ QCOMPARE(tableView->rowHeight(1), 30);
+ QCOMPARE(tableView->rowHeight(2), 10);
+}
+
+void tst_QQuickTableView::checkCellModelIdxAfterReorder()
+{
+ LOAD_TABLEVIEW("reordertableview.qml"); // gives us 'tableView' variable
+ auto model = TestModelAsVariant(3, 3);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ const QSignalSpy columnMovedSpy(tableView, &QQuickTableView::columnMoved);
+ const QSignalSpy rowMovedSpy(tableView, &QQuickTableView::rowMoved);
+
+ const QSharedPointer<TestModel> testModel = model.value<QSharedPointer<TestModel>>();
+ const QString objNameItem21(tableView->itemAtIndex(testModel->index(2, 1))->objectName());
+ const QString objNameItem00(tableView->itemAtIndex(testModel->index(0 ,0))->objectName());
+ const QString objNameItem11(tableView->itemAtIndex(testModel->index(1 ,1))->objectName());
+
+ // Move row and column
+ tableView->moveColumn(0, 2);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(columnMovedSpy.size(), 3);
+
+ tableView->moveRow(1, 0);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(rowMovedSpy.size(), 2);
+
+ // Check model index - index()
+ QModelIndex modelIndex = tableView->index(0, 0);
+ QCOMPARE(modelIndex.column(), 1);
+ QCOMPARE(modelIndex.row(), 1);
+
+ modelIndex = tableView->index(1, 1);
+ QCOMPARE(modelIndex.column(), 2);
+ QCOMPARE(modelIndex.row(), 0);
+
+ modelIndex = tableView->index(2, 2);
+ QCOMPARE(modelIndex.column(), 0);
+ QCOMPARE(modelIndex.row(), 2);
+
+ // Check cell index - cellAtIndex()
+ {
+ QPoint cell = tableView->cellAtIndex(testModel->index(0, 0));
+ QCOMPARE(cell.x(), 2);
+ QCOMPARE(cell.y(), 1);
+ }
+
+ // Check column and row index - columnAtIndex(), rowAtIndex()
+ {
+ int columnIndex = tableView->columnAtIndex(testModel->index(0, 0));
+ int rowIndex = tableView->rowAtIndex(testModel->index(0, 0));
+ QCOMPARE(columnIndex, 2);
+ QCOMPARE(rowIndex, 1);
+ }
+
+ // Check item - itemAtIndex()
+ // Item at index provides the item that is mapped to that model index
+ // and it shouldn't be confused with cell index
+ {
+ QQuickItem *item = tableView->itemAtIndex(testModel->index(0 ,0));
+ QCOMPARE(objNameItem00, item->objectName());
+ }
+
+ // Check item at cell localtion 0, 0 - itemAtCell()
+ {
+ QQuickItem *item = tableView->itemAtCell(QPoint(0, 0));
+ QCOMPARE(objNameItem11, item->objectName());
+ }
+}
+
+void tst_QQuickTableView::checkEditAfterReorder()
+{
+ LOAD_TABLEVIEW("editdelegate.qml"); // gives us 'tableView' variable
+ auto model = TestModelAsVariant(3, 3);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ const QSignalSpy columnMovedSpy(tableView, &QQuickTableView::columnMoved);
+ const QSignalSpy rowMovedSpy(tableView, &QQuickTableView::rowMoved);
+
+ // Move row and column
+ tableView->moveColumn(0, 1);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(columnMovedSpy.size(), 2);
+
+ tableView->moveRow(0, 1);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(rowMovedSpy.size(), 2);
+
+ // Edit model index (0, 0)
+ const QSharedPointer<TestModel> testModel = model.value<QSharedPointer<TestModel>>();
+ const auto cellItem1 = tableView->itemAtCell(QPoint(0, 0));
+ QCOMPARE(cellItem1->property("editing").toBool(), false);
+
+ tableView->edit(testModel->index(1, 1));
+ QCOMPARE(cellItem1->property("editing").toBool(), true);
+
+ // Close the editor
+ tableView->closeEditor();
+ QCOMPARE(cellItem1->property("editing").toBool(), false);
+}
+
+void tst_QQuickTableView::checkSelectionAfterReorder()
+{
+ LOAD_TABLEVIEW("tableviewwithselected1.qml");
+
+ TestModel model(10, 10);
+ QItemSelectionModel selectionModel(&model);
+
+ tableView->setModel(QVariant::fromValue(&model));
+ tableView->setSelectionModel(&selectionModel);
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(selectionModel.hasSelection(), false);
+ QCOMPARE(tableView->selectionBehavior(), QQuickTableView::SelectCells);
+
+ const QSignalSpy columnMovedSpy(tableView, &QQuickTableView::columnMoved);
+ tableView->moveColumn(0, 2);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(columnMovedSpy.size(), 3);
+
+ const QPoint endCellDist(1, 1);
+ const QPoint startCell(0, 0);
+ const QPoint endCell = startCell + endCellDist;
+
+ const QQuickItem *startItem = tableView->itemAtCell(startCell);
+ const QQuickItem *endItem = tableView->itemAtCell(endCell);
+ QVERIFY(startItem);
+ QVERIFY(endItem);
+
+ const QPointF startPos(startItem->x(), startItem->y());
+ const QPointF endPos(endItem->x(), endItem->y());
+
+ QVERIFY(tableViewPrivate->startSelection(startPos, Qt::NoModifier));
+ tableViewPrivate->setSelectionStartPos(startPos);
+ tableViewPrivate->setSelectionEndPos(endPos);
+
+ QCOMPARE(selectionModel.hasSelection(), true);
+
+ const int x1 = qMin(startCell.x(), endCell.x());
+ const int x2 = qMax(startCell.x(), endCell.x());
+ const int y1 = qMin(startCell.y(), endCell.y());
+ const int y2 = qMax(startCell.y(), endCell.y());
+
+ for (int x = x1; x <= x2; ++x) {
+ for (int y = y1; y <= y2; ++y) {
+ const auto index = tableView->index(y, x);
+ QVERIFY(selectionModel.isSelected(index));
+ }
+ }
+
+ const int expectedCount = (x2 - x1 + 1) * (y2 - y1 + 1);
+ const int actualCount = selectionModel.selectedIndexes().size();
+ QCOMPARE(actualCount, expectedCount);
+
+ // The column which has been moved shouldn't have the selected
+ // bit enabled
+ for (int index = 0; index < model.rowCount(); index++)
+ QCOMPARE(selectionModel.isSelected(model.index(index, 0)), false);
+
+ tableViewPrivate->clearSelection();
+ QCOMPARE(selectionModel.hasSelection(), false);
+}
+
QTEST_MAIN(tst_QQuickTableView)
#include "tst_qquicktableview.moc"
diff --git a/tests/auto/quick/qquicktext/BLACKLIST b/tests/auto/quick/qquicktext/BLACKLIST
index a4e9c44eab..46936293ca 100644
--- a/tests/auto/quick/qquicktext/BLACKLIST
+++ b/tests/auto/quick/qquicktext/BLACKLIST
@@ -3,6 +3,7 @@ opensuse-42.1
[contentSize]
windows gcc
msvc-2019
+msvc-2022
[hAlignVisual]
sles
# QTQAINFRA-4127
diff --git a/tests/auto/quick/qquicktext/CMakeLists.txt b/tests/auto/quick/qquicktext/CMakeLists.txt
index b4f2bae534..68330befd9 100644
--- a/tests/auto/quick/qquicktext/CMakeLists.txt
+++ b/tests/auto/quick/qquicktext/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicktext Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicktext LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquicktext/data/elideZeroWidthWithMargins.qml b/tests/auto/quick/qquicktext/data/elideZeroWidthWithMargins.qml
new file mode 100644
index 0000000000..bb269e6ad5
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/elideZeroWidthWithMargins.qml
@@ -0,0 +1,27 @@
+import QtQuick
+
+Item {
+ id: root
+ property bool ok: false
+ width: 640
+ height: 480
+
+ Text {
+ id: text
+ text: "This is a quite long text. Click me and i should remain visible!!! Sadly this doesn't happen"
+ elide: Text.ElideRight
+ anchors {
+ fill: parent
+ margins: 1
+ }
+ }
+
+ Component.onCompleted: {
+ text.width = 300;
+ text.height = 0;
+ text.width = 0;
+ text.height = 30;
+ text.width = 300;
+ root.ok = text.paintedWidth > 0 && text.paintedHeight > 0
+ }
+}
diff --git a/tests/auto/quick/qquicktext/data/lineLayout.qml b/tests/auto/quick/qquicktext/data/lineLayout.qml
index 5a980de7da..74b9ecb500 100644
--- a/tests/auto/quick/qquicktext/data/lineLayout.qml
+++ b/tests/auto/quick/qquicktext/data/lineLayout.qml
@@ -20,7 +20,7 @@ Rectangle {
text: "<b>Lorem ipsum</b> dolor sit amet, consectetur adipiscing elit. Integer at ante dui. Sed eu egestas est.
<br/><p><i>Maecenas nec libero leo. Sed ac leo eget ipsum ultricies viverra sit amet eu orci. Praesent et tortor risus, viverra accumsan sapien. Sed faucibus eleifend lectus, sed euismod urna porta eu. Aenean ultricies lectus ut orci dictum quis convallis nisi ultrices. Nunc elit mi, iaculis a porttitor rutrum, venenatis malesuada nisi. Suspendisse turpis quam, euismod non imperdiet et, rutrum nec ligula. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper tristique metus eu sodales. Integer eget risus ipsum. Quisque ut risus ut nulla tristique volutpat at sit amet nisl. Aliquam pulvinar auctor diam nec bibendum.</i><br/><p>Quisque luctus sapien id arcu volutpat pharetra. Praesent pretium imperdiet euismod. Integer fringilla rhoncus condimentum. Quisque sit amet ornare nulla. Cras sapien augue, sagittis a dictum id, suscipit et nunc. Cras vitae augue in enim elementum venenatis sed nec risus. Sed nisi quam, mollis quis auctor ac, vestibulum in neque. Vivamus eu justo risus. Suspendisse vel mollis est. Vestibulum gravida interdum mi, in molestie neque gravida in. Donec nibh odio, mattis facilisis vulputate et, scelerisque ut felis. Sed ornare eros nec odio aliquam eu varius augue adipiscing. Vivamus sit amet massa dapibus sapien pulvinar consectetur a sit amet felis. Cras non mi id libero dictum iaculis id dignissim eros. Praesent eget enim dui, sed bibendum neque. Ut interdum nisl id leo malesuada ornare. Pellentesque id nisl eu odio volutpat posuere et at massa. Pellentesque nec lorem justo. Integer sem urna, pharetra sed sagittis vitae, condimentum ac felis. Ut vitae sapien ac tortor adipiscing pharetra. Cras tristique urna tempus ante volutpat eleifend non eu ligula. Mauris sodales nisl et lorem tristique sodales. Mauris arcu orci, vehicula semper cursus ac, dapibus ut mi."
- onLineLaidOut: {
+ onLineLaidOut: (line) => {
line.width = line.number * 15
if (line.number === 30 || line.number === 60) {
main.off = line.y
diff --git a/tests/auto/quick/qquicktext/data/lineLayoutFontUpdate.qml b/tests/auto/quick/qquicktext/data/lineLayoutFontUpdate.qml
new file mode 100644
index 0000000000..d018e31d29
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/lineLayoutFontUpdate.qml
@@ -0,0 +1,25 @@
+import QtQuick
+
+Item {
+ width: 640
+ height: 480
+
+ FontLoader {
+ id: fontIcons
+ source: "tarzeau_ocr_a.ttf"
+ }
+
+ Text {
+ id: exampleText
+ objectName: "exampleText"
+ text: "Example multiline text"
+ wrapMode: Text.WordWrap
+ width: 100
+ onLineLaidOut: (line) => {
+ if (line.number < 1) {
+ line.x += 40;
+ line.width -= 40;
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktext/data/lineLayoutImplicitWidth.qml b/tests/auto/quick/qquicktext/data/lineLayoutImplicitWidth.qml
index 0b04028417..94a6ac2797 100644
--- a/tests/auto/quick/qquicktext/data/lineLayoutImplicitWidth.qml
+++ b/tests/auto/quick/qquicktext/data/lineLayoutImplicitWidth.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 Jolla Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
@@ -23,7 +23,7 @@ Rectangle {
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis ante tristique, fermentum magna at, varius lacus. Donec elementum orci sit amet ligula efficitur, eget sodales orci porttitor. Etiam laoreet tellus quis nisi mollis lacinia. Cras vitae nisl sed nunc semper blandit. Duis egestas commodo lacus non congue. Fusce quis rhoncus urna. And magna arcu, sodales vitae nunc vel, rutrum hendrerit magna. Nullam imperdiet porttitor sem at euismod. Morbi faucibus libero sit amet vestibulum aliquam. Duis consectetur lacinia malesuada. Sed quis ante dui. Name dignissim faucibus felis. Quisque dapibus aliquam ante, eu cursus elit dictum in. Mauris placerat efficitur rutrum."
- onLineLaidOut: {
+ onLineLaidOut: (line) => {
var n = line.number
// Save information about the line so the autotest can retrieve it
diff --git a/tests/auto/quick/qquicktext/data/lineLayoutRelayout.qml b/tests/auto/quick/qquicktext/data/lineLayoutRelayout.qml
index 2e1aa6a17d..2f46159602 100644
--- a/tests/auto/quick/qquicktext/data/lineLayoutRelayout.qml
+++ b/tests/auto/quick/qquicktext/data/lineLayoutRelayout.qml
@@ -29,7 +29,7 @@ leo eget ipsum ultricies viverra sit amet eu orci. Praesent et tortor risus,
viverra accumsan sapien. Sed faucibus eleifend lectus, sed euismod urna porta
eu. Quisque vitae accumsan lectus."
- onLineLaidOut: {
+ onLineLaidOut: (line) => {
line.width = width / 2
if (line.y + line.height >= height) {
diff --git a/tests/auto/quick/qquicktext/data/loaderActiveOnVisible.qml b/tests/auto/quick/qquicktext/data/loaderActiveOnVisible.qml
new file mode 100644
index 0000000000..915dc21d84
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/loaderActiveOnVisible.qml
@@ -0,0 +1,24 @@
+import QtQuick
+
+Rectangle {
+ id: root
+ visible: false
+ width: 320
+ height: 240
+ Flickable {
+ id: flickable
+ anchors {
+ fill: root
+ margins: 10
+ }
+ contentHeight: loader.height
+
+ Loader {
+ id: loader
+ width: flickable.width
+ active: root.visible
+ source: "long.qml"
+ }
+ }
+ Component.onCompleted: visible = true
+}
diff --git a/tests/auto/quick/qquicktext/data/long.qml b/tests/auto/quick/qquicktext/data/long.qml
new file mode 100644
index 0000000000..ca27efb35a
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/long.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Text {
+ width: 300
+ wrapMode: Text.WordWrap
+ text: "GNU GENERAL PUBLIC LICENSE\r\nVersion 2, June 1991\r\nCopyright (C) 1989, 1991 Free Software Foundation, Inc.\r\n51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r\n\r\nEveryone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.\r\n\r\nPreamble\r\n\r\nThe licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.\r\n\r\nWhen we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.\r\n\r\nTo protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.\r\n\r\nFor example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.\r\n\r\nWe protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and\/or modify the software.\r\n\r\nAlso, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.\r\n\r\nFinally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.\r\n\r\nThe precise terms and conditions for copying, distribution and modification follow.\r\n\r\nTERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\r\n\r\n1. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The \"Program\", below, refers to any such program or work, and a \"work based on the Program\" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and\/or translated into another language. (Hereinafter, translation is included without limitation in the term \"modification\".) Each licensee is addressed as \"you\".\r\n\r\nActivities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.\r\n\r\n2. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.\r\n\r\nYou may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.\r\n\r\n3. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:\r\n\r\na) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.\r\n\r\nb) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.\r\n\r\nc) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)\r\n\r\nThese requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.\r\n\r\nThus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.\r\n\r\nIn addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.\r\n\r\n4. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:\r\n\r\na) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,\r\n\r\nb) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,\r\n\r\nc) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)\r\n\r\nThe source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.\r\n\r\nIf distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.\r\n\r\n5. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.\r\n\r\n6. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.\r\n\r\n7. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.\r\n\r\n8. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.\r\n\r\nIf any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.\r\n\r\nIt is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author\/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.\r\n\r\nThis section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.\r\n\r\n9. If the distribution and\/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.\r\n\r\n10. The Free Software Foundation may publish revised and\/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.\r\n\r\nEach version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and \"any later version\", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.\r\n\r\n11. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.\r\n\r\nNO WARRANTY\r\n\r\n12. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND\/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\r\n\r\n13. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND\/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\r\nEND OF TERMS AND CONDITIONS\r\n\r\n"
+}
diff --git a/tests/auto/quick/qquicktext/data/qtbug_106205.qml b/tests/auto/quick/qquicktext/data/qtbug_106205.qml
new file mode 100644
index 0000000000..e4db73557a
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/qtbug_106205.qml
@@ -0,0 +1,28 @@
+import QtQuick
+import QtQuick.Controls
+
+Item {
+ id: root
+ objectName: "root"
+ visible: true
+
+ anchors.fill: parent
+ property string text: ""
+
+ ScrollView {
+ anchors.fill: parent
+ Rectangle {
+ x: 100
+ width: 100
+ height: 30
+ color: "lightgray"
+
+ Text {
+ objectName: "textOutsideViewport"
+ text: root.text
+ width: 50
+ clip: true
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktext/data/tarzeau_ocr_a.ttf b/tests/auto/quick/qquicktext/data/tarzeau_ocr_a.ttf
new file mode 100644
index 0000000000..cf93f9651f
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/tarzeau_ocr_a.ttf
Binary files differ
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index c8d9561803..b731f1b069 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtTest/QSignalSpy>
#include <QTextDocument>
@@ -7,11 +7,12 @@
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qjsvalue.h>
#include <QtQuick/private/qquicktext_p.h>
+#include <QtQuick/private/qquickflickable_p.h>
#include <QtQuick/private/qquickmousearea_p.h>
+#include <QtQuick/private/qquickpixmapcache_p.h>
#include <QtQuickTest/QtQuickTest>
#include <private/qquicktext_p_p.h>
-#include <private/qquicktextnode_p.h>
-#include <private/qquicktextdocument_p.h>
+#include <private/qsginternaltextnode_p.h>
#include <private/qquickvaluetypes_p.h>
#include <QFontMetrics>
#include <qmath.h>
@@ -28,12 +29,17 @@ DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
Q_DECLARE_METATYPE(QQuickText::TextFormat)
-QT_BEGIN_NAMESPACE
-extern void qt_setQtEnableTestFont(bool value);
-QT_END_NAMESPACE
+typedef QVector<QPointF> PointVector;
+Q_DECLARE_METATYPE(PointVector);
+
+typedef qreal (*ExpectedBaseline)(QQuickText *item);
+Q_DECLARE_METATYPE(ExpectedBaseline)
Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
+QT_BEGIN_NAMESPACE
+extern void qt_setQtEnableTestFont(bool value);
+
class tst_qquicktext : public QQmlDataTest
{
Q_OBJECT
@@ -47,12 +53,14 @@ private slots:
void wrap();
void elide();
void elideParentChanged();
+ void elideRelayoutAfterZeroWidth_data();
void elideRelayoutAfterZeroWidth();
void multilineElide_data();
void multilineElide();
void implicitElide_data();
void implicitElide();
void textFormat();
+ void clipRectOutsideViewportDynamicallyChanged();
void baseUrl();
void embeddedImages_data();
@@ -100,8 +108,10 @@ private slots:
void clipRect();
void largeTextObservesViewport_data();
void largeTextObservesViewport();
+ void largeTextInDelayedLoader();
void lineLaidOut();
void lineLaidOutRelayout();
+ void lineLaidOutFontUpdate();
void lineLaidOutHAlign();
void lineLaidOutImplicitWidth();
@@ -248,13 +258,12 @@ void tst_qquicktext::text()
{
QQmlComponent textComponent(&engine);
textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->text(), QString(""));
QCOMPARE(textObject->width(), qreal(0));
-
- delete textObject;
}
for (int i = 0; i < standard.size(); i++)
@@ -262,14 +271,12 @@ void tst_qquicktext::text()
QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
-
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->text(), standard.at(i));
QVERIFY(textObject->width() > 0);
-
- delete textObject;
}
for (int i = 0; i < richText.size(); i++)
@@ -277,14 +284,13 @@ void tst_qquicktext::text()
QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QString expected = richText.at(i);
QCOMPARE(textObject->text(), expected.replace("\\\"", "\""));
QVERIFY(textObject->width() > 0);
-
- delete textObject;
}
}
@@ -294,12 +300,11 @@ void tst_qquicktext::width()
{
QQmlComponent textComponent(&engine);
textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->width(), 0.);
-
- delete textObject;
}
bool requiresUnhintedMetrics = !qmlDisableDistanceField();
@@ -341,14 +346,13 @@ void tst_qquicktext::width()
QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QVERIFY(textObject->boundingRect().width() > 0);
QCOMPARE(textObject->width(), qreal(metricWidth));
QVERIFY(textObject->textFormat() == QQuickText::AutoText); // setting text doesn't change format
-
- delete textObject;
}
for (int i = 0; i < richText.size(); i++)
@@ -358,7 +362,8 @@ void tst_qquicktext::width()
QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\"; textFormat: Text.RichText }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
@@ -370,8 +375,6 @@ void tst_qquicktext::width()
QCOMPARE(int(textObject->width()), int(doc->idealWidth()));
QCOMPARE(textObject->textFormat(), QQuickText::RichText);
-
- delete textObject;
}
}
@@ -382,14 +385,13 @@ void tst_qquicktext::wrap()
{
QQmlComponent textComponent(&engine);
textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; wrapMode: Text.WordWrap; width: 300 }", QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
textHeight = textObject->height();
- QVERIFY(textObject != nullptr);
QCOMPARE(textObject->wrapMode(), QQuickText::WordWrap);
QCOMPARE(textObject->width(), 300.);
-
- delete textObject;
}
for (int i = 0; i < standard.size(); i++)
@@ -397,7 +399,8 @@ void tst_qquicktext::wrap()
QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + standard.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->width(), 30.);
@@ -406,8 +409,6 @@ void tst_qquicktext::wrap()
int oldHeight = textObject->height();
textObject->setWidth(100);
QVERIFY(textObject->height() < oldHeight);
-
- delete textObject;
}
for (int i = 0; i < richText.size(); i++)
@@ -415,7 +416,8 @@ void tst_qquicktext::wrap()
QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + richText.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->width(), 30.);
@@ -424,8 +426,6 @@ void tst_qquicktext::wrap()
qreal oldHeight = textObject->height();
textObject->setWidth(100);
QVERIFY(textObject->height() < oldHeight);
-
- delete textObject;
}
// Check that increasing width from idealWidth will cause a relayout
@@ -434,7 +434,8 @@ void tst_qquicktext::wrap()
QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; textFormat: Text.RichText; width: 30; text: \"" + richText.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->width(), 30.);
@@ -453,8 +454,6 @@ void tst_qquicktext::wrap()
qreal oldHeight = textObject->height();
textObject->setWidth(100);
QVERIFY(textObject->height() < oldHeight);
-
- delete textObject;
}
// richtext again with a fixed height
@@ -463,7 +462,8 @@ void tst_qquicktext::wrap()
QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; height: 50; text: \"" + richText.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->width(), 30.);
@@ -472,8 +472,6 @@ void tst_qquicktext::wrap()
qreal oldHeight = textObject->implicitHeight();
textObject->setWidth(100);
QVERIFY(textObject->implicitHeight() < oldHeight);
-
- delete textObject;
}
{
@@ -511,12 +509,12 @@ void tst_qquicktext::elide()
{
QQmlComponent textComponent(&engine);
textComponent.setData(("import QtQuick 2.0\nText { text: \"\"; "+elide+" width: 100 }").toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->elideMode(), m);
QCOMPARE(textObject->width(), 100.);
-
- delete textObject;
}
for (int i = 0; i < standard.size(); i++)
@@ -524,15 +522,15 @@ void tst_qquicktext::elide()
QString componentStr = "import QtQuick 2.0\nText { "+elide+" width: 100; text: \"" + standard.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->elideMode(), m);
QCOMPARE(textObject->width(), 100.);
if (m != QQuickText::ElideNone && !standard.at(i).contains('\n'))
QVERIFY(textObject->contentWidth() <= textObject->width());
-
- delete textObject;
}
for (int i = 0; i < richText.size(); i++)
@@ -540,15 +538,15 @@ void tst_qquicktext::elide()
QString componentStr = "import QtQuick 2.0\nText { "+elide+" width: 100; text: \"" + richText.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->elideMode(), m);
QCOMPARE(textObject->width(), 100.);
if (m != QQuickText::ElideNone && standard.at(i).contains("<br>"))
QVERIFY(textObject->contentWidth() <= textObject->width());
-
- delete textObject;
}
}
}
@@ -592,10 +590,19 @@ void tst_qquicktext::elideParentChanged()
QCOMPARE(actualItemImageGrab, expectedItemImageGrab);
}
+void tst_qquicktext::elideRelayoutAfterZeroWidth_data()
+{
+ QTest::addColumn<QByteArray>("fileName");
+
+ QTest::newRow("no_margins") << QByteArray("elideZeroWidth.qml");
+ QTest::newRow("with_margins") << QByteArray("elideZeroWidthWithMargins.qml");
+}
+
void tst_qquicktext::elideRelayoutAfterZeroWidth()
{
+ QFETCH(const QByteArray, fileName);
QQmlEngine engine;
- QQmlComponent component(&engine, testFileUrl("elideZeroWidth.qml"));
+ QQmlComponent component(&engine, testFileUrl(fileName.constData()));
QScopedPointer<QObject> root(component.create());
QVERIFY2(root, qPrintable(component.errorString()));
QVERIFY(root->property("ok").toBool());
@@ -699,6 +706,7 @@ void tst_qquicktext::implicitElide()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QVERIFY2(textObject, qPrintable(textComponent.errorString()));
QVERIFY(textObject->contentWidth() <= textObject->width());
textObject->setText("the quick brown fox jumped over");
@@ -712,7 +720,8 @@ void tst_qquicktext::textFormat()
{
QQmlComponent textComponent(&engine);
textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->textFormat(), QQuickText::RichText);
@@ -720,13 +729,12 @@ void tst_qquicktext::textFormat()
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
QVERIFY(textPrivate != nullptr);
QVERIFY(textPrivate->richText);
-
- delete textObject;
}
{
QQmlComponent textComponent(&engine);
textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\" }", QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->textFormat(), QQuickText::AutoText);
@@ -734,18 +742,15 @@ void tst_qquicktext::textFormat()
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
QVERIFY(textPrivate != nullptr);
QVERIFY(textPrivate->styledText);
-
- delete textObject;
}
{
QQmlComponent textComponent(&engine);
textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->textFormat(), QQuickText::PlainText);
-
- delete textObject;
}
{
@@ -827,6 +832,28 @@ void tst_qquicktext::textFormat()
}
}
+void tst_qquicktext::clipRectOutsideViewportDynamicallyChanged()
+{
+ // QTBUG-106205
+ QScopedPointer<QQuickView> view(createView(testFile("qtbug_106205.qml")));
+ view->setWidth(100);
+ view->setHeight(200);
+ view->showNormal();
+ QQuickItem *root = view->rootObject();
+ QVERIFY(root);
+ QVERIFY(QTest::qWaitForWindowExposed(view.get()));
+
+ auto clipRectMatches = [&]() -> bool {
+ auto *textOutsideInitialViewport = root->findChild<QQuickText *>("textOutsideViewport");
+ if (!textOutsideInitialViewport)
+ return false;
+ auto *clipNode = QQuickItemPrivate::get(textOutsideInitialViewport)->clipNode();
+
+ return textOutsideInitialViewport->clipRect() == clipNode->clipRect();
+ };
+ QTRY_VERIFY(clipRectMatches());
+}
+
//the alignment tests may be trivial o.oa
void tst_qquicktext::horizontalAlignment()
{
@@ -839,11 +866,11 @@ void tst_qquicktext::horizontalAlignment()
QString componentStr = "import QtQuick 2.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject, qPrintable(textComponent.errorString()));
QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
-
- delete textObject;
}
}
@@ -854,11 +881,11 @@ void tst_qquicktext::horizontalAlignment()
QString componentStr = "import QtQuick 2.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject, qPrintable(textComponent.errorString()));
QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
-
- delete textObject;
}
}
@@ -975,10 +1002,11 @@ void tst_qquicktext::horizontalAlignment_RightToLeft()
QString componentStr = "import QtQuick 2.0\nText {}";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->hAlign(), qApp->inputMethod()->inputDirection() == Qt::LeftToRight ?
QQuickText::AlignLeft : QQuickText::AlignRight);
- delete textObject;
}
int tst_qquicktext::numberOfNonWhitePixels(int fromX, int toX, const QImage &image)
@@ -1076,12 +1104,11 @@ void tst_qquicktext::verticalAlignment()
QString componentStr = "import QtQuick 2.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
-
- delete textObject;
}
}
@@ -1092,12 +1119,11 @@ void tst_qquicktext::verticalAlignment()
QString componentStr = "import QtQuick 2.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
-
- delete textObject;
}
}
@@ -1110,74 +1136,74 @@ void tst_qquicktext::font()
QString componentStr = "import QtQuick 2.0\nText { font.pointSize: 40; text: \"Hello World\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->font().pointSize(), 40);
QCOMPARE(textObject->font().bold(), false);
QCOMPARE(textObject->font().italic(), false);
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { font.pixelSize: 40; text: \"Hello World\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->font().pixelSize(), 40);
QCOMPARE(textObject->font().bold(), false);
QCOMPARE(textObject->font().italic(), false);
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { font.bold: true; text: \"Hello World\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->font().bold(), true);
QCOMPARE(textObject->font().italic(), false);
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { font.italic: true; text: \"Hello World\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->font().italic(), true);
QCOMPARE(textObject->font().bold(), false);
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { font.family: \"Helvetica\"; text: \"Hello World\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->font().family(), QString("Helvetica"));
QCOMPARE(textObject->font().bold(), false);
QCOMPARE(textObject->font().italic(), false);
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { font.family: \"\"; text: \"Hello World\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->font().family(), QString(""));
-
- delete textObject;
}
}
@@ -1189,17 +1215,19 @@ void tst_qquicktext::style()
QString componentStr = "import QtQuick 2.0\nText { style: \"" + styleStrings.at(i) + "\"; styleColor: \"white\"; text: \"Hello World\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE((int)textObject->style(), (int)styles.at(i));
QCOMPARE(textObject->styleColor(), QColor("white"));
-
- delete textObject;
}
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello World\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QRectF brPre = textObject->boundingRect();
textObject->setStyle(QQuickText::Outline);
@@ -1207,8 +1235,6 @@ void tst_qquicktext::style()
QVERIFY(brPre.width() < brPost.width());
QVERIFY(brPre.height() < brPost.height());
-
- delete textObject;
}
void tst_qquicktext::color()
@@ -1219,13 +1245,13 @@ void tst_qquicktext::color()
QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
QCOMPARE(textObject->styleColor(), QColor("black"));
QCOMPARE(textObject->linkColor(), QColor("blue"));
-
- delete textObject;
}
for (int i = 0; i < colorStrings.size(); i++)
@@ -1233,7 +1259,9 @@ void tst_qquicktext::color()
QString componentStr = "import QtQuick 2.0\nText { styleColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(i)));
// default color to black?
@@ -1264,8 +1292,6 @@ void tst_qquicktext::color()
textObject->setLinkColor(QColor("blue"));
QCOMPARE(textObject->linkColor(), QColor("blue"));
QCOMPARE(linkColorSpy.size(), 2);
-
- delete textObject;
}
for (int i = 0; i < colorStrings.size(); i++)
@@ -1273,13 +1299,13 @@ void tst_qquicktext::color()
QString componentStr = "import QtQuick 2.0\nText { linkColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->styleColor(), QColor("black"));
QCOMPARE(textObject->color(), QColor("black"));
QCOMPARE(textObject->linkColor(), QColor(colorStrings.at(i)));
-
- delete textObject;
}
for (int i = 0; i < colorStrings.size(); i++)
@@ -1293,13 +1319,13 @@ void tst_qquicktext::color()
"text: \"Hello World\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(j)));
QCOMPARE(textObject->linkColor(), QColor(colorStrings.at(j)));
-
- delete textObject;
}
}
{
@@ -1310,11 +1336,11 @@ void tst_qquicktext::color()
QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStr + "\"; text: \"Hello World\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->color(), testColor);
-
- delete textObject;
} {
QString colorStr = "#001234";
QColor testColor(colorStr);
@@ -1324,6 +1350,7 @@ void tst_qquicktext::color()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QScopedPointer<QObject> object(textComponent.create());
QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QSignalSpy spy(textObject, SIGNAL(colorChanged()));
@@ -1345,6 +1372,7 @@ void tst_qquicktext::color()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QScopedPointer<QObject> object(textComponent.create());
QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QSignalSpy spy(textObject, SIGNAL(styleColorChanged()));
@@ -1366,6 +1394,7 @@ void tst_qquicktext::color()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QScopedPointer<QObject> object(textComponent.create());
QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QSignalSpy spy(textObject, SIGNAL(linkColorChanged()));
@@ -1389,19 +1418,19 @@ void tst_qquicktext::smooth()
QString componentStr = "import QtQuick 2.0\nText { smooth: false; text: \"" + standard.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->smooth(), false);
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->smooth(), true);
-
- delete textObject;
}
}
for (int i = 0; i < richText.size(); i++)
@@ -1410,19 +1439,19 @@ void tst_qquicktext::smooth()
QString componentStr = "import QtQuick 2.0\nText { smooth: false; text: \"" + richText.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->smooth(), false);
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject != nullptr, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->smooth(), true);
-
- delete textObject;
}
}
}
@@ -1488,23 +1517,21 @@ void tst_qquicktext::weight()
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().weight(), int(QQuickFontEnums::Normal));
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { font.weight: Font.Bold; text: \"Hello world!\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().weight(), int(QQuickFontEnums::Bold));
-
- delete textObject;
}
}
@@ -1553,56 +1580,51 @@ void tst_qquicktext::capitalization()
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().capitalization(), int(QQuickFontEnums::MixedCase));
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"AllUppercase\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().capitalization(), int(QQuickFontEnums::AllUppercase));
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"AllLowercase\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().capitalization(), int(QQuickFontEnums::AllLowercase));
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"SmallCaps\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().capitalization(), int(QQuickFontEnums::SmallCaps));
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"Capitalize\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().capitalization(), int(QQuickFontEnums::Capitalize));
-
- delete textObject;
}
}
@@ -1612,34 +1634,31 @@ void tst_qquicktext::letterSpacing()
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().letterSpacing(), 0.0);
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.letterSpacing: -2 }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().letterSpacing(), -2.);
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.letterSpacing: 3 }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().letterSpacing(), 3.);
-
- delete textObject;
}
}
@@ -1649,34 +1668,31 @@ void tst_qquicktext::wordSpacing()
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().wordSpacing(), 0.0);
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.wordSpacing: -50 }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().wordSpacing(), -50.);
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.wordSpacing: 200 }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().wordSpacing(), 200.);
-
- delete textObject;
}
}
@@ -1803,10 +1819,6 @@ public:
QTextLayout layout;
};
-
-typedef QVector<QPointF> PointVector;
-Q_DECLARE_METATYPE(PointVector);
-
void tst_qquicktext::linkInteraction_data()
{
QTest::addColumn<QString>("text");
@@ -2068,7 +2080,8 @@ void tst_qquicktext::linkInteraction()
"}";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
@@ -2119,8 +2132,6 @@ void tst_qquicktext::linkInteraction()
QCOMPARE(test.hoveredLink, QString());
QCOMPARE(textObject->hoveredLink(), QString());
QCOMPARE(textObject->linkAt(-1, -1), QString());
-
- delete textObject;
}
void tst_qquicktext::baseUrl()
@@ -2131,6 +2142,7 @@ void tst_qquicktext::baseUrl()
QQmlComponent textComponent(&engine);
textComponent.setData("import QtQuick 2.0\n Text {}", localUrl);
QQuickText *textObject = qobject_cast<QQuickText *>(textComponent.create());
+ QVERIFY2(textObject, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->baseUrl(), localUrl);
@@ -2151,12 +2163,15 @@ void tst_qquicktext::baseUrl()
void tst_qquicktext::embeddedImages_data()
{
+ // Cancel some mess left by clipRectOutsideViewportDynamicallyChanged():
+ qmlClearTypeRegistrations();
+
QTest::addColumn<QUrl>("qmlfile");
QTest::addColumn<QString>("error");
QTest::newRow("local") << testFileUrl("embeddedImagesLocal.qml") << "";
QTest::newRow("local-error") << testFileUrl("embeddedImagesLocalError.qml")
<< testFileUrl("embeddedImagesLocalError.qml").toString()+":3:1: QML Text: Cannot open: " + testFileUrl("http/notexists.png").toString();
- QTest::newRow("local") << testFileUrl("embeddedImagesLocalRelative.qml") << "";
+ QTest::newRow("local-relative") << testFileUrl("embeddedImagesLocalRelative.qml") << "";
QTest::newRow("remote") << testFileUrl("embeddedImagesRemote.qml") << "";
QTest::newRow("remote-error") << testFileUrl("embeddedImagesRemoteError.qml")
<< testFileUrl("embeddedImagesRemoteError.qml").toString()+":3:1: QML Text: Error transferring {{ServerBaseUrl}}/notexists.png - server replied: Not found";
@@ -2178,13 +2193,10 @@ void tst_qquicktext::embeddedImages()
if (!error.isEmpty())
QTest::ignoreMessage(QtWarningMsg, error.toLatin1());
- QQuickView *view = new QQuickView;
- view->rootContext()->setContextProperty(QStringLiteral("serverBaseUrl"), server.baseUrl());
- view->setSource(qmlfile);
- view->show();
- view->requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(view));
- QQuickText *textObject = qobject_cast<QQuickText*>(view->rootObject());
+ QQuickView view;
+ view.rootContext()->setContextProperty(QStringLiteral("serverBaseUrl"), server.baseUrl());
+ QVERIFY(QQuickTest::showView(view, qmlfile));
+ QQuickText *textObject = qobject_cast<QQuickText*>(view.rootObject());
QVERIFY(textObject != nullptr);
QTRY_COMPARE(textObject->resourcesLoading(), 0);
@@ -2199,7 +2211,9 @@ void tst_qquicktext::embeddedImages()
QCOMPARE(textObject->height(), 16.0);
}
- delete view;
+ // QTextDocument images are cached in QTextDocumentPrivate::cachedResources,
+ // so verify that we don't redundantly cache them in QQuickPixmapCache
+ QCOMPARE(QQuickPixmapCache::instance()->m_cache.size(), 0);
}
void tst_qquicktext::lineCount()
@@ -2357,7 +2371,9 @@ void tst_qquicktext::implicitSize()
"maximumLineCount: 2 }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
+ QVERIFY2(textObject, qPrintable(textComponent.errorString()));
QVERIFY(textObject->width() < textObject->implicitWidth());
QCOMPARE(textObject->height(), textObject->implicitHeight());
@@ -2366,8 +2382,6 @@ void tst_qquicktext::implicitSize()
textObject->resetWidth();
QCOMPARE(textObject->width(), textObject->implicitWidth());
QCOMPARE(textObject->height(), textObject->implicitHeight());
-
- delete textObject;
}
void tst_qquicktext::implicitSizeMaxLineCount()
@@ -2447,6 +2461,7 @@ void tst_qquicktext::contentSize()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QScopedPointer<QObject> object(textComponent.create());
QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
+ QVERIFY2(textObject, qPrintable(textComponent.errorString()));
QSignalSpy spySize(textObject, SIGNAL(contentSizeChanged()));
QSignalSpy spyWidth(textObject, SIGNAL(contentWidthChanged(qreal)));
@@ -2504,6 +2519,7 @@ void tst_qquicktext::geometryChanged()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QScopedPointer<QObject> object(textComponent.create());
QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
+ QVERIFY2(textObject, qPrintable(textComponent.errorString()));
const qreal implicitHeight = textObject->implicitHeight();
@@ -2763,6 +2779,7 @@ void tst_qquicktext::implicitSizeBinding()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QScopedPointer<QObject> object(textComponent.create());
QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
+ QVERIFY2(textObject, qPrintable(textComponent.errorString()));
QCOMPARE(textObject->width(), textObject->implicitWidth());
QCOMPARE(textObject->height(), textObject->implicitHeight());
@@ -2951,10 +2968,10 @@ void tst_qquicktext::largeTextObservesViewport_data()
Q_ASSERT(text.size() > QQuickTextPrivate::largeTextSizeThreshold);
// by default, the root item acts as the viewport:
- // QQuickTextNode doesn't populate lines of text beyond the bottom of the window
+ // QSGInternalTextNode doesn't populate lines of text beyond the bottom of the window
QTest::newRow("default plain text") << text << QQuickText::PlainText << 0 << false;
// make the rectangle into a viewport item, and move the text upwards:
- // QQuickTextNode doesn't populate lines of text beyond the bottom of the viewport rectangle
+ // QSGInternalTextNode doesn't populate lines of text beyond the bottom of the viewport rectangle
QTest::newRow("clipped plain text") << text << QQuickText::PlainText << 10 << true;
{
@@ -2998,13 +3015,13 @@ void tst_qquicktext::largeTextObservesViewport()
QVERIFY(textItem);
QQuickItem *viewportItem = textItem->parentItem();
QQuickTextPrivate *textPriv = QQuickTextPrivate::get(textItem);
- QQuickTextNode *node = static_cast<QQuickTextNode *>(textPriv->paintNode);
+ QSGInternalTextNode *node = static_cast<QSGInternalTextNode *>(textPriv->paintNode);
QFontMetricsF fm(textItem->font());
const qreal expectedTextHeight = (parentIsViewport ? viewportItem->height() : window.height() - viewportItem->y());
const qreal lineSpacing = qCeil(fm.height());
// A paragraph break is the same as an extra line break; so since our "lines" are paragraphs in StyledText,
// visually, with StyledText we skip down 10 "lines", but the first paragraph you see says "line 5".
- // It's OK anyway for the test, because QQuickTextNode::addTextLayout() treats the paragraph breaks like lines of text.
+ // It's OK anyway for the test, because QSGTextNode::addTextLayout() treats the paragraph breaks like lines of text.
const int expectedLastLine = linesAboveViewport + int(expectedTextHeight / lineSpacing);
viewportItem->setFlag(QQuickItem::ItemIsViewport, parentIsViewport);
@@ -3029,6 +3046,29 @@ void tst_qquicktext::largeTextObservesViewport()
QVERIFY(qAbs(renderedLineRange.second - (expectedLastLine + 1)) < (linesAboveViewport > 80 ? 4 : 2));
}
+void tst_qquicktext::largeTextInDelayedLoader() // QTBUG-115687
+{
+ QQuickView view;
+ QVERIFY(QQuickTest::showView(view, testFileUrl("loaderActiveOnVisible.qml")));
+ auto flick = view.rootObject()->findChild<QQuickFlickable*>();
+ QVERIFY(flick);
+ auto textItem = view.rootObject()->findChild<QQuickText*>();
+ QVERIFY(textItem);
+ QQuickTextPrivate *textPriv = QQuickTextPrivate::get(textItem);
+ QSGInternalTextNode *node = static_cast<QSGInternalTextNode *>(textPriv->paintNode);
+ const auto initialLineRange = node->renderedLineRange();
+ qCDebug(lcTests) << "first line rendered" << initialLineRange.first
+ << "; first line past viewport" << initialLineRange.second;
+ flick->setContentY(500);
+ QTRY_COMPARE_NE(node->renderedLineRange(), initialLineRange);
+ const auto scrolledLineRange = node->renderedLineRange();
+ qCDebug(lcTests) << "after scroll: first line rendered" << scrolledLineRange.first
+ << "; first line past viewport" << scrolledLineRange.second;
+ // We scrolled a good bit more than one window-height, so we must render a
+ // non-overlapping range of text some distance past the initial blocks.
+ QCOMPARE_GT(scrolledLineRange.first, initialLineRange.second);
+}
+
void tst_qquicktext::lineLaidOut()
{
QScopedPointer<QQuickView> window(createView(testFile("lineLayout.qml")));
@@ -3043,11 +3083,11 @@ void tst_qquicktext::lineLaidOut()
for (int i = 0; i < textPrivate->layout.lineCount(); ++i) {
QRectF r = textPrivate->layout.lineAt(i).rect();
- QVERIFY(r.width() == i * 15);
+ QCOMPARE(r.width(), i * 15);
if (i >= 30)
- QVERIFY(r.x() == r.width() + 30);
+ QCOMPARE(r.x(), r.width() + 30);
if (i >= 60) {
- QVERIFY(r.x() == r.width() * 2 + 60);
+ QCOMPARE(r.x(), r.width() * 2 + 60);
QCOMPARE(r.height(), qreal(20));
}
}
@@ -3092,6 +3132,29 @@ void tst_qquicktext::lineLaidOutRelayout()
}
}
+void tst_qquicktext::lineLaidOutFontUpdate()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("lineLayoutFontUpdate.qml")));
+
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+
+ auto *myText = window->rootObject()->findChild<QQuickText*>("exampleText");
+ QVERIFY(myText != nullptr);
+
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
+ QVERIFY(textPrivate != nullptr);
+
+ QCOMPARE(textPrivate->layout.lineCount(), 2);
+
+ QTextLine firstLine = textPrivate->layout.lineAt(0);
+ QTextLine secondLine = textPrivate->layout.lineAt(1);
+
+ QCOMPARE(firstLine.rect().x(), secondLine.rect().x() + 40);
+ QCOMPARE(firstLine.rect().width(), secondLine.rect().width() - 40);
+}
+
void tst_qquicktext::lineLaidOutHAlign()
{
QScopedPointer<QQuickView> window(createView(testFile("lineLayoutHAlign.qml")));
@@ -3272,7 +3335,8 @@ void tst_qquicktext::imgTagsAlign()
QString componentStr = "import QtQuick 2.0\nText { text: \"This is a test <img src=\\\"" + src + "\\\" align=\\\"" + align + "\\\"> of image.\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), testFileUrl("."));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->height(), qreal(imgHeight));
@@ -3287,8 +3351,6 @@ void tst_qquicktext::imgTagsAlign()
QVERIFY(br.y() == imgHeight / 2.0 - br.height() / 2.0);
else if (align == "top")
QCOMPARE(br.y(), qreal(0));
-
- delete textObject;
}
void tst_qquicktext::imgTagsMultipleImages()
@@ -3297,7 +3359,8 @@ void tst_qquicktext::imgTagsMultipleImages()
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), testFileUrl("."));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE(textObject->height(), qreal(85));
@@ -3305,34 +3368,30 @@ void tst_qquicktext::imgTagsMultipleImages()
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
QVERIFY(textPrivate != nullptr);
QCOMPARE(textPrivate->extra->visibleImgTags.size(), 2);
-
- delete textObject;
}
void tst_qquicktext::imgTagsElide()
{
QScopedPointer<QQuickView> window(createView(testFile("imgTagsElide.qml")));
- QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != nullptr);
+ QScopedPointer<QQuickText> myText(window->rootObject()->findChild<QQuickText*>("myText"));
+ QVERIFY(myText);
- QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText.data());
QVERIFY(textPrivate != nullptr);
QCOMPARE(textPrivate->extra->visibleImgTags.size(), 0);
myText->setMaximumLineCount(20);
QTRY_COMPARE(textPrivate->extra->visibleImgTags.size(), 1);
-
- delete myText;
}
void tst_qquicktext::imgTagsUpdates()
{
QScopedPointer<QQuickView> window(createView(testFile("imgTagsUpdates.qml")));
- QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != nullptr);
+ QScopedPointer<QQuickText> myText(window->rootObject()->findChild<QQuickText*>("myText"));
+ QVERIFY(myText);
- QSignalSpy spy(myText, SIGNAL(contentSizeChanged()));
+ QSignalSpy spy(myText.data(), SIGNAL(contentSizeChanged()));
- QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText.data());
QVERIFY(textPrivate != nullptr);
myText->setText("This is a heart<img src=\"images/heart200.png\">.");
@@ -3346,8 +3405,6 @@ void tst_qquicktext::imgTagsUpdates()
// if maximumLineCount is set and the img tag doesn't have an explicit size
// we relayout twice.
QCOMPARE(spy.size(), 3);
-
- delete myText;
}
void tst_qquicktext::imgTagsError()
@@ -3361,10 +3418,10 @@ void tst_qquicktext::imgTagsError()
+ testFileUrl("images/starfish_2.pn").toString());
QTest::ignoreMessage(QtWarningMsg, expectedMessage.toLatin1());
textComponent.setData(componentStr.toLatin1(), testFileUrl("."));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
- delete textObject;
}
void tst_qquicktext::fontSizeMode_data()
@@ -4027,9 +4084,6 @@ void tst_qquicktext::fontFormatSizes()
}
}
-typedef qreal (*ExpectedBaseline)(QQuickText *item);
-Q_DECLARE_METATYPE(ExpectedBaseline)
-
static qreal expectedBaselineTop(QQuickText *item)
{
QFontMetricsF fm(item->font());
@@ -4194,7 +4248,7 @@ void tst_qquicktext::baselineOffset_data()
QTest::newRow("customLine")
<< "hello world"
<< "hello\nworld"
- << QByteArray("height: 200; onLineLaidOut: line.y += 16")
+ << QByteArray("height: 200; onLineLaidOut: (line) => { line.y += 16; }")
<< &expectedBaselineCustom
<< &expectedBaselineCustom;
@@ -4290,7 +4344,8 @@ void tst_qquicktext::baselineOffset_data()
QTest::newRow("customLine with padding")
<< "hello world"
<< "hello\nworld"
- << QByteArray("height: 200; topPadding: 10; bottomPadding: 20; onLineLaidOut: line.y += 16")
+ << QByteArray("height: 200; topPadding: 10; bottomPadding: 20; "
+ "onLineLaidOut: (line) => { line.y += 16; }")
<< &expectedBaselineCustom
<< &expectedBaselineCustom;
@@ -4388,7 +4443,7 @@ void tst_qquicktext::htmlLists()
QFETCH(QString, text);
QFETCH(int, nbLines);
- QQuickView *view = createView(testFile("htmlLists.qml"));
+ QScopedPointer<QQuickView>view(createView(testFile("htmlLists.qml")));
QQuickText *textObject = view->rootObject()->findChild<QQuickText*>("myText");
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
@@ -4400,11 +4455,9 @@ void tst_qquicktext::htmlLists()
view->show();
view->requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(view));
+ QVERIFY(QTest::qWaitForWindowActive(view.get()));
QCOMPARE(textPrivate->extra->doc->lineCount(), nbLines);
-
- delete view;
}
void tst_qquicktext::htmlLists_data()
@@ -4489,9 +4542,9 @@ void tst_qquicktext::padding()
QTRY_COMPARE(window->status(), QQuickView::Ready);
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
- QQuickItem *root = window->rootObject();
+ QScopedPointer<QQuickItem> root(window->rootObject());
QVERIFY(root);
- QQuickText *obj = qobject_cast<QQuickText*>(root);
+ QQuickText *obj = qobject_cast<QQuickText*>(root.data());
QVERIFY(obj != nullptr);
qreal cw = obj->contentWidth();
@@ -4582,8 +4635,6 @@ void tst_qquicktext::padding()
QCOMPARE(obj->leftPadding(), 0.0);
QCOMPARE(obj->rightPadding(), 0.0);
QCOMPARE(obj->bottomPadding(), 0.0);
-
- delete root;
}
void tst_qquicktext::paddingInLoader() // QTBUG-83413
@@ -4618,23 +4669,21 @@ void tst_qquicktext::hintingPreference()
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().hintingPreference(), (int)QFont::PreferDefaultHinting);
-
- delete textObject;
}
{
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.hintingPreference: Font.PreferNoHinting }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().hintingPreference(), (int)QFont::PreferNoHinting);
-
- delete textObject;
}
}
@@ -4710,6 +4759,7 @@ void tst_qquicktext::fontInfo()
QScopedPointer<QObject> object(component.create());
QObject *root = object.data();
+ QVERIFY2(root, qPrintable(component.errorString()));
QQuickText *main = root->findChild<QQuickText *>("main");
QVERIFY(main);
@@ -4806,6 +4856,8 @@ void tst_qquicktext::displaySuperscriptedTag()
QCOMPARE(color.green(), 255);
}
+QT_END_NAMESPACE
+
QTEST_MAIN(tst_qquicktext)
#include "tst_qquicktext.moc"
diff --git a/tests/auto/quick/qquicktextdocument/CMakeLists.txt b/tests/auto/quick/qquicktextdocument/CMakeLists.txt
index e106efd6c2..5bcad96b0a 100644
--- a/tests/auto/quick/qquicktextdocument/CMakeLists.txt
+++ b/tests/auto/quick/qquicktextdocument/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicktextdocument Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicktextdocument LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquicktextdocument/data/hello-8857-7.html b/tests/auto/quick/qquicktextdocument/data/hello-8857-7.html
new file mode 100644
index 0000000000..6bf900858a
--- /dev/null
+++ b/tests/auto/quick/qquicktextdocument/data/hello-8857-7.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="iso-8859-7">
+</head>
+<body>
+<p>ÃåéÜ óïõ Êüóìå!</p>
+</body>
+</html>
diff --git a/tests/auto/quick/qquicktextdocument/data/hello-utf16be.html b/tests/auto/quick/qquicktextdocument/data/hello-utf16be.html
new file mode 100644
index 0000000000..be84e0d63c
--- /dev/null
+++ b/tests/auto/quick/qquicktextdocument/data/hello-utf16be.html
Binary files differ
diff --git a/tests/auto/quick/qquicktextdocument/data/hello.html b/tests/auto/quick/qquicktextdocument/data/hello.html
new file mode 100644
index 0000000000..c160cd5e63
--- /dev/null
+++ b/tests/auto/quick/qquicktextdocument/data/hello.html
@@ -0,0 +1 @@
+Γειά σου <i>Κόσμε</i>!
diff --git a/tests/auto/quick/qquicktextdocument/data/hello.md b/tests/auto/quick/qquicktextdocument/data/hello.md
new file mode 100644
index 0000000000..290f3f1397
--- /dev/null
+++ b/tests/auto/quick/qquicktextdocument/data/hello.md
@@ -0,0 +1 @@
+Γειά σου *Κόσμε*!
diff --git a/tests/auto/quick/qquicktextdocument/data/hello.txt b/tests/auto/quick/qquicktextdocument/data/hello.txt
new file mode 100644
index 0000000000..1f72c3f7a4
--- /dev/null
+++ b/tests/auto/quick/qquicktextdocument/data/hello.txt
@@ -0,0 +1 @@
+Γειά σου Κόσμε!
diff --git a/tests/auto/quick/qquicktextdocument/data/initialText.qml b/tests/auto/quick/qquicktextdocument/data/initialText.qml
new file mode 100644
index 0000000000..be9280f952
--- /dev/null
+++ b/tests/auto/quick/qquicktextdocument/data/initialText.qml
@@ -0,0 +1,16 @@
+import QtQuick
+
+TextEdit {
+ id: te
+ property int sourceChangeCount: 0
+ property int modifiedChangeCount: 0
+ property var statusHistory: []
+
+ width: 320; height: 240
+ text: "Hello Qt"
+ focus: true
+
+ textDocument.onSourceChanged: ++te.sourceChangeCount
+ textDocument.onModifiedChanged: ++te.modifiedChangeCount
+ textDocument.onStatusChanged: te.statusHistory.push(textDocument.status)
+}
diff --git a/tests/auto/quick/qquicktextdocument/data/sideBySideIndependent.qml b/tests/auto/quick/qquicktextdocument/data/sideBySideIndependent.qml
new file mode 100644
index 0000000000..8275e7f5bd
--- /dev/null
+++ b/tests/auto/quick/qquicktextdocument/data/sideBySideIndependent.qml
@@ -0,0 +1,21 @@
+import QtQuick
+
+Row {
+ width: 480; height: 200
+ TextEdit {
+ objectName: "plain"
+ width: parent.width / 2 - 1
+ textFormat: TextEdit.PlainText
+ textDocument.source: "hello.md"
+ }
+ Rectangle {
+ width: 2; height: parent.height
+ color: "lightsteelblue"
+ }
+ TextEdit {
+ objectName: "markdown"
+ width: parent.width / 2 - 1
+ textFormat: TextEdit.MarkdownText
+ textDocument.source: "hello.md"
+ }
+}
diff --git a/tests/auto/quick/qquicktextdocument/data/sideBySideIndependentReverse.qml b/tests/auto/quick/qquicktextdocument/data/sideBySideIndependentReverse.qml
new file mode 100644
index 0000000000..cbd92accec
--- /dev/null
+++ b/tests/auto/quick/qquicktextdocument/data/sideBySideIndependentReverse.qml
@@ -0,0 +1,21 @@
+import QtQuick
+
+Row {
+ width: 480; height: 200
+ TextEdit {
+ objectName: "plain"
+ width: parent.width / 2 - 1
+ textDocument.source: "hello.md"
+ textFormat: TextEdit.PlainText
+ }
+ Rectangle {
+ width: 2; height: parent.height
+ color: "lightsteelblue"
+ }
+ TextEdit {
+ objectName: "markdown"
+ width: parent.width / 2 - 1
+ textDocument.source: "hello.md"
+ textFormat: TextEdit.MarkdownText
+ }
+}
diff --git a/tests/auto/quick/qquicktextdocument/data/text.qml b/tests/auto/quick/qquicktextdocument/data/text.qml
index 43a8c6bb82..d1b9ee7203 100644
--- a/tests/auto/quick/qquicktextdocument/data/text.qml
+++ b/tests/auto/quick/qquicktextdocument/data/text.qml
@@ -1,6 +1,15 @@
-import QtQuick 2.1
+import QtQuick
TextEdit {
- text: ""
-}
+ id: te
+ property int sourceChangeCount: 0
+ property int modifiedChangeCount: 0
+ property var statusHistory: []
+
+ width: 320; height: 240
+ text: "" // this is not a document modification
+ textDocument.onSourceChanged: ++te.sourceChangeCount
+ textDocument.onModifiedChanged: ++te.modifiedChangeCount
+ textDocument.onStatusChanged: te.statusHistory.push(textDocument.status)
+}
diff --git a/tests/auto/quick/qquicktextdocument/tst_qquicktextdocument.cpp b/tests/auto/quick/qquicktextdocument/tst_qquicktextdocument.cpp
index 63d4f24a54..e8c9f09413 100644
--- a/tests/auto/quick/qquicktextdocument/tst_qquicktextdocument.cpp
+++ b/tests/auto/quick/qquicktextdocument/tst_qquicktextdocument.cpp
@@ -1,17 +1,30 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtTest/QtTest>
-#include <QtQuick/QQuickTextDocument>
#include <QtQuick/QQuickItem>
-#include <QtQuick/private/qquicktextedit_p.h>
+#include <QtQuick/QQuickTextDocument>
+#include <QtQuick/QQuickView>
#include <QtQuick/private/qquicktextdocument_p.h>
+#include <QtQuick/private/qquicktextedit_p.h>
+#include <QtQuick/private/qquicktextedit_p_p.h>
+#include <QtCore/QStringConverter>
+#include <QtGui/QTextBlock>
#include <QtGui/QTextDocument>
#include <QtGui/QTextDocumentWriter>
-#include <QtQml/QQmlEngine>
#include <QtQml/QQmlComponent>
+#include <QtQml/QQmlEngine>
+#include <QtQml/QQmlFile>
#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtQuickTestUtils/private/viewtestutils_p.h>
+#ifdef Q_OS_UNIX
+#include <unistd.h>
+#endif
+
+Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
+
+using namespace Qt::StringLiterals;
class tst_qquicktextdocument : public QQmlDataTest
{
@@ -19,18 +32,92 @@ class tst_qquicktextdocument : public QQmlDataTest
public:
tst_qquicktextdocument();
+private:
+ QPair<int, int> fragmentsAndItalics(const QTextDocument *doc);
+ bool isMainFontFixed();
+
private slots:
void textDocumentWriter();
- void textDocumentWithImage();
+ void customDocument();
+ void replaceDocument();
+ void sourceAndSave_data();
+ void sourceAndSave();
+ void loadErrorNoSuchFile();
+ void loadErrorPermissionDenied();
+ void overrideTextFormat_data();
+ void overrideTextFormat();
+ void independentDocumentsSameSource_data();
+ void independentDocumentsSameSource();
};
QString text = QStringLiteral("foo bar");
+// similar to TestDocument in tst_qtextdocument.cpp
+class FakeImageDocument : public QTextDocument
+{
+public:
+ inline FakeImageDocument(const QUrl &testUrl, const QString &testString)
+ : url(testUrl), string(testString), resourceLoaded(false) {}
+
+ bool hasResourceCached();
+
+protected:
+ virtual QVariant loadResource(int type, const QUrl &name) override;
+
+private:
+ QUrl url;
+ QString string;
+ bool resourceLoaded;
+};
+
+bool FakeImageDocument::hasResourceCached()
+{
+ return resourceLoaded;
+}
+
+QVariant FakeImageDocument::loadResource(int type, const QUrl &name)
+{
+ qCDebug(lcTests) << type << name << ": expecting" << int(QTextDocument::ImageResource) << url;
+ if (type == QTextDocument::ImageResource && name == url) {
+ resourceLoaded = true;
+ return string;
+ }
+ return QTextDocument::loadResource(type, name);
+}
+
tst_qquicktextdocument::tst_qquicktextdocument()
: QQmlDataTest(QT_QMLTEST_DATADIR)
{
}
+/*! \internal
+ Returns {fragmentCount, italicFragmentIndex}. If no italic fragment is found,
+ italicFragmentIndex is -1.
+*/
+QPair<int, int> tst_qquicktextdocument::fragmentsAndItalics(const QTextDocument *doc)
+{
+ int fragmentCount = 0;
+ int italicFragment = -1;
+ for (QTextBlock::iterator it = doc->firstBlock().begin(); !(it.atEnd()); ++it) {
+ QTextFragment currentFragment = it.fragment();
+ if (currentFragment.charFormat().fontItalic())
+ italicFragment = fragmentCount;
+ ++fragmentCount;
+ qCDebug(lcTests) << (currentFragment.charFormat().fontItalic() ? "italic" : "roman") << currentFragment.text();
+ }
+ return {fragmentCount, italicFragment};
+}
+
+bool tst_qquicktextdocument::isMainFontFixed()
+{
+ bool ret = QFontInfo(QGuiApplication::font()).fixedPitch();
+ if (ret) {
+ qCWarning(lcTests) << "QFontDatabase::GeneralFont is monospaced: markdown writing is likely to use too many backticks"
+ << QFontDatabase::systemFont(QFontDatabase::GeneralFont);
+ }
+ return ret;
+}
+
void tst_qquicktextdocument::textDocumentWriter()
{
QQmlEngine e;
@@ -54,18 +141,466 @@ void tst_qquicktextdocument::textDocumentWriter()
delete o;
}
-void tst_qquicktextdocument::textDocumentWithImage()
+/*! \internal
+ Verify that it's OK to replace the default QTextDocument that TextEdit creates
+ with a user-created QTextDocument.
+
+ Also verify that the user can still override QTextDocument::loadResource().
+ QTextDocument::loadResource() can call its QObject parent's loadResource();
+ the default QTextDocument's parent is the QQuickTextEdit, which provides an
+ implementation of QQuickTextEdit::loadResource(), which uses QQuickPixmap
+ to load and cache images. This will be bypassed if the user overrides
+ loadResource() to do something different.
+*/
+void tst_qquicktextdocument::customDocument()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("text.qml"));
+ QScopedPointer<QQuickTextEdit> textEdit(qobject_cast<QQuickTextEdit*>(c.create()));
+ QCOMPARE(textEdit.isNull(), false);
+ auto *textEditPriv = QQuickTextEditPrivate::get(textEdit.get());
+ QVERIFY(textEditPriv->ownsDocument);
+
+ QQuickTextDocument *quickDocument = textEdit->property("textDocument").value<QQuickTextDocument*>();
+ QVERIFY(quickDocument);
+ QPointer<QTextDocument> defaultDocument(quickDocument->textDocument());
+ const QString imageUrl = "https://www.qt.io/hubfs/Qt-logo-neon-small.png";
+ const QString fakeImageData = "foo!";
+
+ FakeImageDocument fdoc(QUrl(imageUrl), fakeImageData);
+ quickDocument->setTextDocument(&fdoc);
+ QVERIFY(defaultDocument.isNull()); // deleted because of being replaced (don't leak)
+ QCOMPARE(textEditPriv->ownsDocument, false);
+
+ // QQuickTextEdit::setText() -> QQuickTextControl::setHtml() ->
+ // QQuickTextControlPrivate::setContent() -> fdoc->setHtml()
+ // and eventually fdoc->loadResource() which substitutes a string for the requested image
+ textEdit->setTextFormat(QQuickTextEdit::RichText);
+ textEdit->setText("an image: <img src='" + imageUrl + "'/>");
+ QCOMPARE(fdoc.hasResourceCached(), true);
+
+ auto firstBlock = fdoc.firstBlock();
+ // check that image loading has been bypassed by FakeImageDocument
+ bool foundImage = false;
+ int fragmentCount = 0;
+ for (QTextBlock::iterator it = firstBlock.begin(); !(it.atEnd()); ++it) {
+ QTextFragment currentFragment = it.fragment();
+ QVERIFY(currentFragment.isValid());
+ ++fragmentCount;
+ const QString imageName = currentFragment.charFormat().stringProperty(QTextFormat::ImageName);
+ if (!imageName.isEmpty()) {
+ QCOMPARE(imageName, imageUrl);
+ foundImage = true;
+ QCOMPARE(fdoc.resource(QTextDocument::ImageResource, imageUrl).toString(), fakeImageData);
+ }
+ }
+ QVERIFY(foundImage);
+ QCOMPARE(fragmentCount, 2);
+}
+
+/*! \internal
+ Verify that it's OK to replace the default QTextDocument that TextEdit creates
+ with a user-created QTextDocument that has different text in it, and that
+ interactive editing continues to function afterwards, independently of
+ the previous document.
+*/
+void tst_qquicktextdocument::replaceDocument() // QTBUG-126267
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("initialText.qml")));
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(window.rootObject());
+ QVERIFY(textEdit);
+ auto *textEditPriv = QQuickTextEditPrivate::get(textEdit);
+ QVERIFY(textEditPriv->ownsDocument);
+ QQuickTextDocument *quickDocument = textEdit->property("textDocument").value<QQuickTextDocument*>();
+ QVERIFY(quickDocument);
+ QPointer<QTextDocument> defaultDocument(quickDocument->textDocument());
+
+ QTextDocument replacementDoc;
+ const QString replacementText("Hello World");
+ {
+ QTextCursor cursor(&replacementDoc);
+ cursor.insertText(replacementText);
+ }
+ QCOMPARE(textEdit->text(), "Hello Qt");
+ QSignalSpy renderSpy(&window, &QQuickWindow::afterRendering);
+ quickDocument->setTextDocument(&replacementDoc);
+ QVERIFY(defaultDocument.isNull()); // deleted because of being replaced (don't leak)
+ QCOMPARE(textEditPriv->ownsDocument, false);
+ QCOMPARE(textEdit->text(), replacementText);
+ QCOMPARE(replacementDoc.toPlainText(), replacementText);
+ QTRY_COMPARE_GT(renderSpy.size(), 0);
+
+ QCOMPARE(window.activeFocusItem(), textEdit);
+ QTest::keyEvent(QTest::KeyAction::Click, &window, Qt::Key_End);
+ QTest::keyEvent(QTest::KeyAction::Click, &window, '!');
+ QCOMPARE(textEdit->text(), replacementText + '!');
+}
+
+void tst_qquicktextdocument::sourceAndSave_data()
+{
+ QTest::addColumn<QQuickTextEdit::TextFormat>("textFormat");
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<std::optional<QStringConverter::Encoding>>("expectedEncoding");
+ QTest::addColumn<Qt::TextFormat>("expectedTextFormat");
+ QTest::addColumn<int>("minCharCount");
+ QTest::addColumn<QString>("expectedPlainText");
+
+ const std::optional<QStringConverter::Encoding> nullEnc;
+
+ QTest::newRow("plain") << QQuickTextEdit::PlainText << "hello.txt"
+ << nullEnc << Qt::PlainText << 15 << u"Γειά σου Κόσμε!"_s;
+ QTest::newRow("markdown") << QQuickTextEdit::MarkdownText << "hello.md"
+ << nullEnc << Qt::MarkdownText << 15 << u"Γειά σου Κόσμε!"_s;
+ QTest::newRow("html") << QQuickTextEdit::RichText << "hello.html"
+ << std::optional<QStringConverter::Encoding>(QStringConverter::Utf8)
+ << Qt::RichText << 15 << u"Γειά σου Κόσμε!"_s;
+ QTest::newRow("html-utf16be") << QQuickTextEdit::AutoText << "hello-utf16be.html"
+ << std::optional<QStringConverter::Encoding>(QStringConverter::Utf16BE)
+ << Qt::RichText << 15 << u"Γειά σου Κόσμε!"_s;
+}
+
+void tst_qquicktextdocument::sourceAndSave()
{
- QQuickTextDocumentWithImageResources document(nullptr);
- QImage image(1, 1, QImage::Format_Mono);
- image.fill(1);
+ QFETCH(QQuickTextEdit::TextFormat, textFormat);
+ QFETCH(QString, source);
+ QFETCH(std::optional<QStringConverter::Encoding>, expectedEncoding);
+ QFETCH(Qt::TextFormat, expectedTextFormat);
+ QFETCH(int, minCharCount);
+ QFETCH(QString, expectedPlainText);
+
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("text.qml"));
+ QScopedPointer<QQuickTextEdit> textEdit(qobject_cast<QQuickTextEdit*>(c.create()));
+ QCOMPARE(textEdit.isNull(), false);
+ QQuickTextDocument *qqdoc = textEdit->property("textDocument").value<QQuickTextDocument*>();
+ QVERIFY(qqdoc);
+ const QQmlContext *ctxt = e.rootContext();
+ // text.qml has text: "" but that's not a real change; QQuickTextEdit::setText() returns early
+ // QQuickTextEditPrivate::init() also modifies defaults and then resets the modified state
+ QCOMPARE(qqdoc->isModified(), false);
+ // no stray signals should be visible to QML during init
+ QCOMPARE(textEdit->property("modifiedChangeCount").toInt(), 0);
+ QCOMPARE(textEdit->property("sourceChangeCount").toInt(), 0);
+ QTextDocument *doc = qqdoc->textDocument();
+ QVERIFY(doc);
+ QSignalSpy sourceChangedSpy(qqdoc, &QQuickTextDocument::sourceChanged);
+ QSignalSpy modifiedChangedSpy(qqdoc, &QQuickTextDocument::modifiedChanged);
+ QSignalSpy statusChangedSpy(qqdoc, &QQuickTextDocument::statusChanged);
+
+ QTemporaryDir tmpDir;
+ QVERIFY(tmpDir.isValid());
+ QFile sf(QQmlFile::urlToLocalFileOrQrc(ctxt->resolvedUrl(testFileUrl(source))));
+ qCDebug(lcTests) << source << "orig ->" << sf.fileName();
+ QVERIFY(sf.exists());
+ QString tmpPath = tmpDir.filePath(source);
+ QVERIFY(sf.copy(tmpPath));
+ qCDebug(lcTests) << source << "copy ->" << tmpDir.path() << ":" << tmpPath;
+
+ QCOMPARE(statusChangedSpy.size(), 0);
+ QCOMPARE(qqdoc->status(), QQuickTextDocument::Status::Null);
+ textEdit->setTextFormat(textFormat);
+ qqdoc->setProperty("source", QUrl::fromLocalFile(tmpPath));
+ QCOMPARE(sourceChangedSpy.size(), 1);
+ QCOMPARE(textEdit->property("sourceChangeCount").toInt(), 1);
+ QCOMPARE(statusChangedSpy.size(), 2); // Loading, then Loaded
+ QCOMPARE(qqdoc->status(), QQuickTextDocument::Status::Loaded);
+ QVERIFY(qqdoc->errorString().isEmpty());
+ const auto *qqdp = QQuickTextDocumentPrivate::get(qqdoc);
+ QCOMPARE(qqdp->detectedFormat, expectedTextFormat);
+ QCOMPARE_GE(doc->characterCount(), minCharCount);
+ QCOMPARE(doc->toPlainText().trimmed(), expectedPlainText);
+ QCOMPARE(qqdp->encoding, expectedEncoding);
+
+ textEdit->setText("hello");
+ QCOMPARE(qqdoc->isModified(), false);
+ QCOMPARE_GE(textEdit->property("modifiedChangeCount").toInt(), 1);
+ QCOMPARE(textEdit->property("modifiedChangeCount").toInt(), modifiedChangedSpy.size());
+ modifiedChangedSpy.clear();
+ textEdit->insert(5, "!");
+ QCOMPARE_GE(modifiedChangedSpy.size(), 1);
+ QCOMPARE(qqdoc->isModified(), true);
+
+ qqdoc->save();
+ QCOMPARE(statusChangedSpy.size(), 4); // Saving, then Saved
+ QCOMPARE(qqdoc->status(), QQuickTextDocument::Status::Saved);
+ QVERIFY(qqdoc->errorString().isEmpty());
+ QFile tf(tmpPath);
+ QVERIFY(tf.open(QIODeviceBase::ReadOnly));
+ auto readBack = tf.readAll();
+ if (expectedTextFormat == Qt::RichText) {
+ QStringDecoder dec(*expectedEncoding);
+ const QString decStr = dec(readBack);
+ QVERIFY(decStr.contains("hello!</p>"));
+ } else {
+ QVERIFY(readBack.contains("hello!"));
+ }
+ QCOMPARE(textEdit->property("sourceChangeCount").toInt(), sourceChangedSpy.size());
+}
+
+void tst_qquicktextdocument::loadErrorNoSuchFile()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("text.qml"));
+ QScopedPointer<QQuickTextEdit> textEdit(qobject_cast<QQuickTextEdit*>(c.create()));
+ QCOMPARE(textEdit.isNull(), false);
+ QQuickTextDocument *qqdoc = textEdit->property("textDocument").value<QQuickTextDocument*>();
+ QVERIFY(qqdoc);
+ QCOMPARE(textEdit->property("sourceChangeCount").toInt(), 0);
+ QTextDocument *doc = qqdoc->textDocument();
+ QVERIFY(doc);
+ QSignalSpy sourceChangedSpy(qqdoc, &QQuickTextDocument::sourceChanged);
+ QSignalSpy statusChangedSpy(qqdoc, &QQuickTextDocument::statusChanged);
+
+ QCOMPARE(statusChangedSpy.size(), 0);
+ QCOMPARE(qqdoc->status(), QQuickTextDocument::Status::Null);
+ const QRegularExpression err(".*does not exist");
+ QTest::ignoreMessage(QtWarningMsg, err);
+ qqdoc->setProperty("source", testFileUrl("nosuchfile.md"));
+ QCOMPARE(sourceChangedSpy.size(), 1);
+ QCOMPARE(textEdit->property("sourceChangeCount").toInt(), 1);
+ qCDebug(lcTests) << "status history" << textEdit->property("statusHistory").toList();
+ QCOMPARE(statusChangedSpy.size(), 1);
+ QCOMPARE(qqdoc->status(), QQuickTextDocument::Status::ReadError);
+ QVERIFY(qqdoc->errorString().contains(err));
+}
+
+void tst_qquicktextdocument::loadErrorPermissionDenied()
+{
+#ifdef Q_OS_UNIX
+ if (geteuid() == 0)
+ QSKIP("Permission will not be denied with root privileges.");
+#endif
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("text.qml"));
+ QScopedPointer<QQuickTextEdit> textEdit(qobject_cast<QQuickTextEdit*>(c.create()));
+ QCOMPARE(textEdit.isNull(), false);
+ QQuickTextDocument *qqdoc = textEdit->property("textDocument").value<QQuickTextDocument*>();
+ QVERIFY(qqdoc);
+ const QQmlContext *ctxt = e.rootContext();
+ QCOMPARE(textEdit->property("sourceChangeCount").toInt(), 0);
+ QTextDocument *doc = qqdoc->textDocument();
+ QVERIFY(doc);
+ QSignalSpy sourceChangedSpy(qqdoc, &QQuickTextDocument::sourceChanged);
+ QSignalSpy statusChangedSpy(qqdoc, &QQuickTextDocument::statusChanged);
+
+ QTemporaryDir tmpDir;
+ QVERIFY(tmpDir.isValid());
+ const QString source("hello.md");
+ QFile sf(QQmlFile::urlToLocalFileOrQrc(ctxt->resolvedUrl(testFileUrl(source))));
+ qCDebug(lcTests) << source << "orig ->" << sf.fileName();
+ QVERIFY(sf.exists());
+ QString tmpPath = tmpDir.filePath(source);
+ QVERIFY(sf.copy(tmpPath));
+ qCDebug(lcTests) << source << "copy ->" << tmpDir.path() << ":" << tmpPath;
+ if (!QFile::setPermissions(tmpPath, QFileDevice::Permissions{})) // no permissions at all
+ QSKIP("Failed to change permissions of temporary file: cannot continue.");
+
+ QCOMPARE(statusChangedSpy.size(), 0);
+ QCOMPARE(qqdoc->status(), QQuickTextDocument::Status::Null);
+ const QRegularExpression err(".*Failed to read: Permission denied");
+ QTest::ignoreMessage(QtWarningMsg, err);
+ qqdoc->setProperty("source", QUrl::fromLocalFile(tmpPath));
+ QCOMPARE(sourceChangedSpy.size(), 1);
+ QCOMPARE(textEdit->property("sourceChangeCount").toInt(), 1);
+ qCDebug(lcTests) << "status history" << textEdit->property("statusHistory").toList();
+ QCOMPARE(statusChangedSpy.size(), 1);
+ QCOMPARE(qqdoc->status(), QQuickTextDocument::Status::ReadError);
+ QVERIFY(qqdoc->errorString().contains(err));
+}
+
+void tst_qquicktextdocument::overrideTextFormat_data()
+{
+ QTest::addColumn<QUrl>("qmlfile");
+ QTest::addColumn<QQuickTextEdit::TextFormat>("initialFormat");
+ QTest::addColumn<QUrl>("source");
+ QTest::addColumn<int>("expectedInitialFragmentCount");
+ QTest::addColumn<int>("expectedInitialItalicFragment");
+ // first part of TextEdit.text after loading
+ QTest::addColumn<QString>("expectedTextPrefix");
+
+ QTest::addColumn<QQuickTextEdit::TextFormat>("replacementFormat");
+ QTest::addColumn<int>("expectedFragmentCount");
+ QTest::addColumn<int>("expectedItalicFragment");
+ // first part of TextEdit.text after switching to replacementFormat
+ QTest::addColumn<QString>("expectedReplacementPrefix");
+ QTest::addColumn<int>("expectedTextChangedSignalsAfterReplacement");
+
+ QTest::addColumn<QQuickTextEdit::TextFormat>("finalFormat");
+ QTest::addColumn<int>("expectedFinalFragmentCount");
+ QTest::addColumn<int>("expectedFinalItalicFragment");
+ // first part of TextEdit.text after switching to finalFormat
+ QTest::addColumn<QString>("expectedFinalPrefix");
+
+ QTest::newRow("load md, switch to plain, back to md")
+ << testFileUrl("text.qml") << QQuickTextEdit::MarkdownText << testFileUrl("hello.md")
+ << 3 << 1 << u"Γειά σου *Κόσμε*!"_s
+ << QQuickTextEdit::PlainText << 1 << -1 << u"Γειά σου *Κόσμε*!"_s << 2
+ << QQuickTextEdit::MarkdownText << 3 << 1 << u"Γειά σου *Κόσμε*!"_s;
+ QTest::newRow("load md, switch to plain, then auto")
+ << testFileUrl("text.qml") << QQuickTextEdit::MarkdownText << testFileUrl("hello.md")
+ << 3 << 1 << u"Γειά σου *Κόσμε*!"_s
+ << QQuickTextEdit::PlainText << 1 << -1 << u"Γειά σου *Κόσμε*!"_s << 2
+ << QQuickTextEdit::AutoText << 3 << 1 << u"Γειά σου *Κόσμε*!"_s;
+ QTest::newRow("load md, switch to html, then plain")
+ << testFileUrl("text.qml") << QQuickTextEdit::MarkdownText << testFileUrl("hello.md")
+ << 3 << 1 << u"Γειά σου *Κόσμε*!"_s
+ << QQuickTextEdit::RichText << 3 << 1 << u"<!DOCTYPE HTML"_s << 2
+ << QQuickTextEdit::PlainText << 1 << -1 << u"<!DOCTYPE HTML"_s;
+ QTest::newRow("load md as plain text, switch to md, back to plain")
+ << testFileUrl("text.qml") << QQuickTextEdit::PlainText << testFileUrl("hello.md")
+ << 1 << -1 << u"Γειά σου *Κόσμε*!"_s
+ << QQuickTextEdit::MarkdownText << 3 << 1 << u"Γειά σου *Κόσμε*!"_s << 2
+ << QQuickTextEdit::PlainText << 1 << -1 << u"Γειά σου *Κόσμε*!"_s;
+ QTest::newRow("load md as autotext, switch to plain, back to auto")
+ << testFileUrl("text.qml") << QQuickTextEdit::AutoText << testFileUrl("hello.md")
+ << 3 << 1 << u"Γειά σου *Κόσμε*!"_s
+ << QQuickTextEdit::PlainText << 1 << -1 << u"Γειά σου *Κόσμε*!"_s << 2
+ << QQuickTextEdit::AutoText << 3 << 1 << u"Γειά σου *Κόσμε*!"_s;
+ QTest::newRow("load md as autotext, switch to md, then plain")
+ << testFileUrl("text.qml") << QQuickTextEdit::AutoText << testFileUrl("hello.md")
+ << 3 << 1 << u"Γειά σου *Κόσμε*!"_s
+ << QQuickTextEdit::MarkdownText << 3 << 1 << u"Γειά σου *Κόσμε*!"_s
+ // going from AutoText to a matching explicit format does not cause extra textChanged()
+ << 1
+ << QQuickTextEdit::PlainText << 1 << -1 << u"Γειά σου *Κόσμε*!"_s;
+ QTest::newRow("load md as autotext, switch to html, then plain")
+ << testFileUrl("text.qml") << QQuickTextEdit::AutoText << testFileUrl("hello.md")
+ << 3 << 1 << u"Γειά σου *Κόσμε*!"_s
+ << QQuickTextEdit::RichText << 3 << 1 << u"<!DOCTYPE HTML"_s << 2
+ << QQuickTextEdit::PlainText << 1 << -1 << u"<!DOCTYPE HTML"_s;
+
+ QTest::newRow("load html, switch to plain, back to rich")
+ << testFileUrl("text.qml") << QQuickTextEdit::RichText << testFileUrl("hello.html")
+ << 3 << 1 << u"<!DOCTYPE HTML"_s
+ << QQuickTextEdit::PlainText << 1 << -1 << u"<!DOCTYPE HTML"_s << 2
+ << QQuickTextEdit::RichText << 3 << 1 << u"<!DOCTYPE HTML"_s;
+ QTest::newRow("load html as plain text, switch to html, back to plain")
+ << testFileUrl("text.qml") << QQuickTextEdit::PlainText << testFileUrl("hello.html")
+ << 1 << -1 << u"Γειά σου <i>Κόσμε</i>!"_s
+ << QQuickTextEdit::RichText << 3 << 1 << u"<!DOCTYPE HTML"_s << 2
+ << QQuickTextEdit::PlainText << 1 << -1 << u"<!DOCTYPE HTML"_s;
+ QTest::newRow("load html as autotext, switch to plain, back to auto")
+ << testFileUrl("text.qml") << QQuickTextEdit::AutoText << testFileUrl("hello.html")
+ << 3 << 1 << u"<!DOCTYPE HTML"_s
+ << QQuickTextEdit::PlainText << 1 << -1 << u"<!DOCTYPE HTML"_s << 2
+ << QQuickTextEdit::AutoText << 3 << 1 << u"<!DOCTYPE HTML"_s;
+ QTest::newRow("load html as autotext, switch to html, then plain")
+ << testFileUrl("text.qml") << QQuickTextEdit::AutoText << testFileUrl("hello.html")
+ << 3 << 1 << u"<!DOCTYPE HTML"_s
+ << QQuickTextEdit::RichText << 3 << 1 << u"<!DOCTYPE HTML"_s
+ // going from AutoText to a matching explicit format does not cause extra textChanged()
+ << 1
+ << QQuickTextEdit::PlainText << 1 << -1 << u"<!DOCTYPE HTML"_s;
+ QTest::newRow("load html as autotext, switch to markdown, then plain")
+ << testFileUrl("text.qml") << QQuickTextEdit::AutoText << testFileUrl("hello.html")
+ << 3 << 1 << u"<!DOCTYPE HTML"_s
+ << QQuickTextEdit::MarkdownText << 3 << 1 << u"Γειά σου *Κόσμε*!"_s << 2
+ << QQuickTextEdit::PlainText << 1 << -1 << u"Γειά σου *Κόσμε*!"_s;
+}
+
+void tst_qquicktextdocument::overrideTextFormat() // QTBUG-120772
+{
+ if (isMainFontFixed())
+ QSKIP("fixed-pitch main font (QTBUG-103484)");
+
+ QFETCH(QUrl, qmlfile);
+ QFETCH(QQuickTextEdit::TextFormat, initialFormat);
+ QFETCH(QUrl, source);
+ QFETCH(int, expectedInitialFragmentCount);
+ QFETCH(int, expectedInitialItalicFragment);
+ QFETCH(QString, expectedTextPrefix);
+
+ QFETCH(QQuickTextEdit::TextFormat, replacementFormat);
+ QFETCH(int, expectedFragmentCount);
+ QFETCH(int, expectedItalicFragment);
+ QFETCH(QString, expectedReplacementPrefix);
+ QFETCH(int, expectedTextChangedSignalsAfterReplacement);
+
+ QFETCH(QQuickTextEdit::TextFormat, finalFormat);
+ QFETCH(int, expectedFinalFragmentCount);
+ QFETCH(int, expectedFinalItalicFragment);
+ QFETCH(QString, expectedFinalPrefix);
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, qmlfile));
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(window.rootObject());
+ QVERIFY(textEdit);
+ QQuickTextDocument *qqdoc = textEdit->property("textDocument").value<QQuickTextDocument*>();
+ QVERIFY(qqdoc);
+ QTextDocument *doc = qqdoc->textDocument();
+ QVERIFY(doc);
+
+ textEdit->setTextFormat(initialFormat);
+ QCOMPARE(qqdoc->isModified(), false);
+ QCOMPARE(textEdit->property("sourceChangeCount").toInt(), 0);
+ QSignalSpy sourceChangedSpy(qqdoc, &QQuickTextDocument::sourceChanged);
+ QSignalSpy textChangedSpy(textEdit, &QQuickTextEdit::textChanged);
+
+ qqdoc->setProperty("source", source);
+ QCOMPARE(sourceChangedSpy.size(), 1);
+ QCOMPARE(textEdit->property("sourceChangeCount").toInt(), 1);
+ QCOMPARE_GE(textChangedSpy.size(), 1);
+ auto fragCountAndItalic = fragmentsAndItalics(doc);
+ QCOMPARE(fragCountAndItalic.first, expectedInitialFragmentCount);
+ QCOMPARE(fragCountAndItalic.second, expectedInitialItalicFragment);
+ QString textPropValue = textEdit->text();
+ qCDebug(lcTests) << "expect text()" << textPropValue.first(qMin(20, textPropValue.size() - 1))
+ << "to start with" << expectedTextPrefix;
+ QVERIFY(textPropValue.startsWith(expectedTextPrefix));
+
+ textEdit->setTextFormat(replacementFormat);
+ QCOMPARE(qqdoc->isModified(), false);
+ QCOMPARE(sourceChangedSpy.size(), 1);
+ QCOMPARE_GE(textChangedSpy.size(), expectedTextChangedSignalsAfterReplacement);
+ fragCountAndItalic = fragmentsAndItalics(doc);
+ QCOMPARE(fragCountAndItalic.first, expectedFragmentCount);
+ QCOMPARE(fragCountAndItalic.second, expectedItalicFragment);
+ textPropValue = textEdit->text();
+ qCDebug(lcTests) << "expect text()" << textPropValue.first(qMin(20, textPropValue.size() - 1))
+ << "to start with" << expectedReplacementPrefix;
+ QVERIFY(textPropValue.startsWith(expectedReplacementPrefix));
+
+ textEdit->setTextFormat(finalFormat);
+ QCOMPARE(qqdoc->isModified(), false);
+ QCOMPARE(sourceChangedSpy.size(), 1);
+ QCOMPARE_GE(textChangedSpy.size(), expectedTextChangedSignalsAfterReplacement + 1);
+ fragCountAndItalic = fragmentsAndItalics(doc);
+ QCOMPARE(fragCountAndItalic.first, expectedFinalFragmentCount);
+ QCOMPARE(fragCountAndItalic.second, expectedFinalItalicFragment);
+ textPropValue = textEdit->text();
+ qCDebug(lcTests) << "expect text()" << textPropValue.first(qMin(20, textPropValue.size() - 1))
+ << "to start with" << expectedFinalPrefix;
+ QVERIFY(textPropValue.startsWith(expectedFinalPrefix));
+}
+
+void tst_qquicktextdocument::independentDocumentsSameSource_data()
+{
+ QTest::addColumn<QUrl>("qmlfile");
+
+ QTest::newRow("textFormat above source") << testFileUrl("sideBySideIndependent.qml");
+ QTest::newRow("source above textFormat") << testFileUrl("sideBySideIndependentReverse.qml");
+}
+
+// ensure that two TextEdits' textFormat properties take effect, regardless of qml init order
+void tst_qquicktextdocument::independentDocumentsSameSource() // QTBUG-120772
+{
+ QFETCH(QUrl, qmlfile);
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, qmlfile));
+ QQuickTextEdit *textEditPlain = window.rootObject()->findChild<QQuickTextEdit *>("plain");
+ QVERIFY(textEditPlain);
+ QQuickTextEdit *textEditMarkdown = window.rootObject()->findChild<QQuickTextEdit *>("markdown");
+ QVERIFY(textEditMarkdown);
+
+ auto fragCountAndItalic = fragmentsAndItalics(textEditPlain->textDocument()->textDocument());
+ QCOMPARE(fragCountAndItalic.first, 1);
+ QCOMPARE(fragCountAndItalic.second, -1);
- QString name = "image";
- document.addResource(QTextDocument::ImageResource, name, image);
- QTextImageFormat format;
- format.setName(name);
- QCOMPARE(image, document.image(format));
- QCOMPARE(image, document.resource(QTextDocument::ImageResource, name).value<QImage>());
+ fragCountAndItalic = fragmentsAndItalics(textEditMarkdown->textDocument()->textDocument());
+ QCOMPARE(fragCountAndItalic.first, 3);
+ QCOMPARE(fragCountAndItalic.second, 1);
}
QTEST_MAIN(tst_qquicktextdocument)
diff --git a/tests/auto/quick/qquicktextedit/BLACKLIST b/tests/auto/quick/qquicktextedit/BLACKLIST
index 270a4f7869..d9c889dde3 100644
--- a/tests/auto/quick/qquicktextedit/BLACKLIST
+++ b/tests/auto/quick/qquicktextedit/BLACKLIST
@@ -1,10 +1,3 @@
-# QTBUG-109488 temporary fix
-[largeTextObservesViewport]
-linux
-windows
-android
-darwin
-
[mouseSelection]
opensuse-leap
@@ -36,3 +29,11 @@ android
# QTBUG-108346
[pasteHtmlIntoMarkdown]
ubuntu-20.04
+
+# QTBUG-118066
+[inFlickableMouse]
+opensuse-leap
+
+# QTBUG-118066
+[inFlickableTouch]
+opensuse-leap
diff --git a/tests/auto/quick/qquicktextedit/CMakeLists.txt b/tests/auto/quick/qquicktextedit/CMakeLists.txt
index c071517c04..76ac64d876 100644
--- a/tests/auto/quick/qquicktextedit/CMakeLists.txt
+++ b/tests/auto/quick/qquicktextedit/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicktextedit Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicktextedit LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquicktextedit/data/embeddedImagesLocalError.qml b/tests/auto/quick/qquicktextedit/data/embeddedImagesLocalError.qml
index 067b6d72da..869ef455df 100644
--- a/tests/auto/quick/qquicktextedit/data/embeddedImagesLocalError.qml
+++ b/tests/auto/quick/qquicktextedit/data/embeddedImagesLocalError.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick
TextEdit {
textFormat: TextEdit.RichText
diff --git a/tests/auto/quick/qquicktextedit/data/embeddedImagesRemote.qml b/tests/auto/quick/qquicktextedit/data/embeddedImagesRemote.qml
index 6fc12edf35..a80e669140 100644
--- a/tests/auto/quick/qquicktextedit/data/embeddedImagesRemote.qml
+++ b/tests/auto/quick/qquicktextedit/data/embeddedImagesRemote.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick
TextEdit {
property string serverBaseUrl;
diff --git a/tests/auto/quick/qquicktextedit/data/embeddedImagesRemoteError.qml b/tests/auto/quick/qquicktextedit/data/embeddedImagesRemoteError.qml
index 7ac59e2db4..75b0c5fd5d 100644
--- a/tests/auto/quick/qquicktextedit/data/embeddedImagesRemoteError.qml
+++ b/tests/auto/quick/qquicktextedit/data/embeddedImagesRemoteError.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick
TextEdit {
property string serverBaseUrl;
diff --git a/tests/auto/quick/qquicktextedit/data/focusByDefault.qml b/tests/auto/quick/qquicktextedit/data/focusByDefault.qml
new file mode 100644
index 0000000000..0f518aa7da
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/data/focusByDefault.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+TextEdit {
+ width: 200
+ height: 100
+ focus: true
+}
diff --git a/tests/auto/quick/qquicktextedit/data/hAlignVisual.qml b/tests/auto/quick/qquicktextedit/data/hAlignVisual.qml
index 1280a655f0..f532a9aa36 100644
--- a/tests/auto/quick/qquicktextedit/data/hAlignVisual.qml
+++ b/tests/auto/quick/qquicktextedit/data/hAlignVisual.qml
@@ -4,11 +4,11 @@ Rectangle {
width: 200
height: 100
- Text {
- objectName: "textItem"
+ TextEdit {
+ objectName: "textEditItem"
text: "AA\nBBBBBBB\nCCCCCCCCCCCCCCCC"
anchors.centerIn: parent
- horizontalAlignment: Text.AlignLeft
+ horizontalAlignment: TextEdit.AlignLeft
font.pointSize: 12
font.family: "Times New Roman"
}
diff --git a/tests/auto/quick/qquicktextedit/data/httpfail/warning.png b/tests/auto/quick/qquicktextedit/data/httpfail/warning.png
new file mode 100644
index 0000000000..08d74b8b83
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/data/httpfail/warning.png
Binary files differ
diff --git a/tests/auto/quick/qquicktextedit/data/httpslow/turtle.svg b/tests/auto/quick/qquicktextedit/data/httpslow/turtle.svg
new file mode 100644
index 0000000000..6f34022d0e
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/data/httpslow/turtle.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="355.07501" height="205.41908" viewBox="0 0 284.06001 164.33527" version="1.1" id="svg2" inkscape:version="0.48.4 r9939" sodipodi:docname="AnimalSilhouettes2-Rabbit.svg"><link xmlns="" type="text/css" rel="stylesheet" id="dark-mode-custom-link"/><link xmlns="" type="text/css" rel="stylesheet" id="dark-mode-general-link"/><style xmlns="" lang="en" type="text/css" id="dark-mode-custom-style"/><style xmlns="" lang="en" type="text/css" id="dark-mode-native-style"/><style xmlns="" lang="en" type="text/css" id="dark-mode-native-sheet"/>
+ <metadata id="metadata11474">
+ <rdf:RDF>
+ <cc:Work rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+ <dc:title/>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs id="defs11472"/>
+ <sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1855" inkscape:window-height="1056" id="namedview11470" showgrid="false" units="in" fit-margin-top="0.25" fit-margin-left="0.25" fit-margin-right="0.25" fit-margin-bottom="0.25" inkscape:zoom="0.56869759" inkscape:cx="-269.65967" inkscape:cy="538.58793" inkscape:window-x="65" inkscape:window-y="24" inkscape:window-maximized="1" inkscape:current-layer="svg2"/>
+ <path d="m 116.14,18.675268 c 5.28,-0.32 10.73,-1.18 16,-0.09 1.71,0.51 3.5,0.69 5.3,0.64 0.66,0.08 1.99,0.24 2.65,0.32 0.98,0.67 2.07,0.89 3.26,0.67 l 0.84,0.14 c 0.53,0.21 1.6,0.63 2.13,0.84 l 0.82,-0.07 0.82,0.24 c 0.57,0.2 1.7,0.6 2.27,0.8 l 0.82,0.3 c 0.57,0.22 1.69,0.67 2.26,0.89 0.55,0.24 1.64,0.73 2.19,0.98 l 0.74,0.33 c 0.34,0.16 1.02,0.49 1.36,0.65 l 0.68,0.34 c 0.31,0.17 0.95,0.51 1.26,0.68 l 0.64,0.35 c 0.29,0.18 0.87,0.53 1.17,0.71 0.26,0.19 0.78,0.58 1.04,0.78 l 0.63,0.28 c 0.28,0.2 0.85,0.6 1.13,0.8 0.29,0.21 0.88,0.63 1.17,0.84 l 0.62,0.45 c 0.29,0.22 0.87,0.66 1.16,0.88 0.27,0.21 0.83,0.65 1.11,0.87 0.27,0.22 0.82,0.65 1.09,0.87 0.25,0.23 0.74,0.7 0.99,0.93 l 0.62,0.36 c 0.26,0.24 0.79,0.71 1.06,0.95 0.26,0.24 0.77,0.74 1.03,0.99 0.24,0.25 0.74,0.77 0.99,1.02 0.24,0.27 0.72,0.8 0.96,1.07 l 0.38,0.61 c 0.24,0.25 0.72,0.74 0.96,0.99 0.23,0.26 0.69,0.8 0.92,1.06 0.23,0.27 0.71,0.8 0.94,1.06 0.24,0.26 0.72,0.79 0.96,1.05 0.24,0.27 0.72,0.8 0.96,1.06 0.24,0.27 0.71,0.8 0.95,1.07 0.24,0.27 0.7,0.81 0.94,1.08 l 0.37,0.62 c 0.23,0.24 0.71,0.73 0.94,0.98 0.23,0.26 0.68,0.79 0.91,1.05 0.23,0.26 0.69,0.78 0.92,1.04 0.23,0.26 0.7,0.78 0.94,1.04 0.23,0.26 0.7,0.79 0.93,1.05 0.24,0.27 0.71,0.8 0.95,1.07 0.23,0.28 0.71,0.84 0.95,1.13 l 0.49,0.6 c 0.23,0.28 0.71,0.84 0.94,1.13 0.24,0.26 0.72,0.8 0.96,1.07 0.24,0.25 0.72,0.77 0.97,1.02 0.24,0.25 0.74,0.75 0.98,1 0.26,0.24 0.77,0.72 1.02,0.96 0.26,0.23 0.78,0.69 1.04,0.92 0.27,0.22 0.8,0.66 1.07,0.88 0.25,0.21 0.77,0.64 1.02,0.86 l 0.63,0.32 c 0.28,0.19 0.86,0.56 1.14,0.75 0.28,0.19 0.83,0.56 1.1,0.75 l 0.65,0.25 c 0.29,0.18 0.88,0.54 1.17,0.72 l 0.72,0.21 0.72,0.32 c 0.36,0.15 1.07,0.47 1.43,0.62 l 0.79,0.32 c 0.57,0.23 1.72,0.69 2.29,0.92 l 0.82,0.3 c 0.53,0.28 1.58,0.86 2.1,1.15 l 0.62,0.55 c 0,0.39 0.01,1.16 0.01,1.54 l -0.01,0.7 c -0.14,0.27 -0.42,0.81 -0.56,1.09 -0.13,0.24 -0.38,0.72 -0.5,0.96 l -0.19,0.5 c -0.1,0.23 -0.28,0.69 -0.38,0.92 -0.08,0.22 -0.24,0.66 -0.32,0.89 l -0.14,0.47 -0.16,0.48 c 0.2,-0.11 0.61,-0.34 0.81,-0.45 l 0.55,-0.03 c 0.3,-0.03 0.92,-0.1 1.22,-0.14 l 0.72,-0.12 c 0.52,-0.22 1.56,-0.66 2.09,-0.88 l 0.73,-0.2 c 0.31,-0.18 0.91,-0.55 1.21,-0.73 l 0.69,-0.21 c 0.3,-0.18 0.9,-0.54 1.2,-0.72 l 0.69,-0.22 c 0.3,-0.18 0.9,-0.55 1.2,-0.73 l 0.71,-0.22 c 0.3,-0.19 0.9,-0.55 1.21,-0.73 l 0.7,-0.23 c 0.3,-0.18 0.9,-0.54 1.2,-0.72 l 0.69,-0.23 c 0.3,-0.17 0.89,-0.53 1.19,-0.71 l 0.68,-0.2 c 0.29,-0.18 0.87,-0.53 1.16,-0.7 l 0.7,-0.18 c 0.29,-0.19 0.88,-0.55 1.18,-0.74 0.54,-0.23 1.61,-0.71 2.14,-0.94 l 0.76,-0.34 c 0.35,-0.15 1.07,-0.47 1.42,-0.62 l 0.77,-0.32 c 0.56,-0.2 1.69,-0.62 2.25,-0.83 l 0.82,-0.27 c 0.58,-0.18 1.74,-0.55 2.32,-0.74 0.44,-0.1 1.31,-0.3 1.75,-0.4 0.61,-0.15 1.84,-0.45 2.45,-0.61 0.73,-0.09 2.18,-0.27 2.91,-0.36 1.62,0.07 3.26,0.15 4.9,0.19 l 0.93,0.11 0.89,0.32 c 0.63,0.18 1.88,0.55 2.5,0.74 0.2,0.22 0.61,0.66 0.81,0.87 l 0.61,0.29 c 0.29,0.18 0.85,0.55 1.14,0.73 0.28,0.2 0.85,0.6 1.13,0.8 l 0.59,0.44 c 0.27,0.22 0.8,0.67 1.07,0.89 0.24,0.24 0.74,0.7 0.98,0.94 0.23,0.25 0.68,0.75 0.9,1 0.21,0.27 0.62,0.82 0.83,1.09 l 0.2,0.68 c 0.19,0.3 0.58,0.9 0.77,1.2 l 0.13,0.81 c 0.04,1.24 0.12,2.49 0.22,3.75 l -0.09,0.96 -0.27,0.95 c -0.2,0.66 -0.6,1.99 -0.8,2.65 -0.22,0.21 -0.66,0.62 -0.88,0.83 l -0.3,0.59 c -0.19,0.26 -0.57,0.78 -0.77,1.04 -0.21,0.24 -0.62,0.73 -0.83,0.97 -0.22,0.22 -0.67,0.67 -0.89,0.9 -0.24,0.21 -0.72,0.64 -0.95,0.85 -0.27,0.2 -0.8,0.61 -1.06,0.82 l -0.59,0.4 c -0.31,0.2 -0.92,0.59 -1.23,0.78 -0.53,0.24 -1.61,0.73 -2.15,0.97 -0.42,0.14 -1.26,0.41 -1.68,0.55 -0.59,0.18 -1.76,0.54 -2.34,0.73 l -0.83,0.25 c -0.57,0.19 -1.7,0.57 -2.27,0.76 l -0.81,0.25 c -0.57,0.17 -1.7,0.53 -2.27,0.7 -0.42,0.1 -1.26,0.29 -1.68,0.39 -0.56,0.17 -1.69,0.51 -2.26,0.69 l -0.82,0.23 c -0.57,0.17 -1.71,0.53 -2.27,0.7 -0.43,0.1 -1.27,0.29 -1.7,0.39 -0.57,0.18 -1.71,0.53 -2.29,0.71 l -0.82,0.24 c -0.56,0.19 -1.69,0.57 -2.25,0.76 l -0.81,0.23 -0.83,-0.05 c -0.53,0.21 -1.59,0.65 -2.12,0.87 l -0.83,0.19 c -0.57,0.18 -1.72,0.54 -2.29,0.73 l -0.82,0.250002 c -0.57,0.19 -1.7,0.58 -2.27,0.77 l -0.81,0.23 -0.83,-0.05 c -0.53,0.21 -1.58,0.65 -2.11,0.87 l -0.83,0.18 c -0.57,0.18 -1.69,0.54 -2.26,0.72 l -0.81,0.24 c -0.56,0.19 -1.67,0.57 -2.22,0.76 l -0.81,0.25 c -0.52,0.23 -1.58,0.67 -2.1,0.9 -0.53,0.2 -1.59,0.59 -2.12,0.79 l -0.77,0.25 c -0.54,0.13 -1.6,0.4 -2.14,0.53 l -0.62,0.4 0.17,0.54 c 0.23,0.76 0.46,1.52 0.7,2.29 l 0.19,0.61 c 0.42,-0.01 1.26,-0.03 1.68,-0.04 l 0.85,0 c 0.55,0.17 1.65,0.52 2.21,0.7 l 0.8,0.25 c 0.55,0.19 1.65,0.56 2.21,0.75 l 0.8,0.25 c 0.57,0.18 1.7,0.54 2.26,0.71 l 0.83,0.2 c 0.53,0.21 1.61,0.63 2.14,0.84 l 0.83,-0.07 0.83,0.2 c 0.96,0.75 2.04,1.01 3.25,0.79 l 0.88,-0.04 c 0.68,0.11 2.03,0.32 2.71,0.43 0.6,0.15 1.81,0.45 2.42,0.59 0.42,0.1 1.27,0.3 1.69,0.4 0.54,0.2 1.61,0.59 2.15,0.79 l 0.68,0.32 c 0.33,0.09 0.99,0.25 1.31,0.34 l 0.71,-0.02 c -0.2,0.55 -0.58,1.64 -0.78,2.19 -0.45,1.29 -1.09,2.52 -1.69,3.76 -1.54,0 -2.88,0.8 -4.06,1.7 -0.25,0.2 -0.75,0.61 -1,0.82 l -0.48,0.43 c -0.25,0.21 -0.75,0.61 -1,0.81 -1.23,0.36 -2.39,0.94 -3.3,1.85 -0.36,0.4 -1.1,1.21 -1.47,1.62 l -0.5,0.5 c -0.28,0.18 -0.83,0.52 -1.1,0.69 l -0.63,0.02 -0.63,-0.04 c -0.27,-0.14 -0.81,-0.41 -1.08,-0.55 -0.26,-0.16 -0.78,-0.49 -1.04,-0.66 -0.28,-0.18 -0.83,-0.54 -1.1,-0.72 l -0.59,-0.4 c -0.29,-0.2 -0.87,-0.6 -1.16,-0.79 -0.3,-0.2 -0.89,-0.59 -1.19,-0.79 l -0.63,-0.4 c -0.3,-0.19 -0.9,-0.57 -1.2,-0.76 -0.28,-0.21 -0.82,-0.61 -1.09,-0.82 l -0.67,-0.27 c -0.31,-0.19 -0.93,-0.58 -1.24,-0.77 l -0.65,-0.41 c -0.31,-0.2 -0.93,-0.6 -1.23,-0.8 -0.31,-0.21 -0.93,-0.61 -1.24,-0.81 l -0.64,-0.42 c -0.31,-0.21 -0.91,-0.62 -1.22,-0.83 -0.3,-0.21 -0.9,-0.62 -1.2,-0.82 l -0.63,-0.43 c -0.29,-0.2 -0.87,-0.62 -1.16,-0.82 -0.28,-0.2 -0.83,-0.6 -1.11,-0.8 -0.26,-0.21 -0.77,-0.63 -1.03,-0.84 l -0.62,-0.31 c -0.29,-0.2 -0.86,-0.6 -1.14,-0.81 -0.3,-0.2 -0.89,-0.6 -1.18,-0.81 l -0.63,-0.41 c -0.3,-0.2 -0.9,-0.6 -1.2,-0.8 -0.31,-0.19 -0.92,-0.56 -1.22,-0.75 l -0.64,-0.36 c -0.31,-0.17 -0.92,-0.51 -1.23,-0.68 -0.29,-0.15 -0.88,-0.46 -1.18,-0.62 l -0.72,-0.14 -0.74,-0.2 c -0.58,-1.39 -1.32,-1.5 -2.22,-0.32 -0.66,0.02 -1.99,0.07 -2.66,0.09 -1.79,-0.26 -3.55,0.52 -4.44,2.13 l -0.54,0.65 c -0.15,0.57 -0.44,1.71 -0.58,2.27 l -0.2,0.84 c -0.18,0.57 -0.55,1.72 -0.73,2.3 l -0.24,0.85 c -0.15,0.63 -0.46,1.89 -0.61,2.52 0.08,0.49 0.22,1.49 0.3,1.98 l -0.52,-0.35 c 0.08,0.3 0.24,0.91 0.32,1.21 0.15,0.32 0.45,0.96 0.6,1.28 0.17,0.29 0.5,0.86 0.67,1.15 0.21,0.25 0.63,0.75 0.84,1 0.24,0.22 0.72,0.67 0.97,0.89 l 0.52,0.44 c 0.24,0.21 0.73,0.64 0.98,0.85 0.22,0.22 0.65,0.67 0.86,0.89 l 0.53,0.38 c 0.2,0.26 0.59,0.8 0.78,1.07 0.09,0.34 0.25,1.02 0.34,1.36 0,0.31 0.01,0.94 0.02,1.25 l 0.39,-0.45 c -0.2,0.56 -0.61,1.66 -0.81,2.22 -0.07,0.32 -0.2,0.96 -0.27,1.28 l 0.49,-0.42 -0.67,0.52 c -0.32,0.48 -0.97,1.43 -1.3,1.91 l -0.17,0.79 c -0.03,0.4 -0.09,1.2 -0.11,1.61 -0.46,0.06 -1.37,0.18 -1.83,0.25 -1.52,0.03 -3,0.37 -4.37,0.98 -0.7,0.1 -2.11,0.28 -2.81,0.38 l -0.94,0.04 c -1.75,-0.01 -5.24,-0.03 -6.98,-0.04 -0.73,-0.11 -2.19,-0.33 -2.91,-0.44 -1,-0.7 -2.09,-0.99 -3.29,-0.87 l -0.73,-0.27 c -0.31,-0.14 -0.95,-0.43 -1.27,-0.58 l -0.61,-0.31 c -0.28,-0.18 -0.83,-0.53 -1.11,-0.71 l -0.53,-0.41 c -0.23,-0.25 -0.69,-0.74 -0.92,-0.99 l -0.39,-0.6 c -0.16,-0.34 -0.49,-1.01 -0.65,-1.35 l -0.24,-0.81 c -0.06,-0.69 -0.18,-2.07 -0.25,-2.75 0.07,-0.71 0.19,-2.13 0.25,-2.83 0.17,-0.36 0.5,-1.08 0.67,-1.43 -0.01,-0.43 -0.01,-1.28 -0.02,-1.71 l 0.18,-0.82 c 0.18,-0.34 0.54,-1 0.73,-1.34 0.02,-0.42 0.07,-1.27 0.09,-1.7 l 0.23,-0.85 c 0.17,-0.58 0.53,-1.75 0.7,-2.33 l 0.19,-0.8 c 0.2,-0.31 0.61,-0.91 0.82,-1.21 0.05,-0.41 0.15,-1.23 0.2,-1.65 l 0.36,-0.77 c 0.14,-0.4 0.42,-1.21 0.56,-1.61 l -0.78,-0.26 c -2.71,-0.95 -5.39,-1.57 -8.1,-2.36 -0.38,0.05 -1.15,0.14 -1.53,0.19 -3.58,-0.27 -7.09,-0.38 -10.65,-0.39 -6.39,-0.14 -12.77,0.3 -19.13,-0.1 -0.54,0.18 -1.61,0.52 -2.15,0.69 -0.36,0.09 -1.08,0.27 -1.44,0.36 -0.3,0.1 -0.89,0.3 -1.19,0.4 l 0.71,0.26 c -1.46,-0.04 -1.69,0.56 -0.71,1.8 l 0.07,0.82 c 0,0.4 0,1.21 0,1.61 0.16,0.33 0.47,0.98 0.63,1.31 l 0.14,0.79 c 0.06,0.61 0.17,1.82 0.22,2.43 0.17,0.32 0.5,0.97 0.67,1.29 l 0.24,0.77 c 0.27,0.51 0.8,1.53 1.07,2.04 0.49,0.31 1.48,0.93 1.98,1.23 0.42,0.11 1.25,0.32 1.67,0.42 1.31,0.63 2.73,1 4.19,1.09 0.45,0.07 1.34,0.21 1.79,0.29 0.02,0.43 0.05,1.29 0.07,1.71 l 0.11,0.87 c 0.05,0.43 0.14,1.31 0.19,1.75 l -0.19,0.89 c -0.04,0.44 -0.12,1.33 -0.16,1.77 -1.16,-0.14 -2.02,0.34 -2.57,1.45 -0.43,0.36 -1.3,1.07 -1.73,1.42 -0.12,0.39 -0.35,1.16 -0.47,1.55 l -0.87,-0.12 c -1.23,-0.3 -2.33,-0.04 -3.3,0.79 -1.69,-0.03 -5.06,-0.09 -6.74,-0.13 -1.78,-0.4 -3.59,-0.63 -5.4,-0.61 l -0.87,-0.04 c -0.42,-0.08 -1.28,-0.25 -1.71,-0.34 -0.56,-0.17 -1.67,-0.51 -2.23,-0.68 l -0.7,-0.26 c -0.26,-0.18 -0.79,-0.55 -1.05,-0.73 l -0.63,-0.19 c -0.25,-0.23 -0.74,-0.68 -0.99,-0.9 -0.31,-0.44 -0.94,-1.33 -1.25,-1.77 -0.22,-0.55 -0.65,-1.63 -0.87,-2.17 -0.11,-0.42 -0.34,-1.26 -0.46,-1.67 -0.15,-0.59 -0.47,-1.76 -0.62,-2.35 -0.08,-0.43 -0.24,-1.29 -0.32,-1.72 0.24,-1.21 0,-2.31 -0.7,-3.29 -0.07,-0.43 -0.23,-1.3 -0.3,-1.73 0.24,-1.21 0.01,-2.32 -0.68,-3.31 -0.09,-0.67 -0.27,-1.99 -0.36,-2.65 0.28,-1.2 0.08,-2.3 -0.6,-3.29 -0.12,-0.42 -0.36,-1.25 -0.47,-1.66 -0.4,-0.41 -1.19,-1.21 -1.58,-1.62 -1.12,-0.22 -2.23,-0.48 -3.31,-0.79 -1.11,-0.93 -2.62,-0.28 -2.98,1.03 -0.23,0.22 -0.69,0.65 -0.92,0.86 l -0.33,0.58 c -0.19,0.29 -0.57,0.85 -0.76,1.13 l -0.39,0.59 c -0.19,0.29 -0.57,0.86 -0.75,1.15 -0.2,0.26 -0.6,0.79 -0.8,1.06 l -0.28,0.63 c -0.19,0.28 -0.58,0.86 -0.77,1.14 -0.21,0.27 -0.63,0.8 -0.84,1.06 l -0.32,0.65 c -0.21,0.3 -0.63,0.88 -0.85,1.17 -0.22,0.3 -0.66,0.9 -0.88,1.2 l -0.47,0.62 c -0.23,0.29 -0.7,0.87 -0.93,1.16 -0.24,0.27 -0.71,0.81 -0.95,1.08 -0.24,0.25 -0.72,0.77 -0.96,1.02 -0.25,0.25 -0.75,0.75 -1,0.99 -0.25,0.24 -0.76,0.71 -1.02,0.95 -0.26,0.23 -0.79,0.68 -1.06,0.91 -0.28,0.21 -0.84,0.64 -1.11,0.85 l -0.65,0.28 c -0.28,0.2 -0.82,0.59 -1.1,0.79 l -0.67,0.19 c -0.3,0.16 -0.89,0.49 -1.19,0.65 l -0.67,0.25 c -0.34,0.09 -1.01,0.29 -1.34,0.38 l -0.7,0.06 c -0.32,-0.08 -0.97,-0.23 -1.29,-0.31 l -0.73,0.01 c -0.36,-0.13 -1.07,-0.37 -1.43,-0.5 -0.32,-0.17 -0.95,-0.53 -1.26,-0.71 l -0.6,-0.43 c -0.24,-0.26 -0.73,-0.77 -0.97,-1.03 -0.36,-0.12 -1.1,-0.36 -1.47,-0.49 -0.04,-1.19 -0.55,-2.15 -1.52,-2.86 -0.17,-0.37 -0.49,-1.11 -0.65,-1.47 l -0.35,-0.82 c -0.02,-3.04 -0.02,-5.92 0.08,-8.89 l 0.13,-0.88 0.25,-0.81 c 0.17,-0.3 0.51,-0.91 0.68,-1.21 l 0.13,-0.68 c 0.19,-0.25 0.57,-0.76 0.76,-1.01 l 0.26,-0.59 c 0.22,-0.24 0.65,-0.72 0.86,-0.96 0.26,-0.21 0.78,-0.65 1.03,-0.86 l 0.61,-0.41 c 0.32,-0.19 0.97,-0.57 1.29,-0.75 l 0.74,-0.36 c 0.57,-0.25 1.71,-0.73 2.28,-0.98 l 0.81,-0.34 c 0.52,-0.29 1.57,-0.86 2.09,-1.14 l 0.6,-0.46 c 0.23,-0.21 0.69,-0.65 0.92,-0.86 l 0.29,-0.54 c 0.12,-0.25 0.37,-0.76 0.49,-1.01 l 0.15,-0.55 c 0.09,-0.25 0.25,-0.74 0.33,-0.99 -0.16,-0.21 -0.49,-0.62 -0.66,-0.83 -0.4,-0.33 -1.2,-1.000002 -1.6,-1.330002 l -0.66,-0.34 c -0.28,-0.17 -0.85,-0.51 -1.14,-0.68 l -0.7,-0.15 -0.67,-0.29 c -0.33,-0.14 -0.98,-0.43 -1.31,-0.57 l -0.67,-0.3 c -0.34,-0.15 -1,-0.44 -1.34,-0.59 l -0.71,-0.3 c -0.36,-0.14 -1.09,-0.42 -1.45,-0.56 -0.42,-0.14 -1.25,-0.41 -1.67,-0.54 -1.07,-0.7 -2.23,-0.98 -3.48,-0.83 -0.44,-0.08 -1.33,-0.23 -1.77,-0.31 -0.36,-0.16 -1.07,-0.48 -1.43,-0.64 -0.65,-0.04 -1.94,-0.11 -2.59,-0.15 l -0.84,-0.16 c -0.34,-0.17 -1.03,-0.51 -1.38,-0.68 -0.42,-0.02 -1.27,-0.05 -1.7,-0.06 l -0.83,-0.19 c -0.34,-0.18 -1.03,-0.55 -1.37,-0.74 -0.44,-0.03 -1.33,-0.09 -1.77,-0.11 l -0.88,-0.26 c -0.6,-0.19 -1.82,-0.58 -2.43,-0.78 l -0.8,-0.26 c -0.32,-0.17 -0.97,-0.51 -1.29,-0.68 l -0.76,-0.1 -0.7,-0.3 c -0.33,-0.16 -0.99,-0.47 -1.31,-0.63 l -0.65,-0.32 c -0.29,-0.16 -0.88,-0.49 -1.18,-0.66 l -0.57,-0.32 c -0.24,-0.18 -0.73,-0.52 -0.98,-0.69 -0.21,-0.18 -0.64,-0.54 -0.85,-0.72 -0.2,-0.21 -0.6,-0.63 -0.8,-0.83 l -0.01,-0.64 0.39,-0.57 0.69,0.24 c 0.55,0.12 1.65,0.37 2.19,0.5 l 0.82,0.18 c 0.54,0.2 1.62,0.61 2.16,0.82 l 0.83,-0.06 0.83,0.18 c 0.55,0.22 1.65,0.65 2.2,0.87 l 0.85,-0.05 0.85,0.23 c 1.03,0.7 2.18,0.97 3.43,0.8 0.69,0.12 2.06,0.35 2.75,0.47 1.27,0.5 2.68,1.04 4.06,0.59 l 0.74,-0.14 c 0.91,-0.41 2.71,-0.11 2.88,-1.4 -0.06,-0.25 -0.19,-0.76 -0.26,-1.01 -0.22,-0.18 -0.68,-0.55 -0.91,-0.73 l -0.49,-0.32 c -0.23,-0.16 -0.69,-0.49 -0.92,-0.65 -0.21,-0.16 -0.63,-0.5 -0.84,-0.67 l -0.45,-0.32 c -0.17,-0.21 -0.53,-0.62 -0.7,-0.82 -0.12,-0.25 -0.35,-0.74 -0.46,-0.99 l 0.01,-0.56 0.33,-0.46 c 0.16,-0.23 0.46,-0.7 0.61,-0.93 l 0.45,-0.38 c 0.2,-0.23 0.58,-0.7 0.78,-0.93 0.21,-0.27 0.64,-0.82 0.85,-1.09 l 0.47,-0.63 c 0.31,-0.49 0.94,-1.47 1.25,-1.96 0.22,-0.27 0.67,-0.82 0.89,-1.09 l 0.28,-0.66 c 0.21,-0.28 0.63,-0.82 0.84,-1.1 0.22,-0.26 0.64,-0.79 0.86,-1.05 0.22,-0.26 0.65,-0.78 0.87,-1.04 0.22,-0.27 0.66,-0.81 0.88,-1.08 0.22,-0.29 0.65,-0.86 0.87,-1.15 l 0.45,-0.63 c 0.22,-0.3 0.65,-0.9 0.86,-1.21 0.21,-0.31 0.63,-0.93 0.84,-1.24 l 0.42,-0.65 c 0.2,-0.31 0.6,-0.92 0.8,-1.23 0.22,-0.27 0.64,-0.82 0.85,-1.09 l 0.29,-0.67 c 0.19,-0.29 0.59,-0.89 0.78,-1.18 0.21,-0.27 0.64,-0.82 0.85,-1.09 l 0.3,-0.66 c 0.2,-0.3 0.6,-0.9 0.8,-1.2 0.22,-0.27 0.65,-0.82 0.87,-1.1 l 0.31,-0.67 c 0.2,-0.3 0.61,-0.9 0.81,-1.2 0.22,-0.28 0.66,-0.83 0.87,-1.1 l 0.32,-0.67 c 0.2,-0.3 0.62,-0.9 0.82,-1.19 0.23,-0.27 0.67,-0.81 0.9,-1.08 l 0.32,-0.66 c 0.22,-0.29 0.65,-0.87 0.87,-1.16 0.21,-0.29 0.64,-0.86 0.86,-1.14 0.22,-0.26 0.68,-0.77 0.91,-1.03 l 0.35,-0.63 c 0.22,-0.28 0.67,-0.84 0.89,-1.11 0.23,-0.28 0.69,-0.83 0.91,-1.1 0.23,-0.28 0.69,-0.83 0.92,-1.11 0.23,-0.29 0.7,-0.86 0.93,-1.14 l 0.48,-0.61 c 0.24,-0.27 0.71,-0.83 0.94,-1.11 0.24,-0.26 0.71,-0.79 0.94,-1.05 0.24,-0.25 0.71,-0.75 0.95,-1 0.24,-0.25 0.73,-0.73 0.97,-0.97 0.25,-0.24 0.75,-0.71 1,-0.94 0.25,-0.24 0.77,-0.7 1.03,-0.93 0.28,-0.23 0.82,-0.69 1.1,-0.92 l 0.58,-0.47 c 0.28,-0.22 0.84,-0.67 1.12,-0.89 0.27,-0.22 0.81,-0.65 1.08,-0.87 0.27,-0.22 0.82,-0.65 1.09,-0.87 0.28,-0.21 0.85,-0.64 1.13,-0.85 l 0.61,-0.43 c 0.29,-0.2 0.88,-0.61 1.18,-0.82 0.3,-0.19 0.9,-0.58 1.2,-0.77 l 0.63,-0.38 c 0.3,-0.17 0.91,-0.51 1.22,-0.68 l 0.63,-0.26 c 0.21,-0.22 0.63,-0.66 0.84,-0.87 0.61,-0.19 1.82,-0.56 2.42,-0.75 l 0.84,-0.37 c 0.57,-0.24 1.73,-0.71 2.31,-0.94 0.41,-0.04 1.24,-0.11 1.66,-0.15 0.31,-0.2 0.93,-0.6 1.24,-0.8 l 0.81,-0.2 c 0.6,-0.16 1.8,-0.48 2.4,-0.64 0.45,-0.08 1.36,-0.25 1.81,-0.34 1.19,0 2.39,-0.04 3.59,-0.11 l 0.82,0.17 0.38,-0.76 c 1.2,-0.18 2.41,-0.29 3.64,-0.33 2.49,-0.05 4.98,-0.21 7.47,-0.48 z" id="path9046" inkscape:connector-curvature="0" style="fill:#000000;stroke:#000000;stroke-width:0.09375"/>
+</svg> \ No newline at end of file
diff --git a/tests/auto/quick/qquicktextedit/data/inFlickable.qml b/tests/auto/quick/qquicktextedit/data/inFlickable.qml
index 7a896db29b..183ddd6701 100644
--- a/tests/auto/quick/qquicktextedit/data/inFlickable.qml
+++ b/tests/auto/quick/qquicktextedit/data/inFlickable.qml
@@ -1,6 +1,7 @@
import QtQuick 2.0
Flickable {
+ id: flick
width: 320; height: 120; contentHeight: text.height
TextEdit {
id: text
@@ -8,4 +9,10 @@ Flickable {
font.pixelSize: 20
text: "several\nlines\nof\ntext\n-\ntry\nto\nflick"
}
+ Text {
+ color: "red"
+ parent: flick // stay on top
+ anchors.right: parent.right
+ text: flick.contentY.toFixed(1)
+ }
}
diff --git a/tests/auto/quick/qquicktextedit/data/multipleRemoteImages.md b/tests/auto/quick/qquicktextedit/data/multipleRemoteImages.md
new file mode 100644
index 0000000000..370924e739
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/data/multipleRemoteImages.md
@@ -0,0 +1,13 @@
+# Images
+
+Unsupported URL scheme: ![alt text](gopher://qt.io/icon48.png "Qt doesnt't support gopher")
+
+Just an image, expected to work: ![alt text](serverBaseUrl/exists.png "Qt logo")
+
+Reference-style, same image: ![alt text][logo]
+
+[logo]: serverBaseUrl/exists.png "Qt logo"
+
+Slow: ![Turtle](serverBaseUrl/turtle.svg "Behold the turtle")
+
+Fails to load from server: ![FailBang](serverBaseUrl/warning.png "Warning")
diff --git a/tests/auto/quick/qquicktextedit/data/qtConfigureHelp.qml b/tests/auto/quick/qquicktextedit/data/qtConfigureHelp.qml
new file mode 100644
index 0000000000..58ef58b372
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/data/qtConfigureHelp.qml
@@ -0,0 +1,186 @@
+import QtQuick
+import Qt.test 1.0
+
+NodeCheckerTextEdit {
+ id: textedit
+ width: 640
+ height: 480
+ text: "Usage: configure [options] [-- cmake-options]
+
+This is a convenience script for configuring Qt with CMake.
+Options after the double dash are directly passed to CMake.
+
+Top-level installation directories:
+ -prefix <dir> ...... The deployment directory, as seen on the target device.
+ [/usr/local/Qt-$QT_VERSION; qtbase build directory if
+ -developer-build]
+ -no-prefix ......... The deployment directory is set to the qtbase build
+ directory. Can be used instead of -developer-build
+ to not have to install, as well as avoid
+ -developer-build's default of -warnings-are-errors.
+ -extprefix <dir> ... The installation directory, as seen on the host machine.
+ [SYSROOT/PREFIX]
+
+Fine tuning of installation directory layout. Note that all directories
+except -sysconfdir should be located under -prefix:
+
+ -bindir <dir> ......... Executables [PREFIX/bin]
+ -headerdir <dir> ...... Header files [PREFIX/include]
+ -libdir <dir> ......... Libraries [PREFIX/lib]
+ -archdatadir <dir> .... Arch-dependent data [PREFIX]
+ -plugindir <dir> ...... Plugins [ARCHDATADIR/plugins]
+ -libexecdir <dir> ..... Helper programs [ARCHDATADIR/bin on Windows,
+ ARCHDATADIR/libexec otherwise]
+ -qmldir <dir> ......... QML imports [ARCHDATADIR/qml]
+ -datadir <dir> ........ Arch-independent data [PREFIX]
+ -docdir <dir> ......... Documentation [DATADIR/doc]
+ -translationdir <dir> . Translations [DATADIR/translations]
+ -sysconfdir <dir> ..... Settings used by Qt programs [PREFIX/etc/xdg]
+ -examplesdir <dir> .... Examples [PREFIX/examples]
+ -testsdir <dir> ....... Tests [PREFIX/tests]
+ -hostdatadir <dir> .... Data used by qmake [PREFIX]
+
+Conventions for the remaining options: When an option's description is
+followed by a list of values in brackets, the interpretation is as follows:
+'yes' represents the bare option; all other values are possible prefixes to
+the option, e.g., -no-gui. Alternatively, the value can be assigned, e.g.,
+--gui=yes. Values are listed in the order they are tried if not specified;
+'auto' is a shorthand for 'yes/no'. Solitary 'yes' and 'no' represent binary
+options without auto-detection.
+
+Configure meta:
+
+ -help, -h ............ Display this help screen
+ -redo ................ Re-configure with previously used options. In addition,
+ redo removes CMakeCache.txt file and CMakeFiles/ directory
+ and recreates them from scratch.
+ Additional options may be passed, but will not be
+ saved for later use by -redo.
+
+ -feature-<feature> ... Enable <feature>
+ -no-feature-<feature> Disable <feature> [none]
+ -list-features ....... List available features. Note that some features
+ have dedicated command line options as well.
+
+Build options:
+
+ -cmake-generator <name> ... Explicitly specify the build system generator for
+ CMake instead of auto-detecting one.
+ -cmake-use-default-generator ... Turn off auto-detection of the CMake build
+ system generatsr.
+ -cmake-file-api ...... Let CMake store build metadata for loading the build
+ into an IDE. [no; yes if -developer-build]
+ -no-guess-compiler ... Do not guess the compiler from the target mkspec.
+ -release ............. Build Qt with debugging turned off [yes]
+ -debug ............... Build Qt with debugging turned on [no]
+ -debug-and-release ... Build two versions of Qt, with and without
+ debugging turned on [yes] (Apple and Windows only)
+ -optimize-debug ...... Enable debug-friendly optimizations in debug builds
+ [auto] (Not supported with MSVC or Clang toolchains)
+ -optimize-size ....... Optimize release builds for size instead of speed [no]
+ -force-debug-info .... Create symbol files for release builds [no]
+ -separate-debug-info . Split off debug information to separate files [no]
+ -gdb-index ........... Index the debug info to speed up GDB
+ [no; auto if -developer-build with debug info]
+ -gc-binaries ......... Place each function or data item into its own section
+ and enable linker garbage collection of unused
+ sections. [auto for static builds, otherwise no]
+ -force-asserts ....... Enable Q_ASSERT even in release builds [no]
+ -developer-build ..... Compile and link Qt for developing Qt itself
+ (exports for auto-tests, extra checks, etc.) [no]
+
+ -shared .............. Build shared Qt libraries [yes] (no for UIKit)
+ -static .............. Build static Qt libraries [no] (yes for UIKit)
+ -framework ........... Build Qt framework bundles [yes] (Apple only)
+
+ -platform <target> ... Select mkspec for the qmake companion files
+ -device <name> ....... Select devices/mkspec for the qmake companion files
+ -device-option <key=value> ... Add option for the device mkspec
+
+ -appstore-compliant .. Disable code that is not allowed in platform app stores.
+ This is on by default for platforms which require distribution
+ through an app store by default, in particular Android,
+ iOS, tvOS, and watchOS. [auto]
+
+ -qt-host-path <path> . Specify path to a Qt host build for cross-compiling.
+ -qtnamespace <name> .. Wrap all Qt library code in 'namespace <name> {...}'.
+ -qtlibinfix <infix> .. Rename all libQt6*.so to libQt6*<infix>.so.
+
+ -testcocoon .......... Instrument with the TestCocoon code coverage tool [no]
+ -gcov ................ Instrument with the GCov code coverage tool [no]
+
+ -trace [backend] ..... Enable instrumentation with tracepoints.
+ Currently supported backends are 'etw' (Windows) and
+ 'lttng' (Linux), or 'yes' for auto-detection. [no]
+
+ -sanitize {address|thread|memory|fuzzer-no-link|undefined}
+ Instrument with the specified compiler sanitizer.
+ Note that some sanitizers cannot be combined;
+ for example, -sanitize address cannot be combined with
+ -sanitize thread.
+
+ -mips_dsp/-mips_dspr2 Use MIPS DSP/rev2 instructions [auto]
+
+ -qreal <type> ........ typedef qreal to the specified type. [double]
+ Note: this affects binary compatibility.
+
+ -R <string> .......... Add an explicit runtime library path to the Qt
+ libraries. Supports paths relative to LIBDIR.
+ -rpath ............... Link Qt libraries and executables using the library
+ install path as a runtime library path. Similar to
+ -R LIBDIR. On Apple platforms, disabling this implies
+ using absolute install names (based in LIBDIR) for
+ dynamic libraries and frameworks. [auto]
+
+ -reduce-exports ...... Reduce amount of exported symbols [auto]
+ -reduce-relocations .. Reduce amount of relocations [auto] (Unix only)
+
+ -plugin-manifests .... Embed manifests into plugins [no] (Windows only)
+ -static-runtime ...... With -static, use static runtime [no] (Windows only)
+
+ -pch ................. Use precompiled headers [auto]
+ -ltcg ................ Use Link Time Code Generation [no]
+ -intelcet ............ Use Intel Control-flow Enforcement Technology [no]
+ -linker [bfd,gold,lld,mold]
+ Force use of the GNU ld, GNU gold, LLVM/LLD or mold
+ linker instead of default one (GCC and clang only)
+ -ccache .............. Use the ccache compiler cache [no] (Unix only)
+ -unity-build ......... Enable Unity (Jumbo) build
+ -unity-build-batch-size <int>
+ Maximum number of source files used by the unity build
+ to create unity source files [8]
+
+ -warnings-are-errors . Treat warnings as errors [no; yes if -developer-build]
+
+ -disable-deprecated-up-to <version>
+ Set the QT_DISABLE_DEPRECATED_UP_TO value to <version>.
+ QT_DISABLE_DEPRECATED_UP_TO is used to remove
+ deprecated methods from both API and ABI.
+ <version> is a hex value, for example 0x060500 can be
+ used to remove all code deprecated in Qt 6.5.0 or
+ earlier releases.
+ By default <version> is set to 0x040000 and 0x050000 on
+ Windows, and non-Windows respectively.
+ -disable-deprecated-up-to <version>
+ Set the QT_DISABLE_DEPRECATED_UP_TO value to <version>.
+ QT_DISABLE_DEPRECATED_UP_TO is used to remove
+ deprecated methods from both API and ABI.
+ <version> is a hex value, for example 0x060500 can be
+ used to remove all code deprecated in Qt 6.5.0 or
+ earlier releases.
+ By default <version> is set to 0x040000 and 0x050000 on
+ Windows, and non-Windows respectively.
+used to remove all code deprecated in Qt 6.5.0 or
+ earlier releases.
+
+Build environment:
+
+ -sysroot <dir> ....... Set <dir> as the target sysroot
+
+ -pkg-config .......... Use pkg-config [auto] (Unix only)
+
+ -D <string> .......... Pass additional preprocessor define
+ -I <string> .......... Pass additional include path
+ -L <string> .......... Pass additional library path
+ -F <string> .......... Pass additional framework path (Apple only)>"
+}
diff --git a/tests/auto/quick/qquicktextedit/data/qtbug-112858.qml b/tests/auto/quick/qquicktextedit/data/qtbug-112858.qml
new file mode 100644
index 0000000000..95f7905737
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/data/qtbug-112858.qml
@@ -0,0 +1,12 @@
+import QtQuick
+import QtQuick.Layouts
+
+ColumnLayout {
+ id: layout
+ TextEdit {
+ readOnly: true
+ text: 'שדגשגשגשגדוגמ×
+בעיות יישור
+טֶקסט'
+ }
+}
diff --git a/tests/auto/quick/qquicktextedit/data/resizeTextEditPolish.qml b/tests/auto/quick/qquicktextedit/data/resizeTextEditPolish.qml
new file mode 100644
index 0000000000..44819a0de9
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/data/resizeTextEditPolish.qml
@@ -0,0 +1,42 @@
+import QtQuick
+import QtQuick.Controls
+
+Item {
+ width: 400
+ height: 150
+
+ TextEdit {
+ id: textEdit
+ anchors {
+ top: parent.top
+ left: parent.left
+ right: parent.right
+ }
+ readOnly: true
+ wrapMode: Text.WordWrap
+ verticalAlignment: Text.AlignVCenter
+ text: "Lorem ipsum dolor sit amet, consectetur adipisicing"
+ states: [
+ State {
+ name: "multi-line"
+ when: textEdit.lineCount > 1
+ AnchorChanges {
+ target: textEdit
+ anchors.bottom: undefined
+ }
+ PropertyChanges {
+ target: textEdit
+ height: undefined
+ }
+ },
+ State {
+ name: "single-line"
+ when: true
+ AnchorChanges {
+ target: textEdit
+ anchors.bottom: { return textEdit.parent.bottom }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/auto/quick/qquicktextedit/data/textEdit.qml b/tests/auto/quick/qquicktextedit/data/textEdit.qml
new file mode 100644
index 0000000000..3bcc40350e
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/data/textEdit.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+TextEdit {
+ width: 400
+ height: 540
+}
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index d15d40083d..c8377aa2d3 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -1,12 +1,15 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtTest/QSignalSpy>
#include <QtQuickTestUtils/private/testhttpserver_p.h>
#include <math.h>
#include <QFile>
#include <QtQuick/QQuickTextDocument>
+#include <QtQuickTest/QtQuickTest>
#include <QTextDocument>
+#include <QtGui/qtextobject.h>
+#include <QtGui/QTextTable>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlexpression.h>
@@ -18,7 +21,7 @@
#include <private/qquicktextedit_p.h>
#include <private/qquicktextedit_p_p.h>
#include <private/qquicktext_p.h>
-#include <private/qquicktextdocument_p.h>
+#include <QtQuick/private/qquickpixmapcache_p.h>
#include <QFontMetrics>
#include <QtQuick/QQuickView>
#include <QDir>
@@ -40,14 +43,31 @@ Q_DECLARE_METATYPE(QQuickTextEdit::SelectionMode)
Q_DECLARE_METATYPE(Qt::Key)
DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+
+typedef QPair<int, QChar> Key;
+typedef QList<Key> KeyList;
+Q_DECLARE_METATYPE(KeyList)
+
+Q_DECLARE_METATYPE(QQuickTextEdit::HAlignment)
+Q_DECLARE_METATYPE(QQuickTextEdit::VAlignment)
+Q_DECLARE_METATYPE(QQuickTextEdit::TextFormat)
+
+#if QT_CONFIG(shortcut)
+Q_DECLARE_METATYPE(QKeySequence::StandardKey)
+#endif
+
Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
+// #define DEBUG_WRITE_INPUT
+
static bool isPlatformWayland()
{
return !QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive);
}
-typedef QPair<int, QChar> Key;
+QT_BEGIN_NAMESPACE
class tst_qquicktextedit : public QQmlDataTest
@@ -140,7 +160,10 @@ private slots:
void implicitSizeBinding();
void largeTextObservesViewport_data();
void largeTextObservesViewport();
+ void largeTextSelection();
void renderingAroundSelection();
+ void largeTextTables_data();
+ void largeTextTables();
void signal_editingfinished();
@@ -177,6 +200,7 @@ private slots:
void baseUrl();
void embeddedImages();
void embeddedImages_data();
+ void remoteImagesInDocumentSource();
void emptytags_QTBUG_22058();
void cursorRectangle_QTBUG_38947();
@@ -206,6 +230,13 @@ private slots:
void touchscreenDoesNotSelect();
void touchscreenSetsFocusAndMovesCursor();
+ void longPressInputMethod();
+
+ void rtlAlignmentInColumnLayout_QTBUG_112858();
+
+ void fontManipulationWithCursorSelection();
+ void resizeTextEditPolish();
+
private:
void simulateKeys(QWindow *window, const QList<Key> &keys);
#if QT_CONFIG(shortcut)
@@ -214,7 +245,6 @@ private:
void simulateKey(QWindow *, int key, Qt::KeyboardModifiers modifiers = {});
bool isMainFontFixed();
- static bool hasWindowActivation();
QStringList standard;
QStringList richText;
@@ -232,16 +262,6 @@ private:
QPointingDevice *touchDevice = QTest::createTouchDevice();
};
-typedef QList<int> IntList;
-Q_DECLARE_METATYPE(IntList)
-
-typedef QList<Key> KeyList;
-Q_DECLARE_METATYPE(KeyList)
-
-Q_DECLARE_METATYPE(QQuickTextEdit::HAlignment)
-Q_DECLARE_METATYPE(QQuickTextEdit::VAlignment)
-Q_DECLARE_METATYPE(QQuickTextEdit::TextFormat)
-
void tst_qquicktextedit::simulateKeys(QWindow *window, const QList<Key> &keys)
{
for (int i = 0; i < keys.size(); ++i) {
@@ -346,7 +366,7 @@ public:
void populateLinePositions(QSGNode *node)
{
- linePositions.clear();
+ sortedLinePositions.clear();
lastLinePosition = 0;
QSGNode *ch = node->firstChild();
while (ch != node->lastChild()) {
@@ -361,14 +381,12 @@ public:
qCDebug(lcTests) << "ignoring leaf TransformNode" << tn << "@ y" << y;
} else {
qCDebug(lcTests) << "child" << tn << "@ y" << y << "has children" << tn->childCount();
- if (!linePositions.contains(y)) {
- linePositions.append(y);
- lastLinePosition = qMax(lastLinePosition, y);
- }
+ sortedLinePositions.append(y);
+ lastLinePosition = qMax(lastLinePosition, y);
}
ch = ch->nextSibling();
}
- std::sort(linePositions.begin(), linePositions.end());
+ std::sort(sortedLinePositions.begin(), sortedLinePositions.end());
}
QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *data) override
@@ -379,7 +397,7 @@ public:
return ret;
}
- QList<int> linePositions;
+ QList<int> sortedLinePositions;
int lastLinePosition;
};
@@ -714,9 +732,9 @@ void tst_qquicktextedit::lineCount_data()
void tst_qquicktextedit::lineCount()
{
- QFETCH(QStringList, texts);
+ QFETCH(const QStringList, texts);
- foreach (const QString& text, texts) {
+ for (const QString& text : texts) {
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0\nTextEdit { }", QUrl());
@@ -967,8 +985,8 @@ void tst_qquicktextedit::hAlignVisual()
view.showNormal();
QVERIFY(QTest::qWaitForWindowExposed(&view));
- QQuickText *text = view.rootObject()->findChild<QQuickText*>("textItem");
- QVERIFY(text != nullptr);
+ QQuickTextEdit *text = view.rootObject()->findChild<QQuickTextEdit*>("textEditItem");
+ QVERIFY(text);
// Try to check whether alignment works by checking the number of black
// pixels in the thirds of the grabbed image.
@@ -995,7 +1013,7 @@ void tst_qquicktextedit::hAlignVisual()
}
{
// HCenter Align
- text->setHAlign(QQuickText::AlignHCenter);
+ text->setHAlign(QQuickTextEdit::AlignHCenter);
QImage image = view.grabWindow();
const int left = numberOfNonWhitePixels(centeredSection1, centeredSection2, image);
const int mid = numberOfNonWhitePixels(centeredSection2, centeredSection3, image);
@@ -1005,7 +1023,7 @@ void tst_qquicktextedit::hAlignVisual()
}
{
// Right Align
- text->setHAlign(QQuickText::AlignRight);
+ text->setHAlign(QQuickTextEdit::AlignRight);
QImage image = view.grabWindow();
const int left = numberOfNonWhitePixels(centeredSection1, centeredSection2, image);
const int mid = numberOfNonWhitePixels(centeredSection2, centeredSection3, image);
@@ -1017,36 +1035,36 @@ void tst_qquicktextedit::hAlignVisual()
text->setWidth(200);
{
- // Left Align
+ // Right Align
QImage image = view.grabWindow();
- int x = qCeil(text->implicitWidth() * view.devicePixelRatio());
- int left = numberOfNonWhitePixels(0, x, image);
- int right = numberOfNonWhitePixels(x, image.width() - x, image);
- QVERIFY2(left > 0, msgNotGreaterThan(left, 0).constData());
- QCOMPARE(right, 0);
+ const int x = image.width() - qCeil(text->implicitWidth() * view.devicePixelRatio());
+ const int left = numberOfNonWhitePixels(0, x, image);
+ const int right = numberOfNonWhitePixels(x, image.width() - x, image);
+ QCOMPARE(left, 0);
+ QVERIFY2(right > 0, msgNotGreaterThan(left, 0).constData());
}
{
// HCenter Align
- text->setHAlign(QQuickText::AlignHCenter);
+ text->setHAlign(QQuickTextEdit::AlignHCenter);
QImage image = view.grabWindow();
- int x1 = qFloor(image.width() - text->implicitWidth() * view.devicePixelRatio()) / 2;
- int x2 = image.width() - x1;
- int left = numberOfNonWhitePixels(0, x1, image);
- int mid = numberOfNonWhitePixels(x1, x2 - x1, image);
- int right = numberOfNonWhitePixels(x2, image.width() - x2, image);
+ const int x1 = qFloor(image.width() - text->implicitWidth() * view.devicePixelRatio()) / 2;
+ const int x2 = image.width() - x1;
+ const int left = numberOfNonWhitePixels(0, x1, image);
+ const int mid = numberOfNonWhitePixels(x1, x2 - x1, image);
+ const int right = numberOfNonWhitePixels(x2, image.width(), image);
QCOMPARE(left, 0);
QVERIFY2(mid > 0, msgNotGreaterThan(left, 0).constData());
QCOMPARE(right, 0);
}
{
- // Right Align
- text->setHAlign(QQuickText::AlignRight);
+ // Left Align
+ text->setHAlign(QQuickTextEdit::AlignLeft);
QImage image = view.grabWindow();
- int x = image.width() - qCeil(text->implicitWidth() * view.devicePixelRatio());
- int left = numberOfNonWhitePixels(0, x, image);
- int right = numberOfNonWhitePixels(x, image.width() - x, image);
- QCOMPARE(left, 0);
- QVERIFY2(right > 0, msgNotGreaterThan(left, 0).constData());
+ const int x = qCeil(text->implicitWidth() * view.devicePixelRatio());
+ const int left = numberOfNonWhitePixels(0, x, image);
+ const int right = numberOfNonWhitePixels(x, image.width() - x, image);
+ QVERIFY2(left > 0, msgNotGreaterThan(left, 0).constData());
+ QCOMPARE(right, 0);
}
}
@@ -1297,10 +1315,8 @@ void tst_qquicktextedit::textMargin()
void tst_qquicktextedit::persistentSelection()
{
- QQuickView window(testFileUrl("persistentSelection.qml"));
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("persistentSelection.qml")));
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(edit);
@@ -1410,6 +1426,7 @@ void tst_qquicktextedit::selectionOnFocusOut()
void tst_qquicktextedit::focusOnPress()
{
+ const int doubleClickInterval = qApp->styleHints()->mouseDoubleClickInterval();
QString componentStr =
"import QtQuick 2.0\n"
"TextEdit {\n"
@@ -1466,7 +1483,7 @@ void tst_qquicktextedit::focusOnPress()
QCOMPARE(activeFocusSpy.size(), 2);
// Wait for double click timeout to expire before clicking again.
- QTest::qWait(400);
+ QTest::qWait(doubleClickInterval + 1);
QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QCOMPARE(textEditObject->hasFocus(), false);
@@ -1482,7 +1499,7 @@ void tst_qquicktextedit::focusOnPress()
// Test a selection made in the on(Active)FocusChanged handler isn't overwritten.
textEditObject->setProperty("selectOnFocus", true);
- QTest::qWait(400);
+ QTest::qWait(doubleClickInterval + 1);
QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QCOMPARE(textEditObject->hasFocus(), true);
@@ -1579,20 +1596,12 @@ void tst_qquicktextedit::selection()
void tst_qquicktextedit::overwriteMode()
{
- QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true; }";
- QQmlComponent textEditComponent(&engine);
- textEditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != nullptr);
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("focusByDefault.qml")));
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(window.rootObject());
QSignalSpy spy(textEdit, SIGNAL(overwriteModeChanged(bool)));
- QQuickWindow window;
- textEdit->setParentItem(window.contentItem());
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
-
QVERIFY(textEdit->hasActiveFocus());
textEdit->setOverwriteMode(true);
@@ -1704,12 +1713,8 @@ void tst_qquicktextedit::isRightToLeft()
void tst_qquicktextedit::keySelection()
{
- QQuickView window(testFileUrl("navigation.qml"));
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
-
- QVERIFY(window.rootObject() != nullptr);
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("navigation.qml")));
QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
@@ -2086,7 +2091,7 @@ void tst_qquicktextedit::moveCursorSelectionSequence()
void tst_qquicktextedit::mouseSelection_data()
{
- QTest::addColumn<QString>("qmlfile");
+ QTest::addColumn<QUrl>("qmlfile");
QTest::addColumn<int>("from");
QTest::addColumn<int>("to");
QTest::addColumn<QString>("selectedText");
@@ -2095,64 +2100,64 @@ void tst_qquicktextedit::mouseSelection_data()
QTest::addColumn<int>("clicks");
// import installed
- QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << true << true << 1;
- QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString() << true << true << 1;
- QTest::newRow("default") << testFile("mouseselectionmode_default.qml") << 4 << 9 << "45678" << true << true << 1;
- QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString() << true << true << 1;
- QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << true << true << 1;
-
- QTest::newRow("on unfocused") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << false << 1;
- QTest::newRow("on word selection (4,9) unfocused") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << false << 1;
-
- QTest::newRow("on focus on press") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << true << 1;
- QTest::newRow("on word selection (4,9) focus on press") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << true << 1;
-
- QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
- QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
- QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
- QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
- QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
- QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
- QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
- QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
-
- QTest::newRow("on double click (4,9)") << testFile("mouseselection_true.qml") << 4 << 9 << "0123456789" << true << true << 2;
- QTest::newRow("on double click (2,13)") << testFile("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
- QTest::newRow("on double click (2,30)") << testFile("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
- QTest::newRow("on double click (9,13)") << testFile("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
- QTest::newRow("on double click (9,30)") << testFile("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
- QTest::newRow("on double click (13,2)") << testFile("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
- QTest::newRow("on double click (20,2)") << testFile("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
- QTest::newRow("on double click (12,9)") << testFile("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
- QTest::newRow("on double click (30,9)") << testFile("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
-
- QTest::newRow("on triple click (4,9)") << testFile("mouseselection_true.qml") << 4 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
- QTest::newRow("on triple click (2,13)") << testFile("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
- QTest::newRow("on triple click (2,30)") << testFile("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
- QTest::newRow("on triple click (9,13)") << testFile("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
- QTest::newRow("on triple click (9,30)") << testFile("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
- QTest::newRow("on triple click (13,2)") << testFile("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
- QTest::newRow("on triple click (20,2)") << testFile("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
- QTest::newRow("on triple click (12,9)") << testFile("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
- QTest::newRow("on triple click (30,9)") << testFile("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
-
- QTest::newRow("on triple click (2,40)") << testFile("mouseselection_true.qml") << 2 << 40 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n" << true << true << 3;
- QTest::newRow("on triple click (2,50)") << testFile("mouseselection_true.qml") << 2 << 50 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
- QTest::newRow("on triple click (25,40)") << testFile("mouseselection_true.qml") << 25 << 40 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n" << true << true << 3;
- QTest::newRow("on triple click (25,50)") << testFile("mouseselection_true.qml") << 25 << 50 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
- QTest::newRow("on triple click (40,25)") << testFile("mouseselection_true.qml") << 40 << 25 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n" << true << true << 3;
- QTest::newRow("on triple click (40,50)") << testFile("mouseselection_true.qml") << 40 << 50 << "9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
- QTest::newRow("on triple click (50,25)") << testFile("mouseselection_true.qml") << 50 << 25 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
- QTest::newRow("on triple click (50,40)") << testFile("mouseselection_true.qml") << 50 << 40 << "9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
-
- QTest::newRow("on tr align") << testFile("mouseselection_align_tr.qml") << 4 << 9 << "45678" << true << true << 1;
- QTest::newRow("on center align") << testFile("mouseselection_align_center.qml") << 4 << 9 << "45678" << true << true << 1;
- QTest::newRow("on bl align") << testFile("mouseselection_align_bl.qml") << 4 << 9 << "45678" << true << true << 1;
+ QTest::newRow("on") << testFileUrl("mouseselection_true.qml") << 4 << 9 << "45678" << true << true << 1;
+ QTest::newRow("off") << testFileUrl("mouseselection_false.qml") << 4 << 9 << QString() << true << true << 1;
+ QTest::newRow("default") << testFileUrl("mouseselectionmode_default.qml") << 4 << 9 << "45678" << true << true << 1;
+ QTest::newRow("off word selection") << testFileUrl("mouseselection_false_words.qml") << 4 << 9 << QString() << true << true << 1;
+ QTest::newRow("on word selection (4,9)") << testFileUrl("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << true << true << 1;
+
+ QTest::newRow("on unfocused") << testFileUrl("mouseselection_true.qml") << 4 << 9 << "45678" << false << false << 1;
+ QTest::newRow("on word selection (4,9) unfocused") << testFileUrl("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << false << 1;
+
+ QTest::newRow("on focus on press") << testFileUrl("mouseselection_true.qml") << 4 << 9 << "45678" << false << true << 1;
+ QTest::newRow("on word selection (4,9) focus on press") << testFileUrl("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << true << 1;
+
+ QTest::newRow("on word selection (2,13)") << testFileUrl("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+ QTest::newRow("on word selection (2,30)") << testFileUrl("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+ QTest::newRow("on word selection (9,13)") << testFileUrl("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+ QTest::newRow("on word selection (9,30)") << testFileUrl("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+ QTest::newRow("on word selection (13,2)") << testFileUrl("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+ QTest::newRow("on word selection (20,2)") << testFileUrl("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+ QTest::newRow("on word selection (12,9)") << testFileUrl("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+ QTest::newRow("on word selection (30,9)") << testFileUrl("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+
+ QTest::newRow("on double click (4,9)") << testFileUrl("mouseselection_true.qml") << 4 << 9 << "0123456789" << true << true << 2;
+ QTest::newRow("on double click (2,13)") << testFileUrl("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+ QTest::newRow("on double click (2,30)") << testFileUrl("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+ QTest::newRow("on double click (9,13)") << testFileUrl("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+ QTest::newRow("on double click (9,30)") << testFileUrl("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+ QTest::newRow("on double click (13,2)") << testFileUrl("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+ QTest::newRow("on double click (20,2)") << testFileUrl("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+ QTest::newRow("on double click (12,9)") << testFileUrl("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+ QTest::newRow("on double click (30,9)") << testFileUrl("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+
+ QTest::newRow("on triple click (4,9)") << testFileUrl("mouseselection_true.qml") << 4 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (2,13)") << testFileUrl("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (2,30)") << testFileUrl("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (9,13)") << testFileUrl("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (9,30)") << testFileUrl("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (13,2)") << testFileUrl("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (20,2)") << testFileUrl("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (12,9)") << testFileUrl("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (30,9)") << testFileUrl("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+
+ QTest::newRow("on triple click (2,40)") << testFileUrl("mouseselection_true.qml") << 2 << 40 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n" << true << true << 3;
+ QTest::newRow("on triple click (2,50)") << testFileUrl("mouseselection_true.qml") << 2 << 50 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+ QTest::newRow("on triple click (25,40)") << testFileUrl("mouseselection_true.qml") << 25 << 40 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n" << true << true << 3;
+ QTest::newRow("on triple click (25,50)") << testFileUrl("mouseselection_true.qml") << 25 << 50 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+ QTest::newRow("on triple click (40,25)") << testFileUrl("mouseselection_true.qml") << 40 << 25 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n" << true << true << 3;
+ QTest::newRow("on triple click (40,50)") << testFileUrl("mouseselection_true.qml") << 40 << 50 << "9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+ QTest::newRow("on triple click (50,25)") << testFileUrl("mouseselection_true.qml") << 50 << 25 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+ QTest::newRow("on triple click (50,40)") << testFileUrl("mouseselection_true.qml") << 50 << 40 << "9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+
+ QTest::newRow("on tr align") << testFileUrl("mouseselection_align_tr.qml") << 4 << 9 << "45678" << true << true << 1;
+ QTest::newRow("on center align") << testFileUrl("mouseselection_align_center.qml") << 4 << 9 << "45678" << true << true << 1;
+ QTest::newRow("on bl align") << testFileUrl("mouseselection_align_bl.qml") << 4 << 9 << "45678" << true << true << 1;
}
void tst_qquicktextedit::mouseSelection()
{
- QFETCH(QString, qmlfile);
+ QFETCH(QUrl, qmlfile);
QFETCH(int, from);
QFETCH(int, to);
QFETCH(QString, selectedText);
@@ -2160,13 +2165,8 @@ void tst_qquicktextedit::mouseSelection()
QFETCH(bool, focusOnPress);
QFETCH(int, clicks);
- QQuickView window(QUrl::fromLocalFile(qmlfile));
-
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
-
- QVERIFY(window.rootObject() != nullptr);
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, qmlfile));
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(textEditObject != nullptr);
@@ -2201,15 +2201,8 @@ void tst_qquicktextedit::mouseSelection()
void tst_qquicktextedit::dragMouseSelection()
{
- QString qmlfile = testFile("mouseselection_true.qml");
-
- QQuickView window(QUrl::fromLocalFile(qmlfile));
-
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
-
- QVERIFY(window.rootObject() != nullptr);
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("mouseselection_true.qml")));
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(textEditObject != nullptr);
@@ -2220,7 +2213,6 @@ void tst_qquicktextedit::dragMouseSelection()
QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x1,y));
QTest::mouseMove(&window, QPoint(x2, y));
QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x2,y));
- QTest::qWait(300);
QString str1;
QTRY_VERIFY((str1 = textEditObject->selectedText()).size() > 3);
@@ -2230,7 +2222,6 @@ void tst_qquicktextedit::dragMouseSelection()
QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x1,y));
QTest::mouseMove(&window, QPoint(x2, y));
QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x2,y));
- QTest::qWait(300);
QString str2;
QTRY_VERIFY((str2 = textEditObject->selectedText()).size() > 3);
@@ -2240,29 +2231,25 @@ void tst_qquicktextedit::dragMouseSelection()
void tst_qquicktextedit::mouseSelectionMode_data()
{
- QTest::addColumn<QString>("qmlfile");
+ QTest::addColumn<QUrl>("qmlfile");
QTest::addColumn<bool>("selectWords");
// import installed
- QTest::newRow("SelectWords") << testFile("mouseselectionmode_words.qml") << true;
- QTest::newRow("SelectCharacters") << testFile("mouseselectionmode_characters.qml") << false;
- QTest::newRow("default") << testFile("mouseselectionmode_default.qml") << false;
+ QTest::newRow("SelectWords") << testFileUrl("mouseselectionmode_words.qml") << true;
+ QTest::newRow("SelectCharacters") << testFileUrl("mouseselectionmode_characters.qml") << false;
+ QTest::newRow("default") << testFileUrl("mouseselectionmode_default.qml") << false;
}
void tst_qquicktextedit::mouseSelectionMode()
{
- QFETCH(QString, qmlfile);
+ QFETCH(QUrl, qmlfile);
QFETCH(bool, selectWords);
- QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
- QQuickView window(QUrl::fromLocalFile(qmlfile));
+ const QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, qmlfile));
- QVERIFY(window.rootObject() != nullptr);
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(textEditObject != nullptr);
textEditObject->setSelectByMouse(true);
@@ -2372,8 +2359,6 @@ void tst_qquicktextedit::selectByKeyboard()
#if QT_CONFIG(shortcut)
-Q_DECLARE_METATYPE(QKeySequence::StandardKey)
-
void tst_qquicktextedit::keyboardSelection_data()
{
QTest::addColumn<QString>("text");
@@ -2433,27 +2418,19 @@ void tst_qquicktextedit::keyboardSelection()
QFETCH(QKeySequence::StandardKey, standardKey);
QFETCH(QString, selectedText);
- QQmlComponent component(&engine);
- component.setData("import QtQuick 2.1\n TextEdit { focus: true }", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(object.data());
- QVERIFY(edit);
-
- edit->setText(text);
- edit->setSelectByKeyboard(selectByKeyboard);
- edit->setReadOnly(readOnly);
- edit->setCursorPosition(cursorPosition);
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("focusByDefault.qml")));
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(window.rootObject());
+ QVERIFY(textEdit->hasActiveFocus());
- QQuickWindow window;
- edit->setParentItem(window.contentItem());
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(edit->hasActiveFocus());
+ textEdit->setText(text);
+ textEdit->setSelectByKeyboard(selectByKeyboard);
+ textEdit->setReadOnly(readOnly);
+ textEdit->setCursorPosition(cursorPosition);
simulateKeys(&window, standardKey);
- QCOMPARE(edit->selectedText(), selectedText);
+ QCOMPARE(textEdit->selectedText(), selectedText);
}
#endif // QT_CONFIG(shortcut)
@@ -2484,11 +2461,8 @@ void tst_qquicktextedit::renderType()
void tst_qquicktextedit::inputMethodHints()
{
- QQuickView window(testFileUrl("inputmethodhints.qml"));
- window.show();
- window.requestActivate();
-
- QVERIFY(window.rootObject() != nullptr);
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("inputmethodhints.qml")));
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(textEditObject != nullptr);
QVERIFY(textEditObject->inputMethodHints() & Qt::ImhNoPredictiveText);
@@ -2523,11 +2497,8 @@ void tst_qquicktextedit::positionAt()
QFETCH(QQuickTextEdit::HAlignment, horizontalAlignment);
QFETCH(QQuickTextEdit::VAlignment, verticalAlignment);
- QQuickView window(testFileUrl("positionAt.qml"));
- QVERIFY(window.rootObject() != nullptr);
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("positionAt.qml")));
QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(texteditObject != nullptr);
@@ -2658,13 +2629,8 @@ void tst_qquicktextedit::linkHover()
void tst_qquicktextedit::linkInteraction()
{
- QQuickView window(testFileUrl("linkInteraction.qml"));
- QVERIFY(window.rootObject() != nullptr);
- QQuickVisualTestUtils::centerOnScreen(&window);
- QQuickVisualTestUtils::moveMouseAway(&window);
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("linkInteraction.qml")));
QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(texteditObject != nullptr);
@@ -2721,11 +2687,11 @@ void tst_qquicktextedit::cursorDelegate_data()
void tst_qquicktextedit::cursorDelegate()
{
QFETCH(QUrl, source);
- QQuickView view(source);
- view.show();
- view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
- QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
+
+ const int doubleClickInterval = qApp->styleHints()->mouseDoubleClickInterval();
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, source));
+ QQuickTextEdit *textEditObject = window.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
QVERIFY(textEditObject != nullptr);
// Delegate creation is deferred until focus in or cursor visibility is forced.
QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
@@ -2747,9 +2713,8 @@ void tst_qquicktextedit::cursorDelegate()
textEditObject->setSelectByMouse(true);
textEditObject->setCursorPosition(0);
const QPoint point1 = textEditObject->positionToRectangle(5).center().toPoint();
- QTest::qWait(400); //ensure this isn't treated as a double-click
- QTest::mouseClick(&view, Qt::LeftButton, Qt::NoModifier, point1);
- QTest::qWait(50);
+ QTest::qWait(doubleClickInterval + 1); // ensure this isn't treated as a double-click
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, point1);
QTRY_VERIFY(textEditObject->cursorPosition() != 0);
QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
@@ -2757,29 +2722,26 @@ void tst_qquicktextedit::cursorDelegate()
// Test delegate gets moved on mouse drag
textEditObject->setCursorPosition(0);
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, view.mapToGlobal(point2),
+ QTest::qWait(doubleClickInterval + 1);
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, point1);
+ QMouseEvent mv(QEvent::MouseMove, point2, window.mapToGlobal(point2),
Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QGuiApplication::sendEvent(&view, &mv);
- QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, point2);
- QTest::qWait(50);
+ QGuiApplication::sendEvent(&window, &mv);
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, point2);
QTRY_COMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
textEditObject->setReadOnly(true);
textEditObject->setCursorPosition(0);
- QTest::qWait(400); //ensure this isn't treated as a double-click
- QTest::mouseClick(&view, Qt::LeftButton, Qt::NoModifier, textEditObject->positionToRectangle(5).center().toPoint());
- QTest::qWait(50);
+ QTest::qWait(doubleClickInterval + 1);
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, textEditObject->positionToRectangle(5).center().toPoint());
QTRY_VERIFY(textEditObject->cursorPosition() != 0);
QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
textEditObject->setCursorPosition(0);
- QTest::qWait(400); //ensure this isn't treated as a double-click
- QTest::mouseClick(&view, Qt::LeftButton, Qt::NoModifier, textEditObject->positionToRectangle(5).center().toPoint());
- QTest::qWait(50);
+ QTest::qWait(doubleClickInterval + 1);
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, textEditObject->positionToRectangle(5).center().toPoint());
QTRY_VERIFY(textEditObject->cursorPosition() != 0);
QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
@@ -2793,7 +2755,7 @@ void tst_qquicktextedit::cursorDelegate()
// Delegate moved when text is entered
textEditObject->setText(QString());
for (int i = 0; i < 20; ++i) {
- QTest::keyClick(&view, Qt::Key_A);
+ QTest::keyClick(&window, Qt::Key_A);
QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
}
@@ -2863,11 +2825,10 @@ void tst_qquicktextedit::cursorVisible()
edit.componentComplete();
QSignalSpy spy(&edit, SIGNAL(cursorVisibleChanged(bool)));
- QQuickView view(testFileUrl("cursorVisible.qml"));
- view.show();
- view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
- QCOMPARE(&view, qGuiApp->focusWindow());
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("cursorVisible.qml")));
+
+ QCOMPARE(qGuiApp->focusWindow(), &window);
QCOMPARE(edit.isCursorVisible(), false);
@@ -2883,7 +2844,7 @@ void tst_qquicktextedit::cursorVisible()
QCOMPARE(edit.isCursorVisible(), false);
QCOMPARE(spy.size(), 2);
- edit.setParentItem(view.rootObject());
+ edit.setParentItem(window.rootObject());
QCOMPARE(edit.isCursorVisible(), true);
QCOMPARE(spy.size(), 3);
@@ -2903,8 +2864,8 @@ void tst_qquicktextedit::cursorVisible()
QCOMPARE(edit.isCursorVisible(), false);
QCOMPARE(spy.size(), 6);
- view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
+ window.requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QCOMPARE(edit.isCursorVisible(), true);
QCOMPARE(spy.size(), 7);
@@ -3008,11 +2969,9 @@ void tst_qquicktextedit::delegateLoading()
void tst_qquicktextedit::cursorDelegateHeight()
{
- QQuickView view(testFileUrl("cursorHeight.qml"));
- view.show();
- view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
- QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("cursorHeight.qml")));
+ QQuickTextEdit *textEditObject = window.rootObject()->findChild<QQuickTextEdit*>();
QVERIFY(textEditObject);
// Delegate creation is deferred until focus in or cursor visibility is forced.
QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
@@ -3049,12 +3008,8 @@ the extent of the text, then they should ignore the keys.
*/
void tst_qquicktextedit::navigation()
{
- QQuickView window(testFileUrl("navigation.qml"));
- window.show();
- window.requestActivate();
-
- QVERIFY(window.rootObject() != nullptr);
-
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("navigation.qml")));
QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
QVERIFY(input != nullptr);
@@ -3200,13 +3155,8 @@ void tst_qquicktextedit::middleClickPaste()
if (!PlatformQuirks::isClipboardAvailable())
QSKIP("This machine doesn't support the clipboard");
- QQuickView window(testFileUrl("mouseselection_true.qml"));
-
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
-
- QVERIFY(window.rootObject() != nullptr);
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("mouseselection_true.qml")));
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(textEditObject != nullptr);
@@ -3236,9 +3186,8 @@ void tst_qquicktextedit::middleClickPaste()
void tst_qquicktextedit::readOnly()
{
- QQuickView window(testFileUrl("readOnly.qml"));
- window.show();
- window.requestActivate();
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("readOnly.qml")));
QVERIFY(window.rootObject() != nullptr);
@@ -3278,11 +3227,9 @@ void tst_qquicktextedit::inFlickableMouse()
QFETCH(int, expectFlickingAfter);
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
- QQuickView view(testFileUrl("inFlickable.qml"));
- view.show();
- view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
- QQuickFlickable *flick = qobject_cast<QQuickFlickable *>(view.rootObject());
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("inFlickable.qml")));
+ QQuickFlickable *flick = qobject_cast<QQuickFlickable *>(window.rootObject());
QVERIFY(flick);
QQuickTextEdit *edit = flick->findChild<QQuickTextEdit*>("text");
QVERIFY(edit);
@@ -3291,7 +3238,7 @@ void tst_qquicktextedit::inFlickableMouse()
// flick with mouse
QPoint p(10, 100);
- QTest::mousePress(&view, Qt::LeftButton, {}, p);
+ QTest::mousePress(&window, Qt::LeftButton, {}, p);
QObject *pressGrabber = QPointingDevicePrivate::get(QPointingDevice::primaryPointingDevice())->firstPointExclusiveGrabber();
// even if TextEdit is readonly, it still grabs on press. But not if it's disabled.
if (enabled)
@@ -3302,14 +3249,14 @@ void tst_qquicktextedit::inFlickableMouse()
// after a couple of events, Flickable steals the grab and starts moving
for (; i < 4 && !flick->isMoving(); ++i) {
p -= QPoint(0, dragThreshold);
- QTest::mouseMove(&view, p);
+ QTest::mouseMove(&window, p);
}
QCOMPARE(flick->isMoving(), bool(expectFlickingAfter));
if (expectFlickingAfter) {
qCDebug(lcTests) << "flickable started moving after" << i << "moves, when we got to" << p;
QCOMPARE(i, expectFlickingAfter);
}
- QTest::mouseRelease(&view, Qt::LeftButton, {}, p);
+ QTest::mouseRelease(&window, Qt::LeftButton, {}, p);
}
void tst_qquicktextedit::inFlickableTouch_data()
@@ -3384,18 +3331,11 @@ bool tst_qquicktextedit::isMainFontFixed()
return ret;
}
-bool tst_qquicktextedit::hasWindowActivation()
-{
- return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation));
-}
-
void tst_qquicktextedit::textInput()
{
- QQuickView view(testFileUrl("inputMethodEvent.qml"));
- view.show();
- view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
- QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("inputMethodEvent.qml")));
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(edit);
QVERIFY(edit->hasActiveFocus());
@@ -3444,11 +3384,9 @@ void tst_qquicktextedit::inputMethodUpdate()
QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
inputMethodPrivate->testContext = &platformInputContext;
- QQuickView view(testFileUrl("inputMethodEvent.qml"));
- view.show();
- view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
- QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("inputMethodEvent.qml")));
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(edit);
QVERIFY(edit->hasActiveFocus());
@@ -3534,12 +3472,10 @@ void tst_qquicktextedit::openInputPanel()
QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
inputMethodPrivate->testContext = &platformInputContext;
- QQuickView view(testFileUrl("openInputPanel.qml"));
- view.showNormal();
- view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("openInputPanel.qml")));
- QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(edit);
// check default values
@@ -3550,28 +3486,28 @@ void tst_qquicktextedit::openInputPanel()
QCOMPARE(qApp->inputMethod()->isVisible(), false);
// input panel should open on focus
- QPoint centerPoint(view.width()/2, view.height()/2);
+ QPoint centerPoint(window.width()/2, window.height()/2);
Qt::KeyboardModifiers noModifiers = Qt::NoModifier;
- QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QVERIFY(edit->hasActiveFocus());
QCOMPARE(qApp->focusObject(), edit);
QCOMPARE(qApp->inputMethod()->isVisible(), true);
- QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mouseRelease(&window, Qt::LeftButton, noModifiers, centerPoint);
// input panel should be re-opened when pressing already focused TextEdit
qApp->inputMethod()->hide();
QCOMPARE(qApp->inputMethod()->isVisible(), false);
QVERIFY(edit->hasActiveFocus());
- QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QCOMPARE(qApp->inputMethod()->isVisible(), true);
- QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mouseRelease(&window, Qt::LeftButton, noModifiers, centerPoint);
// input panel should stay visible if focus is lost to another text editor
QSignalSpy inputPanelVisibilitySpy(qApp->inputMethod(), SIGNAL(visibleChanged()));
QQuickTextEdit anotherEdit;
- anotherEdit.setParentItem(view.rootObject());
+ anotherEdit.setParentItem(window.rootObject());
anotherEdit.setFocus(true);
QCOMPARE(qApp->inputMethod()->isVisible(), true);
QCOMPARE(qApp->focusObject(), qobject_cast<QObject*>(&anotherEdit));
@@ -3579,7 +3515,7 @@ void tst_qquicktextedit::openInputPanel()
anotherEdit.setFocus(false);
QVERIFY(qApp->focusObject() != &anotherEdit);
- QCOMPARE(view.activeFocusItem(), view.contentItem());
+ QCOMPARE(window.activeFocusItem(), window.contentItem());
anotherEdit.setFocus(true);
qApp->inputMethod()->hide();
@@ -3588,8 +3524,8 @@ void tst_qquicktextedit::openInputPanel()
edit->setReadOnly(true);
edit->setFocus(true);
QCOMPARE(qApp->inputMethod()->isVisible(), false);
- QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
- QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mouseRelease(&window, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QCOMPARE(qApp->inputMethod()->isVisible(), false);
@@ -3598,8 +3534,8 @@ void tst_qquicktextedit::openInputPanel()
edit->setFocus(false);
edit->setFocus(true);
QCOMPARE(qApp->inputMethod()->isVisible(), false);
- QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
- QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mouseRelease(&window, Qt::LeftButton, noModifiers, centerPoint);
QCOMPARE(qApp->inputMethod()->isVisible(), false);
inputMethodPrivate->testContext = nullptr;
@@ -3763,16 +3699,16 @@ void tst_qquicktextedit::largeTextObservesViewport_data()
// by default, the root item acts as the viewport:
// QQuickTextEdit doesn't populate lines of text beyond the bottom of the window
// cursor position 1000 is on line 121
- QTest::newRow("default plain text") << text << QQuickTextEdit::PlainText << false << 1000 << 0
- << 1 << 118 << 142 << 2400 << 3000;
+ QTest::newRow("default plain text") << text << QQuickTextEdit::PlainText << false << 1000 << 2
+ << 3 << 118 << 144 << 2150 << 3000;
// make the rectangle into a viewport item, and move the text upwards:
// QQuickTextEdit doesn't populate lines of text beyond the bottom of the viewport rectangle
QTest::newRow("clipped plain text") << text << QQuickTextEdit::PlainText << true << 1000 << 0
- << 1 << 123 << 137 << 2550 << 3000;
+ << 3 << 123 << 137 << 2200 << 3000;
// scroll backwards
QTest::newRow("scroll backwards in plain text") << text << QQuickTextEdit::PlainText << true << 1000 << 600
- << 1 << 93 << 108 << 1475 << 2300;
+ << 3 << 91 << 108 << 1475 << 2300;
{
QStringList lines;
@@ -3796,20 +3732,20 @@ void tst_qquicktextedit::largeTextObservesViewport_data()
// by default, the root item acts as the viewport:
// QQuickTextEdit doesn't populate blocks beyond the bottom of the window
QTest::newRow("default styled text") << text << QQuickTextEdit::RichText << false << 1000 << 0
- << 1 << 124 << 139 << 3900 << 4500;
+ << 3 << 122 << 139 << 3600 << 4500;
// make the rectangle into a viewport item, and move the text upwards:
// QQuickTextEdit doesn't populate blocks that don't intersect the viewport rectangle
QTest::newRow("clipped styled text") << text << QQuickTextEdit::RichText << true << 1000 << 0
- << 1 << 127 << 136 << 4000 << 4360;
+ << 3 << 127 << 136 << 3700 << 4360;
// get the "chapter 2" heading into the viewport
QTest::newRow("heading visible") << text << QQuickTextEdit::RichText << true << 800 << 0
- << 1 << 105 << 113 << 3300 << 3600;
+ << 3 << 105 << 113 << 3050 << 3600;
// get the "chapter 2" heading into the viewport, and then scroll backwards
QTest::newRow("scroll backwards") << text << QQuickTextEdit::RichText << true << 800 << 20
- << 1 << 104 << 113 << 3200 << 3600;
+ << 3 << 104 << 113 << 3000 << 3600;
// get the "chapter 2" heading into the viewport, and then scroll forwards
QTest::newRow("scroll forwards") << text << QQuickTextEdit::RichText << true << 800 << -50
- << 1 << 106 << 115 << 3300 << 3670;
+ << 3 << 106 << 115 << 3000 << 3670;
}
void tst_qquicktextedit::largeTextObservesViewport()
@@ -3881,14 +3817,49 @@ void tst_qquicktextedit::largeTextObservesViewport()
QCOMPARE(textPriv->cursorItem->isVisible(), textPriv->renderedRegion.intersects(textItem->cursorRectangle()));
}
+void tst_qquicktextedit::largeTextSelection()
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("qtConfigureHelp.qml")));
+ NodeCheckerTextEdit *textItem = qmlobject_cast<NodeCheckerTextEdit *>(window.rootObject());
+ QVERIFY(textItem);
+ QTRY_VERIFY(textItem->sortedLinePositions.size() > 0);
+ const auto sortedLinePositions = textItem->sortedLinePositions;
+
+ QQuickTextEditPrivate *textPriv = QQuickTextEditPrivate::get(textItem);
+ QSignalSpy renderSpy(&window, &QQuickWindow::afterRendering);
+ if (lcTests().isDebugEnabled())
+ QTest::qWait(500); // for visual check; not needed in CI
+
+ const int renderCount = renderSpy.size();
+ textItem->setCursorPosition(200);
+ textItem->moveCursorSelection(220);
+ QTRY_COMPARE_GT(renderSpy.size(), renderCount);
+
+ if (lcTests().isDebugEnabled())
+ QTest::qWait(500); // for visual check; not needed in CI
+
+ qCDebug(lcTests) << "TextEdit's nodes" << textPriv->textNodeMap;
+ qCDebug(lcTests) << "font" << textItem->font() << "line positions"
+ << textItem->sortedLinePositions << "expected" << sortedLinePositions;
+
+ const bool eachTextNodeRenderedOnlyOnce = [textItem]() -> bool {
+ for (auto i = 1; i < textItem->sortedLinePositions.count(); ++i)
+ if (textItem->sortedLinePositions[i - 1] == textItem->sortedLinePositions[i])
+ return false;
+ return true;
+ }();
+ QVERIFY(eachTextNodeRenderedOnlyOnce);
+}
+
void tst_qquicktextedit::renderingAroundSelection()
{
QQuickView window;
QVERIFY(QQuickTest::showView(window, testFileUrl("threeLines.qml")));
NodeCheckerTextEdit *textItem = qmlobject_cast<NodeCheckerTextEdit*>(window.rootObject());
QVERIFY(textItem);
- QTRY_VERIFY(textItem->linePositions.size() > 0);
- const auto linePositions = textItem->linePositions;
+ QTRY_VERIFY(textItem->sortedLinePositions.size() > 0);
+ const auto sortedLinePositions = textItem->sortedLinePositions;
const int lastLinePosition = textItem->lastLinePosition;
QQuickTextEditPrivate *textPriv = QQuickTextEditPrivate::get(textItem);
QSignalSpy renderSpy(&window, &QQuickWindow::afterRendering);
@@ -3910,27 +3881,120 @@ void tst_qquicktextedit::renderingAroundSelection()
QTest::qWait(500); // for visual check; not needed in CI
qCDebug(lcTests) << "TextEdit's nodes" << textPriv->textNodeMap;
- qCDebug(lcTests) << "font" << textItem->font() << "line positions" << textItem->linePositions << "should be" << linePositions;
+ qCDebug(lcTests) << "font" << textItem->font() << "line positions" << textItem->sortedLinePositions << "should be" << sortedLinePositions;
QCOMPARE(textItem->lastLinePosition, lastLinePosition);
- QTRY_COMPARE(textItem->linePositions, linePositions);
+ QTRY_COMPARE(textItem->sortedLinePositions, sortedLinePositions);
}
-void tst_qquicktextedit::signal_editingfinished()
-{
- QQuickView *window = new QQuickView(nullptr);
- window->setBaseSize(QSize(800,600));
+struct OffsetAndExpectedBlocks {
+ int tableIndex; // which nested frame
+ qreal tableOffset; // fraction of that frame's height to scroll to
+ int minExpectedBlockCount;
- window->setSource(testFileUrl("signal_editingfinished.qml"));
- window->show();
- window->requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(window));
- QCOMPARE(QGuiApplication::focusWindow(), window);
+ OffsetAndExpectedBlocks(int i, qreal o, int c)
+ : tableIndex(i), tableOffset(o), minExpectedBlockCount(c) {}
+};
- QVERIFY(window->rootObject() != nullptr);
+typedef QList<OffsetAndExpectedBlocks> OffsetAndExpectedBlocksList;
+
+void tst_qquicktextedit::largeTextTables_data()
+{
+ QTest::addColumn<int>("tables");
+ QTest::addColumn<int>("tableCols");
+ QTest::addColumn<int>("tableRows");
+ QTest::addColumn<OffsetAndExpectedBlocksList>("steps");
+
+ QTest::newRow("one big table") << 1 << 3 << 70
+ << OffsetAndExpectedBlocksList{
+ OffsetAndExpectedBlocks(1, 0.75, 150),
+ OffsetAndExpectedBlocks(1, 0.5, 150)};
+ QTest::newRow("short tables") << 5 << 3 << 10
+ << OffsetAndExpectedBlocksList{
+ OffsetAndExpectedBlocks(4, 0.75, 35),
+ OffsetAndExpectedBlocks(3, 0.25, 50),
+ OffsetAndExpectedBlocks(2, 0.75, 50)};
+}
+
+void tst_qquicktextedit::largeTextTables() // QTBUG-118636
+{
+ QFETCH(int, tables);
+ QFETCH(int, tableCols);
+ QFETCH(int, tableRows);
+ QFETCH(OffsetAndExpectedBlocksList, steps);
+
+ QStringList lines;
+
+ lines << QLatin1String("<h1>") + QTest::currentDataTag() + "</h1>";
+ for (int t = 0; t < tables; ++t) {
+ if (t > 0)
+ lines << QString("<p>table %1</p>").arg(t);
+ lines << "<table border='1'>";
+ for (int r = 0; r < tableRows; ++r) {
+ lines << " <tr>";
+ for (int c = 0; c < tableCols; ++c)
+ lines << QString(" <td>table %1 cell %2, %3</td>").arg(t).arg(c).arg(r);
+ lines << " </tr>";
+ }
+ lines << "</table>";
+ }
+ lines << "<p>here endeth the tables</p>";
+ QString html = lines.join('\n');
+
+#ifdef DEBUG_WRITE_INPUT
+ QFile f(QLatin1String("/tmp/") + QTest::currentDataTag() + ".html");
+ f.open(QFile::WriteOnly);
+ f.write(html.toUtf8());
+ f.close();
+#endif
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("inFlickable.qml")));
+ QQuickFlickable *flick = qmlobject_cast<QQuickFlickable *>(window.rootObject());
+ QVERIFY(flick);
+ QQuickTextEdit *te = window.rootObject()->findChild<QQuickTextEdit *>();
+ QVERIFY(te);
+ auto *tePriv = QQuickTextEditPrivate::get(te);
+ auto font = te->font();
+ font.setPixelSize(10);
+ te->setFont(font);
+
+ te->setTextFormat(QQuickTextEdit::RichText);
+ te->setText(html);
+ te->setFlag(QQuickItem::ItemObservesViewport); // this isn't "large text", but test viewporting anyway
+
+ QTextDocument *doc = te->textDocument()->textDocument();
+ QList<QTextFrame *> frames = doc->rootFrame()->childFrames();
+ frames.prepend(doc->rootFrame());
+ qCDebug(lcTests) << "blocks" << doc->blockCount() << "chars" << doc->characterCount() << "frames" << frames;
+
+ for (const OffsetAndExpectedBlocks &oeb : steps) {
+ QCOMPARE_GT(frames.size(), oeb.tableIndex);
+ const QTextFrame *textFrame = frames.at(oeb.tableIndex);
+ const QTextCursor top = textFrame->firstCursorPosition();
+ const qreal yTop = te->positionToRectangle(top.position()).top();
+ const QTextCursor bottom = textFrame->lastCursorPosition();
+ const qreal yBottom = te->positionToRectangle(bottom.position()).bottom();
+ const qreal y = yTop + (yBottom - yTop) * oeb.tableOffset;
+ qCDebug(lcTests) << "frame" << textFrame << "goes from pos" << top.position() << "y" << yTop
+ << "to pos" << bottom.position() << "y" << yBottom << "; scrolling to" << y
+ << "which is at" << oeb.tableOffset << "of table height" << (yBottom - yTop);
+ flick->setContentY(y);
+ qCDebug(lcTests) << tePriv->renderedRegion << "rendered blocks" << tePriv->renderedBlockCount << ":"
+ << tePriv->firstBlockInViewport << "to" << tePriv->firstBlockPastViewport;
+ QTRY_COMPARE_GE(tePriv->renderedBlockCount, oeb.minExpectedBlockCount);
+ }
+}
+
+void tst_qquicktextedit::signal_editingfinished()
+{
+ QQuickView window;
+ window.setBaseSize(QSize(800, 600));
+ QVERIFY(QQuickTest::showView(window, testFileUrl("signal_editingfinished.qml")));
+ QCOMPARE(QGuiApplication::focusWindow(), &window);
- QQuickTextEdit *input1 = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window->rootObject()->property("input1")));
+ QQuickTextEdit *input1 = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("input1")));
QVERIFY(input1);
- QQuickTextEdit *input2 = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window->rootObject()->property("input2")));
+ QQuickTextEdit *input2 = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("input2")));
QVERIFY(input2);
QSignalSpy editingFinished1Spy(input1, SIGNAL(editingFinished()));
@@ -3941,7 +4005,7 @@ void tst_qquicktextedit::signal_editingfinished()
{
QKeyEvent key(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1);
- QGuiApplication::sendEvent(window, &key);
+ QGuiApplication::sendEvent(&window, &key);
QVERIFY(key.isAccepted());
QTRY_COMPARE(editingFinished1Spy.size(), 1);
@@ -3957,7 +4021,7 @@ void tst_qquicktextedit::signal_editingfinished()
{
QKeyEvent key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1);
- QGuiApplication::sendEvent(window, &key);
+ QGuiApplication::sendEvent(&window, &key);
QVERIFY(key.isAccepted());
QTRY_COMPARE(editingFinished2Spy.size(), 1);
@@ -4139,12 +4203,10 @@ void tst_qquicktextedit::preeditCursorRectangle()
{
QString preeditText = "super";
- QQuickView view(testFileUrl("inputMethodEvent.qml"));
- view.show();
- view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("inputMethodEvent.qml")));
- QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(edit);
QQuickItem *cursor = edit->findChild<QQuickItem *>("cursor");
@@ -4222,12 +4284,10 @@ void tst_qquicktextedit::inputMethodComposing()
{
QString text = "supercalifragisiticexpialidocious!";
- QQuickView view(testFileUrl("inputContext.qml"));
- view.show();
- view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("inputContext.qml")));
- QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(edit);
QCOMPARE(QGuiApplication::focusObject(), static_cast<QObject *>(edit));
@@ -4338,11 +4398,11 @@ void tst_qquicktextedit::cursorRectangleSize()
{
QFETCH(bool, useCursorDelegate);
- QQuickView *window = new QQuickView(testFileUrl("positionAt.qml"));
- QVERIFY(window->rootObject() != nullptr);
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(window->rootObject());
+ QQuickView window(testFileUrl("positionAt.qml"));
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(window.rootObject());
+ QVERIFY(textEdit);
- QQmlComponent cursorDelegate(window->engine());
+ QQmlComponent cursorDelegate(window.engine());
if (useCursorDelegate) {
cursorDelegate.setData("import QtQuick 2.0\nRectangle { width:10; height:10; }", QUrl());
textEdit->setCursorDelegate(&cursorDelegate);
@@ -4354,9 +4414,9 @@ void tst_qquicktextedit::cursorRectangleSize()
textEdit->setCursorPosition(3);
QVERIFY(textEdit != nullptr);
textEdit->setFocus(true);
- window->show();
- window->requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(window));
+ window.show();
+ window.requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QInputMethodQueryEvent event(Qt::ImCursorRectangle);
qApp->sendEvent(textEdit, &event);
@@ -4381,8 +4441,6 @@ void tst_qquicktextedit::cursorRectangleSize()
// input panel cursorRectangle property and tranformed item cursor rectangle match
QRectF sceneCursorRect = QQuickItemPrivate::get(textEdit)->itemToWindowTransform().mapRect(cursorRectFromItem);
QCOMPARE(sceneCursorRect, qApp->inputMethod()->cursorRectangle());
-
- delete window;
}
void tst_qquicktextedit::getText_data()
@@ -5567,17 +5625,9 @@ void tst_qquicktextedit::undo()
QFETCH(IntList, insertMode);
QFETCH(QStringList, expectedString);
- QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true }";
- QQmlComponent textEditComponent(&engine);
- textEditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != nullptr);
-
- QQuickWindow window;
- textEdit->setParentItem(window.contentItem());
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("focusByDefault.qml")));
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(textEdit->hasActiveFocus());
QVERIFY(!textEdit->canUndo());
@@ -5653,17 +5703,10 @@ void tst_qquicktextedit::redo()
QFETCH(IntList, insertIndex);
QFETCH(QStringList, expectedString);
- QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true }";
- QQmlComponent textEditComponent(&engine);
- textEditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != nullptr);
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("focusByDefault.qml")));
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(window.rootObject());
- QQuickWindow window;
- textEdit->setParentItem(window.contentItem());
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textEdit->hasActiveFocus());
QVERIFY(!textEdit->canUndo());
@@ -5876,17 +5919,10 @@ void tst_qquicktextedit::undo_keypressevents()
QFETCH(KeyList, keys);
QFETCH(QStringList, expectedString);
- QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true }";
- QQmlComponent textEditComponent(&engine);
- textEditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != nullptr);
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("focusByDefault.qml")));
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(window.rootObject());
- QQuickWindow window;
- textEdit->setParentItem(window.contentItem());
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textEdit->hasActiveFocus());
simulateKeys(&window, keys);
@@ -5902,17 +5938,9 @@ void tst_qquicktextedit::undo_keypressevents()
void tst_qquicktextedit::clear()
{
- QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true }";
- QQmlComponent textEditComponent(&engine);
- textEditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != nullptr);
-
- QQuickWindow window;
- textEdit->setParentItem(window.contentItem());
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("focusByDefault.qml")));
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(textEdit->hasActiveFocus());
QSignalSpy spy(textEdit, SIGNAL(canUndoChanged()));
@@ -5993,11 +6021,11 @@ void tst_qquicktextedit::embeddedImages_data()
QTest::newRow("local") << testFileUrl("embeddedImagesLocal.qml") << "";
QTest::newRow("local-error") << testFileUrl("embeddedImagesLocalError.qml")
<< testFileUrl("embeddedImagesLocalError.qml").toString()+":3:1: QML TextEdit: Cannot open: " + testFileUrl("http/notexists.png").toString();
- QTest::newRow("local") << testFileUrl("embeddedImagesLocalRelative.qml") << "";
+ QTest::newRow("local-relative") << testFileUrl("embeddedImagesLocalRelative.qml") << "";
QTest::newRow("remote") << testFileUrl("embeddedImagesRemote.qml") << "";
QTest::newRow("remote-error") << testFileUrl("embeddedImagesRemoteError.qml")
<< testFileUrl("embeddedImagesRemoteError.qml").toString()+":3:1: QML TextEdit: Error transferring {{ServerBaseUrl}}/notexists.png - server replied: Not found";
- QTest::newRow("remote") << testFileUrl("embeddedImagesRemoteRelative.qml") << "";
+ QTest::newRow("remote-relative") << testFileUrl("embeddedImagesRemoteRelative.qml") << "";
}
void tst_qquicktextedit::embeddedImages()
@@ -6015,40 +6043,93 @@ void tst_qquicktextedit::embeddedImages()
QTest::ignoreMessage(QtWarningMsg, error.toLatin1());
QQmlComponent textComponent(&engine, qmlfile);
- QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.beginCreate(engine.rootContext()));
- QVERIFY(textObject != nullptr);
+ QScopedPointer<QQuickTextEdit> textObject(qobject_cast<QQuickTextEdit*>(textComponent.beginCreate(engine.rootContext())));
+ QVERIFY(!textObject.isNull());
const int baseUrlPropertyIndex = textObject->metaObject()->indexOfProperty("serverBaseUrl");
if (baseUrlPropertyIndex != -1) {
QMetaProperty prop = textObject->metaObject()->property(baseUrlPropertyIndex);
- QVERIFY(prop.write(textObject, server.baseUrl().toString()));
+ QVERIFY(prop.write(textObject.get(), server.baseUrl().toString()));
}
textComponent.completeCreate();
- QTRY_COMPARE(QQuickTextEditPrivate::get(textObject)->document->resourcesLoading(), 0);
+ QTRY_COMPARE(textObject->resourcesLoading(), 0);
QPixmap pm(testFile("http/exists.png"));
if (error.isEmpty()) {
- QCOMPARE(textObject->width(), double(pm.width()));
- QCOMPARE(textObject->height(), double(pm.height()));
+ QCOMPARE(textObject->width(), pm.width());
+ QCOMPARE(textObject->height(), pm.height());
} else {
QVERIFY(16 != pm.width()); // check test is effective
- QCOMPARE(textObject->width(), 16.0); // default size of QTextDocument broken image icon
- QCOMPARE(textObject->height(), 16.0);
+ QCOMPARE(textObject->width(), 16); // default size of QTextDocument broken image icon
+ QCOMPARE(textObject->height(), 16);
}
- delete textObject;
+ // QTextDocument images are cached in QTextDocumentPrivate::cachedResources,
+ // so verify that we don't redundantly cache them in QQuickPixmapCache
+ QCOMPARE(QQuickPixmapCache::instance()->m_cache.size(), 0);
}
-void tst_qquicktextedit::emptytags_QTBUG_22058()
+void tst_qquicktextedit::remoteImagesInDocumentSource()
{
- QQuickView window(testFileUrl("qtbug-22058.qml"));
- QVERIFY(window.rootObject() != nullptr);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ server.serveDirectory(testFile("http"));
+ server.serveDirectory(testFile("httpfail"), TestHTTPServer::Disconnect);
+ server.serveDirectory(testFile("httpslow"), TestHTTPServer::Delay);
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
+ QTemporaryDir tmpDir;
+ QVERIFY(tmpDir.isValid());
+ QString tmpPath = tmpDir.filePath("multipleRemoteImages.md");
+ QByteArray markdownBuf;
+ {
+ QFile sf(QQmlFile::urlToLocalFileOrQrc(testFileUrl("multipleRemoteImages.md")));
+ QVERIFY(sf.open(QIODeviceBase::ReadOnly));
+ markdownBuf = sf.readAll();
+ qCDebug(lcTests) << sf.fileName() << "->" << tmpPath
+ << "s/serverBaseUrl/" << server.baseUrl().toString()
+ << "/ in markdown: size" << markdownBuf.size();
+ }
+ markdownBuf.replace("serverBaseUrl", server.baseUrl().toString().toLocal8Bit());
+ {
+ QFile of(tmpPath);
+ QVERIFY(of.open(QIODeviceBase::WriteOnly));
+ QCOMPARE(of.write(markdownBuf), markdownBuf.size());
+ }
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("textEdit.qml")));
+ auto *textEdit = qmlobject_cast<QQuickTextEdit *>(window.rootObject());
+ QVERIFY(textEdit);
+ QQuickTextEditPrivate *priv = QQuickTextEditPrivate::get(textEdit);
+ QSignalSpy implicitHeightChangedSpy(textEdit, &QQuickTextEdit::implicitHeightChanged);
+
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*Protocol \"gopher\" is unknown"));
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*Connection closed")); // httpfail/warning.png
+ textEdit->setTextFormat(QQuickTextEdit::MarkdownText);
+ textEdit->textDocument()->setSource(QUrl::fromLocalFile(tmpPath));
+
+ // the document gets loaded first, then the resources
+ QTRY_COMPARE(textEdit->textDocument()->status(), QQuickTextDocument::Status::Loaded);
+ const qreal implicitHeight = textEdit->implicitHeight();
+
+ // all resource-loading jobs complete or fail eventually
+ QTRY_COMPARE(priv->pixmapsInProgress.size(), 0);
+
+ // after httpslow/turtle.svg loads, implicitHeight increases
+ QCOMPARE(implicitHeightChangedSpy.size(), 2);
+ QCOMPARE_GT(textEdit->implicitHeight(), implicitHeight);
+
+ // QTextDocument images are cached in QTextDocumentPrivate::cachedResources,
+ // so verify that we don't redundantly cache them in QQuickPixmapCache
+ QCOMPARE(QQuickPixmapCache::instance()->m_cache.size(), 0);
+}
+
+void tst_qquicktextedit::emptytags_QTBUG_22058()
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("qtbug-22058.qml")));
QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("inputField")));
QVERIFY(input->hasActiveFocus());
@@ -6235,31 +6316,25 @@ void tst_qquicktextedit::QTBUG_51115_readOnlyResetsSelection()
void tst_qquicktextedit::keys_shortcutoverride()
{
// Tests that QML TextEdit receives Keys.onShortcutOverride (QTBUG-68711)
- QQuickView view;
- view.setSource(testFileUrl("keys_shortcutoverride.qml"));
- view.show();
- view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
- QObject *root = view.rootObject();
- QVERIFY(root);
-
- QQuickTextEdit *textEdit = root->findChild<QQuickTextEdit*>();
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("keys_shortcutoverride.qml")));
+ QQuickTextEdit *textEdit = window.rootObject()->findChild<QQuickTextEdit*>();
QVERIFY(textEdit);
- QQuickRectangle *rectangle = root->findChild<QQuickRectangle*>(QLatin1String("rectangle"));
+ QQuickRectangle *rectangle = window.rootObject()->findChild<QQuickRectangle*>(QLatin1String("rectangle"));
QVERIFY(rectangle);
// Precondition: check if its not already changed
- QCOMPARE(root->property("who").value<QString>(), QLatin1String("nobody"));
+ QCOMPARE(window.rootObject()->property("who").value<QString>(), QLatin1String("nobody"));
// send Key_Escape to the Rectangle
QVERIFY(rectangle->hasActiveFocus());
- QTest::keyPress(&view, Qt::Key_Escape);
- QCOMPARE(root->property("who").value<QString>(), QLatin1String("Rectangle"));
+ QTest::keyPress(&window, Qt::Key_Escape);
+ QCOMPARE(window.rootObject()->property("who").value<QString>(), QLatin1String("Rectangle"));
// send Key_Escape to TextEdit
textEdit->setFocus(true);
- QTest::keyPress(&view, Qt::Key_Escape);
- QCOMPARE(root->property("who").value<QString>(), QLatin1String("TextEdit"));
+ QTest::keyPress(&window, Qt::Key_Escape);
+ QCOMPARE(window.rootObject()->property("who").value<QString>(), QLatin1String("TextEdit"));
}
void tst_qquicktextedit::transparentSelectionColor()
@@ -6267,18 +6342,13 @@ void tst_qquicktextedit::transparentSelectionColor()
if (QGuiApplication::platformName() == QLatin1String("minimal"))
QSKIP("Skipping due to grabWindow not functional on minimal platforms");
- QQuickView view;
- view.setSource(testFileUrl("transparentSelectionColor.qml"));
- view.show();
- QVERIFY(QTest::qWaitForWindowExposed(&view));
- QObject *root = view.rootObject();
- QVERIFY(root);
-
- QQuickTextEdit *textEdit = root->findChild<QQuickTextEdit *>();
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("transparentSelectionColor.qml")));
+ QQuickTextEdit *textEdit = window.rootObject()->findChild<QQuickTextEdit *>();
QVERIFY(textEdit);
textEdit->selectAll();
- QImage img = view.grabWindow();
+ QImage img = window.grabWindow();
QCOMPARE(img.isNull(), false);
QColor color = img.pixelColor(int(textEdit->width() / 2), int(textEdit->height()) / 2);
@@ -6289,11 +6359,9 @@ void tst_qquicktextedit::transparentSelectionColor()
void tst_qquicktextedit::keyEventPropagation()
{
- QQuickView view;
- view.setSource(testFileUrl("keyEventPropagation.qml"));
- view.show();
- QVERIFY(QTest::qWaitForWindowExposed(&view));
- QObject *root = view.rootObject();
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("keyEventPropagation.qml")));
+ QObject *root = window.rootObject();
QVERIFY(root);
QSignalSpy downSpy(root, SIGNAL(keyDown(int)));
@@ -6301,7 +6369,7 @@ void tst_qquicktextedit::keyEventPropagation()
QQuickTextEdit *textEdit = root->findChild<QQuickTextEdit *>();
QVERIFY(textEdit->hasActiveFocus());
- simulateKey(&view, Qt::Key_Back);
+ simulateKey(&window, Qt::Key_Back);
QCOMPARE(downSpy.size(), 1);
QCOMPARE(upSpy.size(), 1);
auto downKey = downSpy.takeFirst();
@@ -6309,7 +6377,7 @@ void tst_qquicktextedit::keyEventPropagation()
QCOMPARE(downKey.at(0).toInt(), Qt::Key_Back);
QCOMPARE(upKey.at(0).toInt(), Qt::Key_Back);
- simulateKey(&view, Qt::Key_Shift);
+ simulateKey(&window, Qt::Key_Shift);
QCOMPARE(downSpy.size(), 1);
QCOMPARE(upSpy.size(), 1);
downKey = downSpy.takeFirst();
@@ -6317,11 +6385,11 @@ void tst_qquicktextedit::keyEventPropagation()
QCOMPARE(downKey.at(0).toInt(), Qt::Key_Shift);
QCOMPARE(upKey.at(0).toInt(), Qt::Key_Shift);
- simulateKey(&view, Qt::Key_A);
+ simulateKey(&window, Qt::Key_A);
QCOMPARE(downSpy.size(), 0);
QCOMPARE(upSpy.size(), 0);
- simulateKey(&view, Qt::Key_Right);
+ simulateKey(&window, Qt::Key_Right);
QCOMPARE(downSpy.size(), 0);
QCOMPARE(upSpy.size(), 1);
upKey = upSpy.takeFirst();
@@ -6447,8 +6515,8 @@ void tst_qquicktextedit::touchscreenDoesNotSelect()
void tst_qquicktextedit::touchscreenSetsFocusAndMovesCursor()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
+
QQuickView window;
QVERIFY(QQuickTest::showView(window, testFileUrl("twoInAColumn.qml")));
window.requestActivate();
@@ -6488,6 +6556,169 @@ void tst_qquicktextedit::touchscreenSetsFocusAndMovesCursor()
QVERIFY(top->selectedText().isEmpty());
}
+void tst_qquicktextedit::longPressInputMethod() // QTBUG-115004
+{
+ QQuickView window;
+ window.setMinimumWidth(200);
+ window.setMinimumHeight(100);
+ QVERIFY(QQuickTest::showView(window, testFileUrl("positionAt.qml")));
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(window.rootObject());
+ QVERIFY(edit);
+
+ // Realistically there are touch events. But QQuickTextEdit doesn't handle them yet;
+ // so we only test the synth-mouse events for now.
+ QPoint pos = edit->positionToRectangle(20).center().toPoint(); // in the word "pi|ece"
+ QTest::mousePress(&window, Qt::LeftButton, {}, pos);
+
+ // Simulate input method events as seen on Android during long-press
+ {
+ QInputMethodEvent imEvent({}, QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 20, 0, {}));
+ QCoreApplication::sendEvent(edit, &imEvent);
+ }
+ {
+ QInputMethodEvent imEvent({}, QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, {})
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 13, -5, {}));
+ QCoreApplication::sendEvent(edit, &imEvent);
+ }
+
+ // Release later => long press
+ QTest::mouseRelease(&window, Qt::LeftButton, {}, pos, 1500);
+
+ QTRY_COMPARE(edit->selectedText(), "piece");
+}
+
+void tst_qquicktextedit::rtlAlignmentInColumnLayout_QTBUG_112858()
+{
+ QQuickView window(testFileUrl("qtbug-112858.qml"));
+ QVERIFY(window.rootObject() != nullptr);
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ QQuickTextEdit *edit = window.rootObject()->findChild<QQuickTextEdit *>();
+ QVERIFY(edit != nullptr);
+
+ const auto text = edit->text();
+ const auto lines = text.split("\n");
+ QCOMPARE(lines.size(), edit->lineCount());
+
+ int currentLineStartPos = 0;
+ QRectF firstLineStartPosRect;
+
+ // check that all lines are aligned, for RTL text it means that they have the same pos at the right
+ for (int i = 0; i < lines.size(); ++i) {
+ const auto lineStartPosRect = edit->positionToRectangle(currentLineStartPos);
+ QVERIFY(lineStartPosRect.isValid());
+
+ if (i == 0)
+ firstLineStartPosRect = lineStartPosRect;
+ else
+ QCOMPARE(lineStartPosRect.right(), firstLineStartPosRect.right());
+
+ currentLineStartPos += lines.at(i).size() + 1;
+ }
+}
+
+void tst_qquicktextedit::fontManipulationWithCursorSelection()
+{
+ QString testStr = standard[0];//TODO: What should happen for multiline/rich text?
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \""+ testStr +"\"; }";
+ QQmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(texteditComponent.create());
+ QVERIFY(textEditObject != nullptr);
+
+ const int originalStartPos = 0;
+ const int originalEndPos = (testStr.size() - 1) / 2;
+
+ textEditObject->select(originalStartPos, originalEndPos);
+ QCOMPARE(textEditObject->selectionStart(), originalStartPos);
+ QCOMPARE(textEditObject->selectionEnd(), originalEndPos);
+
+ QCOMPARE(textEditObject->cursorSelection()->text(), textEditObject->text().mid(originalStartPos, originalEndPos));
+
+ // test font manipulation
+ QFont font = textEditObject->cursorSelection()->font();
+ QVERIFY(!font.bold());
+ font.setBold(true);
+ textEditObject->cursorSelection()->setFont(font);
+ QVERIFY(textEditObject->cursorSelection()->font().bold());
+
+ // test color manipulation
+ QCOMPARE_NE(textEditObject->cursorSelection()->color(), QColorConstants::Cyan);
+ textEditObject->cursorSelection()->setColor(QColorConstants::Cyan);
+ QCOMPARE(textEditObject->cursorSelection()->color(), QColorConstants::Cyan);
+
+ // test alignment
+ QCOMPARE(textEditObject->cursorSelection()->alignment(), Qt::AlignLeft);
+ textEditObject->cursorSelection()->setAlignment(Qt::AlignRight);
+ QCOMPARE(textEditObject->cursorSelection()->alignment(), Qt::AlignRight);
+
+ // change seleciton and verify that we don't keep the same formatting
+ const int newStartPos = testStr.size() / 2;
+ const int newEndPos = testStr.size() - 1;
+
+ textEditObject->select(newStartPos, newEndPos);
+ QCOMPARE(textEditObject->selectionStart(), newStartPos);
+ QCOMPARE(textEditObject->selectionEnd(), newEndPos);
+ QVERIFY(!textEditObject->cursorSelection()->font().bold());
+ QCOMPARE_NE(textEditObject->cursorSelection()->color(), QColorConstants::Cyan);
+ QEXPECT_FAIL("", "The text alignment doesn't update when changing selection", Continue);
+ QCOMPARE(textEditObject->cursorSelection()->alignment(), Qt::AlignLeft);
+
+ // change back to the previous fragment, and verify that we have the old formatting
+ textEditObject->select(originalStartPos, originalEndPos);
+ QVERIFY(font.bold());
+ QCOMPARE(textEditObject->cursorSelection()->color(), QColorConstants::Cyan);
+ QCOMPARE(textEditObject->cursorSelection()->alignment(), Qt::AlignRight);
+
+ // test text manipulation
+ textEditObject->cursorSelection()->setText("Q");
+ QEXPECT_FAIL("", "QQuickTextSelection::text doesn't currently work correctly", Continue);
+ QCOMPARE(textEditObject->text(), QLatin1String("Q%1").arg(testStr.mid(newStartPos, newEndPos)));
+
+ // Make sure that QQuickTextEdit::setFont() affects all blocks
+ font.setItalic(true);
+ font.setWeight(QFont::Black);
+ textEditObject->setFont(font);
+ const auto *doc = textEditObject->textDocument()->textDocument();
+ for (QTextBlock block = doc->begin(); block != doc->end(); block = block.next())
+ QCOMPARE(block.charFormat().font(), font);
+}
+
+void tst_qquicktextedit::resizeTextEditPolish()
+{
+ QQuickView window(testFileUrl("resizeTextEditPolish.qml"));
+ QVERIFY(window.rootObject() != nullptr);
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ auto *edit = window.rootObject()->findChild<QQuickTextEdit *>();
+ QVERIFY(edit != nullptr);
+ QCOMPARE(edit->lineCount(), 1);
+
+ QSignalSpy spy(edit, SIGNAL(lineCountChanged()));
+
+ // Resize item and check for item polished
+ auto *item = edit->parentItem();
+ item->setWidth(item->width() - (item->width() / 2));
+
+ QVERIFY(QQuickTest::qIsPolishScheduled(edit));
+ QVERIFY(QQuickTest::qWaitForPolish(edit));
+
+ QTRY_COMPARE(spy.size(), 1);
+ QVERIFY(edit->lineCount() > 1);
+ QCOMPARE(edit->state(), QString("multi-line"));
+ auto *editPriv = QQuickTextEditPrivate::get(edit);
+ QCOMPARE(editPriv->xoff, 0);
+ QCOMPARE(editPriv->yoff, 0);
+}
+
+QT_END_NAMESPACE
+
QTEST_MAIN(tst_qquicktextedit)
#include "tst_qquicktextedit.moc"
diff --git a/tests/auto/quick/qquicktextinput/BLACKLIST b/tests/auto/quick/qquicktextinput/BLACKLIST
index 4d03982f73..2af586c68a 100644
--- a/tests/auto/quick/qquicktextinput/BLACKLIST
+++ b/tests/auto/quick/qquicktextinput/BLACKLIST
@@ -2,14 +2,6 @@
[mouseSelectionMode]
opensuse-leap
-# QTBUG-99150
-[copyAndPaste]
-opensuse-leap
-
-# QTBUG-99150
-[canPaste]
-opensuse-leap
-
# QTBUG-82058
[setInputMask]
macos ci
@@ -18,22 +10,6 @@ macos ci
[passwordCharacter]
ci b2qt 32bit
-# QTBUG-95940
-[canPaste]
-opensuse-leap
-
-# QTBUG-95940
-[canPasteEmpty]
-opensuse-leap
-
-# QTBUG-95940
-[copyAndPaste]
-opensuse-leap
-
-# QTBUG-95940
-[copyAndPasteKeySequence]
-opensuse-leap
-
# QTBUG-103256
[copyAndPasteKeySequence]
android
diff --git a/tests/auto/quick/qquicktextinput/CMakeLists.txt b/tests/auto/quick/qquicktextinput/CMakeLists.txt
index 716d7b371b..70003a63b8 100644
--- a/tests/auto/quick/qquicktextinput/CMakeLists.txt
+++ b/tests/auto/quick/qquicktextinput/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicktextinput Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicktextinput LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index 267b9c10a0..8f8442544f 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -1,10 +1,12 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <QtTest/QSignalSpy>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/testhttpserver_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
+#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <private/qinputmethod_p.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -212,7 +214,6 @@ private:
#if QT_CONFIG(shortcut)
void simulateKeys(QWindow *window, const QKeySequence &sequence);
#endif
- static bool hasWindowActivation();
QQmlEngine engine;
QStringList standard;
@@ -238,11 +239,6 @@ void tst_qquicktextinput::simulateKeys(QWindow *window, const QList<Key> &keys)
}
}
-bool tst_qquicktextinput::hasWindowActivation()
-{
- return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation));
-}
-
#if QT_CONFIG(shortcut)
void tst_qquicktextinput::simulateKeys(QWindow *window, const QKeySequence &sequence)
@@ -1877,7 +1873,7 @@ void tst_qquicktextinput::maxLength()
QVERIFY(textinputObject != nullptr);
QVERIFY(textinputObject->text().isEmpty());
QCOMPARE(textinputObject->maxLength(), 10);
- foreach (const QString &str, standard) {
+ for (const QString &str : std::as_const(standard)) {
QVERIFY(textinputObject->text().size() <= 10);
textinputObject->setText(str);
QVERIFY(textinputObject->text().size() <= 10);
@@ -2757,15 +2753,18 @@ void tst_qquicktextinput::copyAndPasteKeySequence()
#if QT_CONFIG(clipboard) && QT_CONFIG(shortcut)
void tst_qquicktextinput::canPasteEmpty()
{
+ if (!PlatformQuirks::isClipboardAvailable())
+ QSKIP("This machine has no clipboard support.");
+
QGuiApplication::clipboard()->clear();
- QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
+ const QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
QVERIFY(textInput != nullptr);
- bool cp = !textInput->isReadOnly() && QGuiApplication::clipboard()->text().size() != 0;
+ const bool cp = !textInput->isReadOnly() && QGuiApplication::clipboard()->text().size() != 0;
QCOMPARE(textInput->canPaste(), cp);
}
#endif
@@ -2773,15 +2772,18 @@ void tst_qquicktextinput::canPasteEmpty()
#if QT_CONFIG(clipboard) && QT_CONFIG(shortcut)
void tst_qquicktextinput::canPaste()
{
+ if (!PlatformQuirks::isClipboardAvailable())
+ QSKIP("This machine has no clipboard support.");
+
QGuiApplication::clipboard()->setText("Some text");
- QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
+ const QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
QVERIFY(textInput != nullptr);
- bool cp = !textInput->isReadOnly() && QGuiApplication::clipboard()->text().size() != 0;
+ const bool cp = !textInput->isReadOnly() && QGuiApplication::clipboard()->text().size() != 0;
QCOMPARE(textInput->canPaste(), cp);
}
#endif
@@ -2790,7 +2792,7 @@ void tst_qquicktextinput::canPaste()
void tst_qquicktextinput::middleClickPaste()
{
if (!PlatformQuirks::isClipboardAvailable())
- QSKIP("This machine doesn't support the clipboard");
+ QSKIP("This machine has no clipboard support.");
QQuickView window(testFileUrl("mouseselectionmode_default.qml"));
@@ -2805,8 +2807,8 @@ void tst_qquicktextinput::middleClickPaste()
textInputObject->setFocus(true);
- QString originalText = textInputObject->text();
- QString selectedText = "234567";
+ const QString originalText = textInputObject->text();
+ const QString selectedText = "234567";
// press-and-drag-and-release from x1 to x2
const QPoint p1 = textInputObject->positionToRectangle(2).center().toPoint();
@@ -6427,7 +6429,7 @@ void tst_qquicktextinput::setInputMask()
// inputMaskChanged signal
QString unescapedMask = mask; // mask is escaped, because '\' is also escape in a JS string
unescapedMask.replace(QLatin1String("\\\\"), QLatin1String("\\")); // simple unescape
- QSignalSpy spy(textInput, SIGNAL(inputMaskChanged(const QString &)));
+ QSignalSpy spy(textInput, SIGNAL(inputMaskChanged(QString)));
textInput->setInputMask(unescapedMask);
QCOMPARE(spy.size(), 0);
@@ -7176,12 +7178,26 @@ void tst_qquicktextinput::touchscreenDoesNotSelect()
QTest::touchEvent(&window, touchscreen.data()).release(0, QPoint(x2,y), &window);
QQuickTouchUtils::flush(&window);
QVERIFY(textInputObject->selectedText().isEmpty());
+
+ // select all text (which moves the cursor to the end), then tap:
+ // with old API, it deselects, and moves the cursor (QTBUG-116606)
+ // with new API, it remains selected, and the cursor remains at the end
+ textInputObject->selectAll();
+ const int cursorPos = textInputObject->cursorPosition();
+ QTest::touchEvent(&window, touchscreen.data()).press(0, QPoint(x2,y), &window);
+ QTest::touchEvent(&window, touchscreen.data()).release(0, QPoint(x2,y), &window);
+ QQuickTouchUtils::flush(&window);
+ QCOMPARE(textInputObject->selectedText().isEmpty(), !expectDefaultSelectByMouse);
+ if (expectDefaultSelectByMouse)
+ QCOMPARE(textInputObject->cursorPosition(), cursorPos);
+ else
+ QCOMPARE_NE(textInputObject->cursorPosition(), cursorPos);
}
void tst_qquicktextinput::touchscreenSetsFocusAndMovesCursor()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
+
QQuickView window;
QVERIFY(QQuickTest::showView(window, testFileUrl("twoInAColumn.qml")));
window.requestActivate();
diff --git a/tests/auto/quick/qquicktextmetrics/CMakeLists.txt b/tests/auto/quick/qquicktextmetrics/CMakeLists.txt
index 6880cf8445..86bc976156 100644
--- a/tests/auto/quick/qquicktextmetrics/CMakeLists.txt
+++ b/tests/auto/quick/qquicktextmetrics/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicktextmetrics Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicktextmetrics LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qquicktextmetrics
SOURCES
tst_qquicktextmetrics.cpp
diff --git a/tests/auto/quick/qquicktextmetrics/tst_qquicktextmetrics.cpp b/tests/auto/quick/qquicktextmetrics/tst_qquicktextmetrics.cpp
index 21c816fa9d..8c3448d422 100644
--- a/tests/auto/quick/qquicktextmetrics/tst_qquicktextmetrics.cpp
+++ b/tests/auto/quick/qquicktextmetrics/tst_qquicktextmetrics.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QFont>
#include <QString>
diff --git a/tests/auto/quick/qquicktimeline/CMakeLists.txt b/tests/auto/quick/qquicktimeline/CMakeLists.txt
index bdb2d19ad1..e4e1de1346 100644
--- a/tests/auto/quick/qquicktimeline/CMakeLists.txt
+++ b/tests/auto/quick/qquicktimeline/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicktimeline Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicktimeline LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qquicktimeline
SOURCES
tst_qquicktimeline.cpp
diff --git a/tests/auto/quick/qquicktimeline/tst_qquicktimeline.cpp b/tests/auto/quick/qquicktimeline/tst_qquicktimeline.cpp
index 76de05258d..247af56fd7 100644
--- a/tests/auto/quick/qquicktimeline/tst_qquicktimeline.cpp
+++ b/tests/auto/quick/qquicktimeline/tst_qquicktimeline.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <private/qquicktimeline_p_p.h>
diff --git a/tests/auto/quick/qquicktreeview/CMakeLists.txt b/tests/auto/quick/qquicktreeview/CMakeLists.txt
index 27e94c2c1e..1fa487c2e8 100644
--- a/tests/auto/quick/qquicktreeview/CMakeLists.txt
+++ b/tests/auto/quick/qquicktreeview/CMakeLists.txt
@@ -5,6 +5,12 @@
## tst_qquicktreeview Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicktreeview LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquicktreeview/data/CustomDelegate.qml b/tests/auto/quick/qquicktreeview/data/CustomDelegate.qml
index 72fa344b0b..525f9ea337 100644
--- a/tests/auto/quick/qquicktreeview/data/CustomDelegate.qml
+++ b/tests/auto/quick/qquicktreeview/data/CustomDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import TestModel
diff --git a/tests/auto/quick/qquicktreeview/data/normaltreeview.qml b/tests/auto/quick/qquicktreeview/data/normaltreeview.qml
index cf4d72d0ca..7a68646c80 100644
--- a/tests/auto/quick/qquicktreeview/data/normaltreeview.qml
+++ b/tests/auto/quick/qquicktreeview/data/normaltreeview.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import TestModel
diff --git a/tests/auto/quick/qquicktreeview/testmodel.cpp b/tests/auto/quick/qquicktreeview/testmodel.cpp
index 9962234a06..66fbf9b656 100644
--- a/tests/auto/quick/qquicktreeview/testmodel.cpp
+++ b/tests/auto/quick/qquicktreeview/testmodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testmodel.h"
@@ -128,3 +128,33 @@ bool TestModel::insertRows(int position, int rows, const QModelIndex &parent)
endInsertRows();
return true;
}
+
+
+void insertColumnsRecursive(TreeItem *item, int row, int pos, int cols)
+{
+ for (int col = 0; col < cols; col++)
+ item->m_entries.insert(pos + col, QVariant(QString("%1, %2 (inserted)").arg(row).arg(pos + col)));
+ for (auto child : item->m_childItems) {
+ insertColumnsRecursive(child, row, pos, cols);
+ row++;
+ }
+}
+
+bool TestModel::insertColumns(int position, int cols, const QModelIndex &parent)
+{
+ if (!parent.isValid()) {
+ qWarning() << "Cannot insert columns on an invalid parent!";
+ return false;
+ }
+
+ beginInsertColumns(parent, position, position + cols - 1);
+ TreeItem *parentItem = treeItem(parent);
+
+ TreeItem *item = m_rootItem.data();
+
+ insertColumnsRecursive(item, 0, position, cols);
+ m_columnCount += cols;
+
+ endInsertColumns();
+ return true;
+}
diff --git a/tests/auto/quick/qquicktreeview/testmodel.h b/tests/auto/quick/qquicktreeview/testmodel.h
index 4cb80d0eab..e12d0ae1d6 100644
--- a/tests/auto/quick/qquicktreeview/testmodel.h
+++ b/tests/auto/quick/qquicktreeview/testmodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTMODEL_H
#define TESTMODEL_H
@@ -39,6 +39,7 @@ public:
int maxDepth() { return 4; }
bool insertRows(int position, int rows, const QModelIndex &parent) override;
+ bool insertColumns(int position, int cols, const QModelIndex &parent) override;
private:
QScopedPointer<TreeItem> m_rootItem;
diff --git a/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp b/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp
index 6e7a1e1216..d41d811496 100644
--- a/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp
+++ b/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuickTest/quicktest.h>
@@ -76,6 +76,7 @@ private slots:
void emptyModel();
void updatedModifiedModel();
void insertRows();
+ void insertColumns();
void toggleExpandedUsingArrowKeys();
void expandAndCollapsUsingDoubleClick();
void selectionBehaviorCells_data();
@@ -87,6 +88,8 @@ private slots:
void sortTreeModel();
void sortTreeModelDynamic_data();
void sortTreeModelDynamic();
+ void setRootIndex();
+ void setRootIndexToLeaf();
};
tst_qquicktreeview::tst_qquicktreeview()
@@ -139,7 +142,7 @@ void tst_qquicktreeview::expandAndCollapseRoot()
// 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)));
+ QSignalSpy expandedSpy(treeView, SIGNAL(expanded(int,int)));
// Expand the root
treeView->expand(0);
@@ -184,7 +187,7 @@ void tst_qquicktreeview::expandAndCollapseChildren()
LOAD_TREEVIEW("normaltreeview.qml");
const int childCount = 4;
- QSignalSpy expandedSpy(treeView, SIGNAL(expanded(int, int)));
+ QSignalSpy expandedSpy(treeView, SIGNAL(expanded(int,int)));
// Expand the last child of a parent recursively four times
for (int level = 0; level < 4; ++level) {
@@ -305,7 +308,7 @@ void tst_qquicktreeview::requiredPropertiesChildren()
QCOMPARE(viewProp, treeView);
QCOMPARE(isTreeNode, true);
QCOMPARE(expanded, row == 4);
- QCOMPARE(hasChildren, model->hasChildren(treeView->modelIndex(row, 0)));
+ QCOMPARE(hasChildren, model->hasChildren(treeView->index(row, 0)));
QCOMPARE(depth, row <= 4 ? 1 : 2);
}
}
@@ -328,7 +331,7 @@ void tst_qquicktreeview::emptyModel()
QCOMPARE(treeView->depth(0), -1);
QCOMPARE(treeView->isExpanded(0), false);
- QVERIFY(!treeView->modelIndex(10, 10).isValid());
+ QVERIFY(!treeView->index(10, 10).isValid());
QCOMPARE(treeView->rowAtIndex(QModelIndex()), -1);
QCOMPARE(treeView->columnAtIndex(QModelIndex()), -1);
}
@@ -390,6 +393,48 @@ void tst_qquicktreeview::insertRows()
QCOMPARE(treeView->rows(), 9);
}
+void tst_qquicktreeview::insertColumns()
+{
+ // Check that if we add new columns to the model, TreeView gets updated
+ // to contain the new expected number of rows (flattened to a list)
+ LOAD_TREEVIEW("normaltreeview.qml");
+ treeView->expand(0);
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(treeView->columns(), 5);
+
+ const QModelIndex rootNode = model->index(0, 0, QModelIndex());
+ model->insertColumns(0, 2, rootNode);
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(treeView->columns(), 7);
+ auto childItem1 = treeViewPrivate->loadedTableItem(QPoint(0, 1))->item;
+ QCOMPARE(childItem1->property("text").toString(), "0, 0 (inserted)");
+ auto childItem2 = treeViewPrivate->loadedTableItem(QPoint(0, 2))->item;
+ QCOMPARE(childItem2->property("text").toString(), "1, 0 (inserted)");
+ auto childItem3 = treeViewPrivate->loadedTableItem(QPoint(0, 3))->item;
+ QCOMPARE(childItem3->property("text").toString(), "2, 0 (inserted)");
+ auto childItem4 = treeViewPrivate->loadedTableItem(QPoint(3, 0))->item;
+ QCOMPARE(childItem4->property("text").toString(), "0, 1");
+ auto childItem5 = treeViewPrivate->loadedTableItem(QPoint(3, 1))->item;
+ QCOMPARE(childItem5->property("text").toString(), "0, 1");
+
+ const QModelIndex indexOfInsertedChild = model->index(1, 0, rootNode);
+ model->insertRows(0, 2, indexOfInsertedChild);
+ treeView->expand(2);
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(treeView->rows(), 7);
+ QCOMPARE(treeView->columns(), 7);
+
+ for (int i = 0; i < 7; i++) {
+ for (int j = 0; j < 7; j++) {
+ auto childItem = treeViewPrivate->loadedTableItem(QPoint(j, i))->item;
+ QVERIFY(childItem);
+ }
+ }
+}
+
void tst_qquicktreeview::expandChildPendingToBeVisible()
{
// Check that if we expand a row r1, and that row has a child r2 that can
@@ -434,7 +479,7 @@ void tst_qquicktreeview::expandRecursivelyRoot()
QFETCH(int, depth);
LOAD_TREEVIEW("normaltreeview.qml");
- QSignalSpy spy(treeView, SIGNAL(expanded(int, int)));
+ QSignalSpy spy(treeView, SIGNAL(expanded(int,int)));
treeView->expandRecursively(rowToExpand, depth);
@@ -461,7 +506,7 @@ void tst_qquicktreeview::expandRecursivelyRoot()
// 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 auto modelIndex = treeView->index(currentRow, 0);
const int currentDepth = treeView->depth(currentRow);
const bool isChild = currentDepth > rowToExpandDepth;
const bool isExpandable = model->rowCount(modelIndex) > 0;
@@ -491,7 +536,7 @@ void tst_qquicktreeview::expandRecursivelyChild()
QFETCH(int, depth);
LOAD_TREEVIEW("normaltreeview.qml");
- QSignalSpy spy(treeView, SIGNAL(expanded(int, int)));
+ QSignalSpy spy(treeView, SIGNAL(expanded(int,int)));
treeView->expand(0);
@@ -513,7 +558,7 @@ void tst_qquicktreeview::expandRecursivelyChild()
WAIT_UNTIL_POLISHED;
- const bool rowToExpandDepth = treeView->depth(rowToExpand);
+ const int rowToExpandDepth = treeView->depth(rowToExpand);
const int effectiveMaxDepth = depth != -1 ? rowToExpandDepth + depth : model->maxDepth();
// Check that none of the rows before rowToExpand are expanded
@@ -532,7 +577,7 @@ void tst_qquicktreeview::expandRecursivelyChild()
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 auto modelIndex = treeView->index(currentRow, 0);
const bool isExpandable = model->rowCount(modelIndex) > 0;
const bool shouldBeExpanded = isChild && isExpandable && currentDepth < effectiveMaxDepth;
QCOMPARE(treeView->isExpanded(currentRow), shouldBeExpanded);
@@ -543,7 +588,7 @@ 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)));
+ QSignalSpy spy(treeView, SIGNAL(expanded(int,int)));
treeView->expandRecursively(-1, -1);
QCOMPARE(spy.size(), 1);
@@ -555,7 +600,7 @@ void tst_qquicktreeview::expandRecursivelyWholeTree()
// 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 auto modelIndex = treeView->index(currentRow, 0);
const bool isExpandable = model->rowCount(modelIndex) > 0;
QCOMPARE(treeView->isExpanded(currentRow), isExpandable);
}
@@ -575,7 +620,7 @@ void tst_qquicktreeview::collapseRecursivelyRoot()
const int expectedRowCount = 1 + (model->maxDepth() * 8) - 4;
QCOMPARE(treeView->rows(), expectedRowCount);
- QSignalSpy spy(treeView, SIGNAL(collapsed(int, bool)));
+ QSignalSpy spy(treeView, SIGNAL(collapsed(int,bool)));
// Collapse the whole tree again. This time, only the root should end up visible
treeView->collapseRecursively();
@@ -595,7 +640,7 @@ void tst_qquicktreeview::collapseRecursivelyRoot()
// 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);
+ const QModelIndex currentIndex = treeView->index(currentRow, 0);
if (model->hasChildren(currentIndex)) {
QVERIFY(!treeView->isExpanded(currentRow));
treeView->expand(currentRow);
@@ -622,11 +667,11 @@ void tst_qquicktreeview::collapseRecursivelyChild()
const int expectedRowCount = 1 + (model->maxDepth() * 8) - 4;
QCOMPARE(treeView->rows(), expectedRowCount);
- QSignalSpy spy(treeView, SIGNAL(collapsed(int, bool)));
+ QSignalSpy spy(treeView, SIGNAL(collapsed(int,bool)));
// Collapse the 8th child recursive
const int rowToCollapse = 8;
- const QModelIndex collapseIndex = treeView->modelIndex(rowToCollapse, 0);
+ const QModelIndex collapseIndex = treeView->index(rowToCollapse, 0);
const auto expectedLabel = model->data(collapseIndex, Qt::DisplayRole);
QCOMPARE(expectedLabel, QStringLiteral("3, 0"));
treeView->collapseRecursively(rowToCollapse);
@@ -646,7 +691,7 @@ void tst_qquicktreeview::collapseRecursivelyChild()
// 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);
+ const QModelIndex currentIndex = treeView->index(currentRow, 0);
if (model->hasChildren(currentIndex)) {
if (treeView->depth(currentRow) == 1 && currentIndex.row() == 2) {
// We did only recursively expand the 4th child, so the
@@ -669,7 +714,7 @@ 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)));
+ QSignalSpy spy(treeView, SIGNAL(collapsed(int,bool)));
treeView->expandRecursively();
treeView->collapseRecursively();
@@ -688,7 +733,7 @@ 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)));
+ QSignalSpy spy(treeView, SIGNAL(expanded(int,int)));
const QModelIndex root = model->index(0, 0);
const QModelIndex child1 = model->index(3, 0, root);
@@ -731,7 +776,7 @@ void tst_qquicktreeview::toggleExpandedUsingArrowKeys()
QQuickWindow *window = treeView->window();
// Start by making cell 0, 0 current
- treeView->selectionModel()->setCurrentIndex(treeView->modelIndex(0, 0), QItemSelectionModel::NoUpdate);
+ treeView->selectionModel()->setCurrentIndex(treeView->index(0, 0), QItemSelectionModel::NoUpdate);
// Expand row 0
const int row0 = 0;
@@ -747,7 +792,7 @@ void tst_qquicktreeview::toggleExpandedUsingArrowKeys()
// Hitting Key_Right again should be a no-op
QTest::keyPress(window, Qt::Key_Right);
QVERIFY(treeView->isExpanded(row0));
- QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->modelIndex(row0, 0));
+ QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->index(row0, 0));
// Move down to row 1 and try to expand it. Since Row 1
// doesn't have children, expanding it will be a no-op.
@@ -758,7 +803,7 @@ void tst_qquicktreeview::toggleExpandedUsingArrowKeys()
QTest::keyPress(window, Qt::Key_Down);
QTest::keyPress(window, Qt::Key_Right);
QVERIFY(!treeView->isExpanded(row1));
- QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->modelIndex(row1, 0));
+ QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->index(row1, 0));
// Move down to row 4 and expand it
const int row4 = 4;
@@ -768,7 +813,7 @@ void tst_qquicktreeview::toggleExpandedUsingArrowKeys()
QVERIFY(!treeView->isExpanded(row4));
QTest::keyPress(window, Qt::Key_Right);
QVERIFY(treeView->isExpanded(row4));
- QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->modelIndex(row4, 0));
+ QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->index(row4, 0));
// Move up again to row 0 and collapse it
while (treeView->currentRow() != row0)
@@ -781,7 +826,7 @@ void tst_qquicktreeview::toggleExpandedUsingArrowKeys()
// Hitting Key_Left again should be a no-op
QTest::keyPress(window, Qt::Key_Left);
QVERIFY(!treeView->isExpanded(row0));
- QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->modelIndex(row0, 0));
+ QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->index(row0, 0));
}
void tst_qquicktreeview::expandAndCollapsUsingDoubleClick()
@@ -791,7 +836,7 @@ void tst_qquicktreeview::expandAndCollapsUsingDoubleClick()
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
// Expand the root by double clicking on the row
- const auto item = treeView->itemAtCell(0, 0);
+ const auto item = treeView->itemAtIndex(treeView->index(0, 0));
QVERIFY(item);
const QPoint localPos = QPoint(item->width() / 2, item->height() / 2);
const QPoint pos = item->window()->contentItem()->mapFromItem(item, localPos).toPoint();
@@ -876,6 +921,7 @@ void tst_qquicktreeview::selectionBehaviorCells()
const QPointF endPos(endItem->x(), endItem->y());
const QPointF endPosWrapped(endItemWrapped->x(), endItemWrapped->y());
+ QVERIFY(treeViewPrivate->startSelection(startPos, Qt::NoModifier));
treeViewPrivate->setSelectionStartPos(startPos);
treeViewPrivate->setSelectionEndPos(endPos);
@@ -888,7 +934,7 @@ void tst_qquicktreeview::selectionBehaviorCells()
for (int x = x1; x < x2; ++x) {
for (int y = y1; y < y2; ++y) {
- const auto index = treeView->modelIndex(y, x);
+ const auto index = treeView->index(y, x);
QVERIFY(selectionModel->isSelected(index));
}
}
@@ -930,6 +976,7 @@ void tst_qquicktreeview::selectionBehaviorRows()
QCOMPARE(selectionModel->hasSelection(), false);
// Drag from row 0 to row 3
+ QVERIFY(treeViewPrivate->startSelection(QPointF(0, 0), Qt::NoModifier));
treeViewPrivate->setSelectionStartPos(QPointF(0, 0));
treeViewPrivate->setSelectionEndPos(QPointF(80, 60));
@@ -941,7 +988,7 @@ void tst_qquicktreeview::selectionBehaviorRows()
for (int x = 0; x < treeView->columns(); ++x) {
for (int y = 0; y < 3; ++y) {
- const auto index = treeView->modelIndex(y, x);
+ const auto index = treeView->index(y, x);
QVERIFY(selectionModel->isSelected(index));
}
}
@@ -950,6 +997,7 @@ void tst_qquicktreeview::selectionBehaviorRows()
QCOMPARE(selectionModel->hasSelection(), false);
// Drag from row 3 to row 0 (and overshoot mouse)
+ QVERIFY(treeViewPrivate->startSelection(QPointF(80, 60), Qt::NoModifier));
treeViewPrivate->setSelectionStartPos(QPointF(80, 60));
treeViewPrivate->setSelectionEndPos(QPointF(-10, -10));
@@ -960,7 +1008,7 @@ void tst_qquicktreeview::selectionBehaviorRows()
for (int x = 0; x < treeView->columns(); ++x) {
for (int y = 0; y < 3; ++y) {
- const auto index = treeView->modelIndex(y, x);
+ const auto index = treeView->index(y, x);
QVERIFY(selectionModel->isSelected(index));
}
}
@@ -981,6 +1029,7 @@ void tst_qquicktreeview::selectionBehaviorColumns()
QCOMPARE(selectionModel->hasSelection(), false);
// Drag from column 0 to column 3
+ QVERIFY(treeViewPrivate->startSelection(QPointF(0, 0), Qt::NoModifier));
treeViewPrivate->setSelectionStartPos(QPointF(0, 0));
treeViewPrivate->setSelectionEndPos(QPointF(225, 90));
@@ -992,7 +1041,7 @@ void tst_qquicktreeview::selectionBehaviorColumns()
for (int x = 0; x < 3; ++x) {
for (int y = 0; y < treeView->rows(); ++y) {
- const auto index = treeView->modelIndex(y, x);
+ const auto index = treeView->index(y, x);
QVERIFY(selectionModel->isSelected(index));
}
}
@@ -1001,6 +1050,7 @@ void tst_qquicktreeview::selectionBehaviorColumns()
QCOMPARE(selectionModel->hasSelection(), false);
// Drag from column 3 to column 0 (and overshoot mouse)
+ QVERIFY(treeViewPrivate->startSelection(QPointF(225, 90), Qt::NoModifier));
treeViewPrivate->setSelectionStartPos(QPointF(225, 90));
treeViewPrivate->setSelectionEndPos(QPointF(-10, -10));
@@ -1011,7 +1061,7 @@ void tst_qquicktreeview::selectionBehaviorColumns()
for (int x = 0; x < 3; ++x) {
for (int y = 0; y < treeView->rows(); ++y) {
- const auto index = treeView->modelIndex(y, x);
+ const auto index = treeView->index(y, x);
QVERIFY(selectionModel->isSelected(index));
}
}
@@ -1030,10 +1080,11 @@ void tst_qquicktreeview::selectionBehaviorDisabled()
QCOMPARE(selectionModel->hasSelection(), false);
- // Drag from column 0 to column 3
- treeViewPrivate->setSelectionStartPos(QPointF(0, 0));
- treeViewPrivate->setSelectionEndPos(QPointF(60, 60));
-
+ // Try to start a selection. treeViewPrivate->startSelection() should
+ // reject that, and and return false. The selectionFlag will there stay as
+ // QItemSelectionModel::NoUpdate, meaning no active selection is ongoing.
+ QVERIFY(!treeViewPrivate->startSelection(QPointF(0, 0), Qt::NoModifier));
+ QCOMPARE(treeViewPrivate->selectionFlag, QItemSelectionModel::NoUpdate);
QCOMPARE(selectionModel->hasSelection(), false);
}
@@ -1068,7 +1119,7 @@ void tst_qquicktreeview::sortTreeModel()
// is the same as in the view. That means that QQmlTreeModelToTableModel
// and QSortFilterProxyModel are in sync.
for (int row = 0; row < treeView->rows(); ++row) {
- const auto index = treeView->modelIndex(row, 0);
+ const auto index = treeView->index(row, 0);
const QString modelDisplay = proxyModel.data(index, Qt::DisplayRole).toString();
const auto childFxItem = treeViewPrivate->loadedTableItem(QPoint(0, row));
QVERIFY(childFxItem);
@@ -1084,7 +1135,7 @@ void tst_qquicktreeview::sortTreeModel()
WAIT_UNTIL_POLISHED;
for (int row = 0; row < treeView->rows(); ++row) {
- const auto index = treeView->modelIndex(row, 0);
+ const auto index = treeView->index(row, 0);
const QString modelDisplay = proxyModel.data(index, Qt::DisplayRole).toString();
const auto childFxItem = treeViewPrivate->loadedTableItem(QPoint(0, row));
QVERIFY(childFxItem);
@@ -1133,7 +1184,7 @@ void tst_qquicktreeview::sortTreeModelDynamic()
// is the same as in the view. That means that QQmlTreeModelToTableModel
// and QSortFilterProxyModel are in sync.
for (int row = 0; row < treeView->rows(); ++row) {
- const auto index = treeView->modelIndex(row, 0);
+ const auto index = treeView->index(row, 0);
const QString modelDisplay = proxyModel.data(index, Qt::DisplayRole).toString();
const auto childFxItem = treeViewPrivate->loadedTableItem(QPoint(0, row));
QVERIFY(childFxItem);
@@ -1146,10 +1197,10 @@ void tst_qquicktreeview::sortTreeModelDynamic()
// Now change the text in one of the items. This will trigger
// a sort for only one of the parents in the model.
- proxyModel.setData(treeView->modelIndex(row, 0), u"xxx"_s, Qt::DisplayRole);
+ proxyModel.setData(treeView->index(row, 0), u"xxx"_s, Qt::DisplayRole);
for (int row = 0; row < treeView->rows(); ++row) {
- const auto index = treeView->modelIndex(row, 0);
+ const auto index = treeView->index(row, 0);
const QString modelDisplay = proxyModel.data(index, Qt::DisplayRole).toString();
const auto childFxItem = treeViewPrivate->loadedTableItem(QPoint(0, row));
QVERIFY(childFxItem);
@@ -1161,6 +1212,100 @@ void tst_qquicktreeview::sortTreeModelDynamic()
}
}
+void tst_qquicktreeview::setRootIndex()
+{
+ // Check that if you can change the root index in the view to point
+ // at a child branch in the model
+ LOAD_TREEVIEW("normaltreeview.qml");
+
+ const QModelIndex rootIndex = model->index(0, 0);
+ const QModelIndex childIndex = model->index(3, 0, rootIndex);
+ QVERIFY(model->hasChildren(childIndex));
+ treeView->setRootIndex(childIndex);
+
+ // Go through all rows in the view, and check that view shows the
+ // same display text as the display role in the model (under the
+ // given root).
+ for (int row = 0; row < treeView->rows(); ++row) {
+ const auto index = model->index(row, 0, childIndex);
+ const QString modelDisplay = model->data(index, Qt::DisplayRole).toString();
+ const auto childFxItem = treeViewPrivate->loadedTableItem(QPoint(0, row));
+ QVERIFY(childFxItem);
+ const auto childItem = childFxItem->item;
+ QVERIFY(childItem);
+ const auto context = qmlContext(childItem.data());
+ const auto itemDisplay = context->contextProperty("display").toString();
+ QCOMPARE(itemDisplay, modelDisplay);
+ }
+
+ // Do the same once more, but this time choose a child that is deeper in the model
+ const QModelIndex childIndex2 = model->index(3, 0, childIndex);
+ QVERIFY(model->hasChildren(childIndex2));
+ treeView->setRootIndex(childIndex);
+
+ for (int row = 0; row < treeView->rows(); ++row) {
+ const auto index = model->index(row, 0, childIndex2);
+ const QString modelDisplay = model->data(index, Qt::DisplayRole).toString();
+ const auto childFxItem = treeViewPrivate->loadedTableItem(QPoint(0, row));
+ QVERIFY(childFxItem);
+ const auto childItem = childFxItem->item;
+ QVERIFY(childItem);
+ const auto context = qmlContext(childItem.data());
+ const auto itemDisplay = context->contextProperty("display").toString();
+ QCOMPARE(itemDisplay, modelDisplay);
+ }
+
+ // Reset rootIndex. This should show the whole model again
+ treeView->setRootIndex(QModelIndex());
+
+ for (int row = 0; row < treeView->rows(); ++row) {
+ const auto index = model->index(row, 0);
+ const QString modelDisplay = model->data(index, Qt::DisplayRole).toString();
+ const auto childFxItem = treeViewPrivate->loadedTableItem(QPoint(0, row));
+ QVERIFY(childFxItem);
+ const auto childItem = childFxItem->item;
+ QVERIFY(childItem);
+ const auto context = qmlContext(childItem.data());
+ const auto itemDisplay = context->contextProperty("display").toString();
+ QCOMPARE(itemDisplay, modelDisplay);
+ }
+}
+
+void tst_qquicktreeview::setRootIndexToLeaf()
+{
+ // When you set a custom root index, the root index itself will not
+ // be shown. Therefore, check that if you change the root index to a
+ // leaf in the model, TreeView will be empty.
+ LOAD_TREEVIEW("normaltreeview.qml");
+
+ const QModelIndex rootIndex = model->index(0, 0);
+ const QModelIndex leafIndex = model->index(1, 0, rootIndex);
+ QVERIFY(!model->hasChildren(leafIndex));
+ treeView->setRootIndex(leafIndex);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(treeView->rows(), 0);
+
+ // According to the docs, you can set rootIndex to undefined
+ // in order to show the whole model again. This is the same
+ // as calling 'reset' on the property from c++. Verify that this works.
+ const QMetaObject *metaObject = treeView->metaObject();
+ const int propertyIndex = metaObject->indexOfProperty("rootIndex");
+ QVERIFY(propertyIndex != -1);
+ metaObject->property(propertyIndex).reset(treeView);
+
+ for (int row = 0; row < treeView->rows(); ++row) {
+ const auto index = model->index(row, 0);
+ const QString modelDisplay = model->data(index, Qt::DisplayRole).toString();
+ const auto childFxItem = treeViewPrivate->loadedTableItem(QPoint(0, row));
+ QVERIFY(childFxItem);
+ const auto childItem = childFxItem->item;
+ QVERIFY(childItem);
+ const auto context = qmlContext(childItem.data());
+ const auto itemDisplay = context->contextProperty("display").toString();
+ QCOMPARE(itemDisplay, modelDisplay);
+ }
+}
+
QTEST_MAIN(tst_qquicktreeview)
#include "tst_qquicktreeview.moc"
diff --git a/tests/auto/quick/qquickview/CMakeLists.txt b/tests/auto/quick/qquickview/CMakeLists.txt
index d5d248481a..658d957de5 100644
--- a/tests/auto/quick/qquickview/CMakeLists.txt
+++ b/tests/auto/quick/qquickview/CMakeLists.txt
@@ -7,6 +7,14 @@
## tst_qquickview Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickview LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_policy(SET QTP0001 NEW)
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -26,6 +34,14 @@ qt_internal_add_test(tst_qquickview
TESTDATA ${test_data}
)
+
+qt_add_qml_module(
+ tst_qquickview
+ URI test
+ QML_FILES
+ "data/TestQml.qml"
+)
+
## Scopes:
#####################################################################
diff --git a/tests/auto/quick/qquickview/data/TestQml.qml b/tests/auto/quick/qquickview/data/TestQml.qml
new file mode 100644
index 0000000000..3052615aef
--- /dev/null
+++ b/tests/auto/quick/qquickview/data/TestQml.qml
@@ -0,0 +1,3 @@
+import QtQuick
+
+Item {}
diff --git a/tests/auto/quick/qquickview/data/overlay.qml b/tests/auto/quick/qquickview/data/overlay.qml
new file mode 100644
index 0000000000..cefaaed8bd
--- /dev/null
+++ b/tests/auto/quick/qquickview/data/overlay.qml
@@ -0,0 +1,17 @@
+// RootItem.qml
+import QtQuick
+import QtQuick.Controls.Basic
+
+Item {
+ id: root
+ width: 640
+ height: 480
+
+ property double scaleFactor: 2.0
+ Scale {
+ id: scale
+ xScale: root.scaleFactor
+ yScale: root.scaleFactor
+ }
+ Overlay.overlay.transform: scale
+}
diff --git a/tests/auto/quick/qquickview/tst_qquickview.cpp b/tests/auto/quick/qquickview/tst_qquickview.cpp
index e226cfdca7..91a45077fb 100644
--- a/tests/auto/quick/qquickview/tst_qquickview.cpp
+++ b/tests/auto/quick/qquickview/tst_qquickview.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtTest/QSignalSpy>
#include <QtQml/qqmlcomponent.h>
@@ -10,9 +10,13 @@
#include <QtGui/QWindow>
#include <QtCore/QDebug>
#include <QtQml/qqmlengine.h>
+#include <private/qv4engine_p.h>
+#include <private/qv4mm_p.h>
#include <QtQuickTestUtils/private/geometrytestutils_p.h>
+using namespace Qt::StringLiterals;
+
class tst_QQuickView : public QQmlDataTest
{
Q_OBJECT
@@ -20,11 +24,16 @@ public:
tst_QQuickView();
private slots:
+ void gc();
void resizemodeitem();
void errors();
void engine();
void findChild();
void setInitialProperties();
+ void fromModuleCtor();
+ void loadFromModule_data();
+ void loadFromModule();
+ void overlay();
};
@@ -33,6 +42,36 @@ tst_QQuickView::tst_QQuickView()
{
}
+void tst_QQuickView::gc()
+{
+ QQuickView view;
+ QQmlEngine *engine = view.engine();
+ QV4::ExecutionEngine *v4 = engine->handle();
+
+ v4->memoryManager->gcStateMachine->deadline = QDeadlineTimer(QDeadlineTimer::Forever);
+ auto sm = v4->memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::CallDestroyObjects) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ view.loadFromModule("test", "TestQml");
+ auto root = view.rootObject();
+ QVERIFY(root);
+ auto ddata = QQmlData::get(root, false);
+ while (sm->state != QV4::GCState::DoSweep) {
+ if (sm->state > QV4::GCState::InitCallDestroyObjects) {
+ sm->mm->collectFromJSStack(sm->mm->markStack());
+ sm->mm->m_markStack->drain();
+ }
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QVERIFY(ddata);
+ QVERIFY(ddata->jsWrapper.asManaged());
+ QVERIFY(ddata->jsWrapper.asManaged()->markBit());
+}
+
void tst_QQuickView::resizemodeitem()
{
QWindow window;
@@ -270,6 +309,50 @@ void tst_QQuickView::setInitialProperties()
QCOMPARE(rootObject->property("width").toInt(), 100);
}
+void tst_QQuickView::fromModuleCtor()
+{
+ QQuickView view("QtQuick", "Rectangle");
+ // creation is always synchronous for C++ defined types, so we don't need _TRY
+ QObject *rootObject = view.rootObject();
+ QVERIFY(rootObject);
+ QCOMPARE(rootObject->metaObject()->className(), "QQuickRectangle");
+}
+
+void tst_QQuickView::loadFromModule_data()
+{
+ QTest::addColumn<QString>("module");
+ QTest::addColumn<QString>("typeName");
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<QQuickView::Status>("status");
+
+ QTest::addRow("Item") << u"QtQuick"_s << u"Item"_s << QUrl() << QQuickView::Ready;
+ QTest::addRow("composite") << u"test"_s << u"TestQml"_s << QUrl("qrc:/qt/qml/test/data/TestQml.qml") << QQuickView::Ready;
+ QTest::addRow("nonexistent") << u"missing"_s << u"Type"_s << QUrl() << QQuickView::Error;
+}
+
+void tst_QQuickView::loadFromModule()
+{
+ QFETCH(QString, module);
+ QFETCH(QString, typeName);
+ QFETCH(QUrl, url);
+ QFETCH(QQuickView::Status, status);
+
+ QQuickView view;
+ view.loadFromModule(module, typeName);
+ QTRY_COMPARE(view.status(), status);
+ QCOMPARE(view.source(), url);
+}
+
+void tst_QQuickView::overlay()
+{
+ QTest::ignoreMessage(QtWarningMsg,
+ QRegularExpression(".*: Cannot set properties on overlay as it is null"));
+ QQuickView view;
+ view.setSource(testFileUrl("overlay.qml"));
+ QObject *rootObject = view.rootObject();
+ QVERIFY(!rootObject);
+}
+
QTEST_MAIN(tst_QQuickView)
#include "tst_qquickview.moc"
diff --git a/tests/auto/quick/qquickview_extra/CMakeLists.txt b/tests/auto/quick/qquickview_extra/CMakeLists.txt
index 2d8bf7e282..4287c97f51 100644
--- a/tests/auto/quick/qquickview_extra/CMakeLists.txt
+++ b/tests/auto/quick/qquickview_extra/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickview_extra Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickview_extra LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickview_extra/tst_qquickview_extra.cpp b/tests/auto/quick/qquickview_extra/tst_qquickview_extra.cpp
index 0cd4b69e00..9fbd318669 100644
--- a/tests/auto/quick/qquickview_extra/tst_qquickview_extra.cpp
+++ b/tests/auto/quick/qquickview_extra/tst_qquickview_extra.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtTest/QSignalSpy>
#include <QtQuick/qquickview.h>
@@ -42,7 +42,7 @@ void tst_QQuickViewExtra::qtbug_87228()
auto children = contentItem->childItems();
QVERIFY(children.size() > 0);
// for the sake of this test, any child would be suitable, so pick first
- deletionSpy.reset(new QSignalSpy(children[0], SIGNAL(destroyed(QObject *))));
+ deletionSpy.reset(new QSignalSpy(children[0], SIGNAL(destroyed(QObject*))));
}
QCOMPARE(deletionSpy->size(), 1);
}
diff --git a/tests/auto/quick/qquickvisualdatamodel/CMakeLists.txt b/tests/auto/quick/qquickvisualdatamodel/CMakeLists.txt
index 05aa977033..2b11d7233a 100644
--- a/tests/auto/quick/qquickvisualdatamodel/CMakeLists.txt
+++ b/tests/auto/quick/qquickvisualdatamodel/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickvisualdatamodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickvisualdatamodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/externalManagedModel.qml b/tests/auto/quick/qquickvisualdatamodel/data/externalManagedModel.qml
index d6444dd636..f067e7a841 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/externalManagedModel.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/externalManagedModel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick.Window 2.2
import QtQuick 2.6
diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
index dd845b37d5..0821669703 100644
--- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
+++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
@@ -59,7 +60,7 @@ public:
struct Branch {
Branch(Branch *parent = nullptr) : parent(parent) {}
- ~Branch() { foreach (const Node &child, children) delete child.branch; }
+ ~Branch() { for (const Node &child : std::as_const(children)) delete child.branch; }
int indexOf(Branch *branch) const {
for (int i = 0; i < children.size(); ++i) {
if (children.at(i).branch == branch)
@@ -75,7 +76,7 @@ public:
SingleRoleModel(const QStringList &list = QStringList(), const QByteArray &role = "name", QObject *parent = nullptr)
: QAbstractItemModel(parent), m_role(role)
{
- foreach (const QString &string, list)
+ for (const QString &string : list)
trunk.children.append(Node(string));
}
~SingleRoleModel() {}
@@ -182,7 +183,7 @@ public:
QStringList getList() const {
QStringList list;
- foreach (const Node &node, trunk.children)
+ for (const Node &node : trunk.children)
list.append(node.display);
return list;
}
@@ -190,13 +191,13 @@ public:
void setList(const QStringList &l) {
if (trunk.children.size() > 0) {
beginRemoveRows(QModelIndex(), 0, trunk.children.size() - 1);
- foreach (const Node &child, trunk.children) delete child.branch;
+ for (const Node &child : std::as_const(trunk.children)) delete child.branch;
trunk.children.clear();
endRemoveRows();
}
if (l.size() > 0) {
beginInsertRows(QModelIndex(), 0, l.size() -1);
- foreach (const QString &string, l)
+ for (const QString &string : l)
trunk.children.append(Node(string));
endInsertRows();
}
@@ -603,7 +604,8 @@ void tst_qquickvisualdatamodel::childChanged()
QVERIFY(name);
QCOMPARE(name->text(), QString("Row 2 updated child"));
- model.item(1,0)->appendRow(new QStandardItem(QLatin1String("Row 2 Child Item 2")));
+ QStandardItem item(QLatin1String("Row 2 Child Item 2"));
+ model.item(1,0)->appendRow(&item);
QCOMPARE(listview->count(), 2);
listview->forceLayout();
@@ -635,10 +637,10 @@ void tst_qquickvisualdatamodel::objectListModel()
QQuickView view;
QList<QObject*> dataList;
- dataList.append(new DataObject("Item 1", "red"));
- dataList.append(new DataObject("Item 2", "green"));
- dataList.append(new DataObject("Item 3", "blue"));
- dataList.append(new DataObject("Item 4", "yellow"));
+ dataList.append(new DataObject("Item 1", "red", &view));
+ dataList.append(new DataObject("Item 2", "green", &view));
+ dataList.append(new DataObject("Item 3", "blue", &view));
+ dataList.append(new DataObject("Item 4", "yellow", &view));
QQmlContext *ctxt = view.rootContext();
ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
@@ -777,10 +779,10 @@ void tst_qquickvisualdatamodel::modelProperties()
QQuickView view;
QList<QObject*> dataList;
- dataList.append(new DataObject("Item 1", "red"));
- dataList.append(new DataObject("Item 2", "green"));
- dataList.append(new DataObject("Item 3", "blue"));
- dataList.append(new DataObject("Item 4", "yellow"));
+ dataList.append(new DataObject("Item 1", "red", &view));
+ dataList.append(new DataObject("Item 2", "green", &view));
+ dataList.append(new DataObject("Item 3", "blue", &view));
+ dataList.append(new DataObject("Item 4", "yellow", &view));
QQmlContext *ctxt = view.rootContext();
ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
@@ -846,12 +848,9 @@ void tst_qquickvisualdatamodel::modelProperties()
QUrl source(testFileUrl("modelproperties2.qml"));
//3 items, 3 i each
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: modelData is not defined");
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: modelData is not defined");
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: modelData is not defined");
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: modelData is not defined");
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: modelData is not defined");
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: modelData is not defined");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: TypeError: Cannot read property 'display' of undefined");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: TypeError: Cannot read property 'display' of undefined");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: TypeError: Cannot read property 'display' of undefined");
QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined");
QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined");
QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined");
@@ -2261,7 +2260,7 @@ void tst_qquickvisualdatamodel::onChanged()
evaluate<void>(object.data(), expression);
- foreach (const QString &test, tests) {
+ for (const QString &test : std::as_const(tests)) {
bool passed = evaluate<bool>(object.data(), test);
if (!passed)
qWarning() << test;
@@ -3998,7 +3997,8 @@ void tst_qquickvisualdatamodel::asynchronousInsert()
engine.rootContext()->setContextProperty("myModel", &model);
- QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(c.create());
+ QScopedPointer<QObject> o(c.create());
+ QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(o.data());
QVERIFY(visualModel);
ItemRequester requester;
@@ -4063,7 +4063,8 @@ void tst_qquickvisualdatamodel::asynchronousRemove()
engine.rootContext()->setContextProperty("myModel", &model);
- QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(c.create());
+ QScopedPointer<QObject> o(c.create());
+ QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(o.data());
QVERIFY(visualModel);
ItemRequester requester;
@@ -4142,7 +4143,8 @@ void tst_qquickvisualdatamodel::asynchronousMove()
engine.rootContext()->setContextProperty("myModel", &model);
- QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(c.create());
+ QScopedPointer<QObject> o(c.create());
+ QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(o.data());
QVERIFY(visualModel);
ItemRequester requester;
@@ -4190,7 +4192,8 @@ void tst_qquickvisualdatamodel::asynchronousCancel()
engine.rootContext()->setContextProperty("myModel", &model);
- QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(c.create());
+ QScopedPointer<QObject> o(c.create());
+ QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(o.data());
QVERIFY(visualModel);
QQuickItem *item = qobject_cast<QQuickItem*>(visualModel->object(requestIndex, QQmlIncubator::Asynchronous));
@@ -4312,7 +4315,8 @@ void tst_qquickvisualdatamodel::delegateModelChangeDelegate()
c.setData("import QtQml.Models 2.2\nDelegateModel {}\n", QUrl());
QCOMPARE(c.status(), QQmlComponent::Ready);
- QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(c.create(context.data()));
+ QScopedPointer<QObject> o(c.create(context.data()));
+ QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(o.data());
QVERIFY(visualModel);
visualModel->setModel(QVariant(3));
diff --git a/tests/auto/quick/qquickwindow/CMakeLists.txt b/tests/auto/quick/qquickwindow/CMakeLists.txt
index 6e8cef42b2..0bec56ea73 100644
--- a/tests/auto/quick/qquickwindow/CMakeLists.txt
+++ b/tests/auto/quick/qquickwindow/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickwindow Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickwindow LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/qquickwindow/data/conflictingVisibleFalse.qml b/tests/auto/quick/qquickwindow/data/conflictingVisibleFalse.qml
new file mode 100644
index 0000000000..98f374a741
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/conflictingVisibleFalse.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Window {
+ visibility: Window.Windowed
+ visible: false
+}
diff --git a/tests/auto/quick/qquickwindow/data/conflictingVisibleTrue.qml b/tests/auto/quick/qquickwindow/data/conflictingVisibleTrue.qml
new file mode 100644
index 0000000000..52d9b2fc34
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/conflictingVisibleTrue.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Window {
+ visibility: Window.Hidden
+ visible: true
+}
diff --git a/tests/auto/quick/qquickwindow/data/eventTypes.qml b/tests/auto/quick/qquickwindow/data/eventTypes.qml
new file mode 100644
index 0000000000..05d80bfbd1
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/eventTypes.qml
@@ -0,0 +1,20 @@
+import QtQuick
+import QtQuick.Window
+
+Window {
+ id: root
+ function handleKey(e: KeyEvent) {}
+ function handleMouse(e: MouseEvent) {}
+ function handleWheel(e: WheelEvent) {}
+ function handleClose(e: CloseEvent) {}
+
+ Item {
+ Keys.onDeletePressed: root.handleKey
+ MouseArea {
+ onClicked: root.handleMouse
+ onWheel: root.handleWheel
+ }
+ }
+
+ onClosing: handleClose
+}
diff --git a/tests/auto/quick/qquickwindow/data/maximized.qml b/tests/auto/quick/qquickwindow/data/maximized.qml
new file mode 100644
index 0000000000..4d7054645b
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/maximized.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Window {
+ visibility: Window.Maximized
+}
diff --git a/tests/auto/quick/qquickwindow/data/shortcut.qml b/tests/auto/quick/qquickwindow/data/shortcut.qml
index 3b92cdf2e0..892eca1727 100644
--- a/tests/auto/quick/qquickwindow/data/shortcut.qml
+++ b/tests/auto/quick/qquickwindow/data/shortcut.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.9
import QtQuick.Window 2.2
diff --git a/tests/auto/quick/qquickwindow/data/shortcutOverride.qml b/tests/auto/quick/qquickwindow/data/shortcutOverride.qml
index e5d35a984d..960035c10f 100644
--- a/tests/auto/quick/qquickwindow/data/shortcutOverride.qml
+++ b/tests/auto/quick/qquickwindow/data/shortcutOverride.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quick/qquickwindow/data/visibilityDoesntClobberWindowState.qml b/tests/auto/quick/qquickwindow/data/visibilityDoesntClobberWindowState.qml
new file mode 100644
index 0000000000..af899ec5dd
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/visibilityDoesntClobberWindowState.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Window {
+
+}
diff --git a/tests/auto/quick/qquickwindow/data/windowattached.qml b/tests/auto/quick/qquickwindow/data/windowattached.qml
index 66083db428..2f0d08984f 100644
--- a/tests/auto/quick/qquickwindow/data/windowattached.qml
+++ b/tests/auto/quick/qquickwindow/data/windowattached.qml
@@ -1,5 +1,4 @@
-import QtQuick 2.4
-import QtQuick.Window 2.2
+import QtQuick
Rectangle {
id: root
@@ -19,6 +18,7 @@ Rectangle {
property Window extraWindow: Window {
objectName: "extraWindow"
title: "extra window"
+ transientParent: null
Text {
objectName: "extraWindowText"
anchors.centerIn: parent
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index d0f3e4156a..a80827a663 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
@@ -27,13 +27,12 @@
#include <QOperatingSystemVersion>
#include <functional>
#include <QtGui/private/qeventpoint_p.h>
-#include <QtGui/private/qrhi_p.h>
+#include <rhi/qrhi.h>
#if QT_CONFIG(opengl)
#include <QOpenGLContext>
#endif
#if QT_CONFIG(vulkan)
#include <QVulkanInstance>
-#include <QtGui/private/qrhivulkan_p.h>
#endif
Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
@@ -547,6 +546,13 @@ private slots:
void graphicsConfiguration();
+ void visibleVsVisibility_data();
+ void visibleVsVisibility();
+
+ void visibilityDoesntClobberWindowState();
+
+ void eventTypes();
+
private:
QPointingDevice *touchDevice; // TODO make const after fixing QTBUG-107864
const QPointingDevice *touchDeviceWithVelocity;
@@ -2924,8 +2930,8 @@ void tst_qquickwindow::test_circleMapItem()
mat->setObjectName("Top Item/MouseArea");
mat->setSize(QSizeF(40, 40));
- QSignalSpy bottomSpy(mab, SIGNAL(clicked(QQuickMouseEvent *)));
- QSignalSpy topSpy(mat, SIGNAL(clicked(QQuickMouseEvent *)));
+ QSignalSpy bottomSpy(mab, SIGNAL(clicked(QQuickMouseEvent*)));
+ QSignalSpy topSpy(mat, SIGNAL(clicked(QQuickMouseEvent*)));
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
@@ -3295,57 +3301,48 @@ public:
*/
bool testFilterPreConditions() const { return !m_filterNotPreAccepted; }
static QVector<DeliveryRecord> &deliveryList() { return m_deliveryList; }
- static QSet<QEvent::Type> &includedEventTypes()
+ static void setExpectedDeliveryList(const QVector<DeliveryRecord> &v) { m_expectedDeliveryList = v; }
+
+ bool isRelevant(QQuickItem *receiver, QEvent *e)
{
- if (m_includedEventTypes.isEmpty())
- m_includedEventTypes << QEvent::MouseButtonPress;
- return m_includedEventTypes;
+ if (receiver->acceptTouchEvents())
+ return e->type() == QEvent::TouchBegin;
+ return e->type() == QEvent::MouseButtonPress;
}
- static void setExpectedDeliveryList(const QVector<DeliveryRecord> &v) { m_expectedDeliveryList = v; }
protected:
bool childMouseEventFilter(QQuickItem *i, QEvent *e) override
{
+ if (!isRelevant(i, e))
+ return QQuickRectangle::childMouseEventFilter(i, e);
+
appendEvent(this, i, e);
- switch (e->type()) {
- case QEvent::MouseButtonPress:
- if (!e->isAccepted())
- m_filterNotPreAccepted = true;
- e->setAccepted(m_filterAccepts);
- // qCDebug(lcTests) << objectName() << i->objectName();
- return m_filterReturns;
- default:
- break;
- }
- return QQuickRectangle::childMouseEventFilter(i, e);
+ if (!e->isAccepted())
+ m_filterNotPreAccepted = true;
+ e->setAccepted(m_filterAccepts);
+ return m_filterReturns;
}
bool event(QEvent *e) override
{
+ if (!isRelevant(this, e))
+ QQuickRectangle::event(e);
+
appendEvent(nullptr, this, e);
- switch (e->type()) {
- case QEvent::MouseButtonPress:
- // qCDebug(lcTests) << objectName();
- e->setAccepted(m_eventAccepts);
- return true;
- default:
- break;
- }
- return QQuickRectangle::event(e);
+ e->setAccepted(m_eventAccepts);
+ return true;
}
private:
- static void appendEvent(QQuickItem *filter, QQuickItem *receiver, QEvent *event) {
- if (includedEventTypes().contains(event->type())) {
- auto record = DeliveryRecord(filter ? filter->objectName() : QString(), receiver ? receiver->objectName() : QString());
- int i = m_deliveryList.size();
- if (m_expectedDeliveryList.size() > i && m_expectedDeliveryList[i] == record)
- qCDebug(lcTests).noquote().nospace() << i << ": " << record;
- else
- qCDebug(lcTests).noquote().nospace() << i << ": " << record
- << ", expected " << (m_expectedDeliveryList.size() > i ? m_expectedDeliveryList[i].toString() : QLatin1String("nothing")) << " <---";
- m_deliveryList << record;
- }
+ static void appendEvent(QQuickItem *filter, QQuickItem *receiver, QEvent *) {
+ auto record = DeliveryRecord(filter ? filter->objectName() : QString(), receiver ? receiver->objectName() : QString());
+ int i = m_deliveryList.size();
+ if (m_expectedDeliveryList.size() > i && m_expectedDeliveryList[i] == record)
+ qCDebug(lcTests).noquote().nospace() << i << ": " << record;
+ else
+ qCDebug(lcTests).noquote().nospace() << i << ": " << record
+ << ", expected " << (m_expectedDeliveryList.size() > i ? m_expectedDeliveryList[i].toString() : QLatin1String("nothing")) << " <---";
+ m_deliveryList << record;
}
bool m_eventAccepts;
bool m_filterReturns;
@@ -3355,12 +3352,10 @@ private:
// list of (filtering-parent . receiver) pairs
static DeliveryRecordVector m_expectedDeliveryList;
static DeliveryRecordVector m_deliveryList;
- static QSet<QEvent::Type> m_includedEventTypes;
};
DeliveryRecordVector EventItem::m_expectedDeliveryList;
DeliveryRecordVector EventItem::m_deliveryList;
-QSet<QEvent::Type> EventItem::m_includedEventTypes;
typedef QVector<const char*> CharStarVector;
@@ -3385,11 +3380,21 @@ void tst_qquickwindow::testChildMouseEventFilter_data()
// r0->r1->r2->r3
//
QTest::addColumn<QPoint>("mousePos");
+ QTest::addColumn<QString>("eventMode");
QTest::addColumn<InputState>("inputState");
QTest::addColumn<DeliveryRecordVector>("expectedDeliveryOrder");
- QTest::newRow("if filtered and rejected, do not deliver it to the item that filtered it")
+ for (const QString &eventMode : {
+ QStringLiteral("mouse"),
+ QStringLiteral("touch"),
+ QStringLiteral("touchToMouse")
+ }) {
+
+ #define desc(txt) qPrintable(QString("%1 events, ").arg(eventMode) + txt)
+
+ QTest::newRow(desc("if filtered and rejected, do not deliver it to the item that filtered it"))
<< QPoint(100, 100)
+ << eventMode
<< InputState({
// | event() | child mouse filter
// +---------+---------+---------+---------
@@ -3407,8 +3412,9 @@ void tst_qquickwindow::testChildMouseEventFilter_data()
<< DeliveryRecord("r1")
);
- QTest::newRow("no filtering, no accepting")
+ QTest::newRow(desc("no filtering, no accepting"))
<< QPoint(100, 100)
+ << eventMode
<< InputState({
// | event() | child mouse filter
// +---------+---------+---------+---------
@@ -3427,8 +3433,9 @@ void tst_qquickwindow::testChildMouseEventFilter_data()
<< DeliveryRecord("root")
);
- QTest::newRow("all filtering, no accepting")
+ QTest::newRow(desc("all filtering, no accepting"))
<< QPoint(100, 100)
+ << eventMode
<< InputState({
// | event() | child mouse filter
// +---------+---------+---------+---------
@@ -3454,8 +3461,9 @@ void tst_qquickwindow::testChildMouseEventFilter_data()
);
- QTest::newRow("some filtering, no accepting")
+ QTest::newRow(desc("some filtering, no accepting"))
<< QPoint(100, 100)
+ << eventMode
<< InputState({
// | event() | child mouse filter
// +---------+---------+---------+---------
@@ -3479,8 +3487,9 @@ void tst_qquickwindow::testChildMouseEventFilter_data()
<< DeliveryRecord("root")
);
- QTest::newRow("r1 accepts")
+ QTest::newRow(desc("r1 accepts"))
<< QPoint(100, 100)
+ << eventMode
<< InputState({
// | event() | child mouse filter
// +---------+---------+---------+---------
@@ -3502,8 +3511,9 @@ void tst_qquickwindow::testChildMouseEventFilter_data()
<< DeliveryRecord("r1")
);
- QTest::newRow("r1 rejects and filters")
+ QTest::newRow(desc("r1 rejects and filters"))
<< QPoint(100, 100)
+ << eventMode
<< InputState({
// | event() | child mouse filter
// +---------+---------+---------+---------
@@ -3526,12 +3536,13 @@ void tst_qquickwindow::testChildMouseEventFilter_data()
<< DeliveryRecord("r0")
<< DeliveryRecord("root")
);
-
+ }
}
void tst_qquickwindow::testChildMouseEventFilter()
{
QFETCH(QPoint, mousePos);
+ QFETCH(QString, eventMode);
QFETCH(InputState, inputState);
QFETCH(DeliveryRecordVector, expectedDeliveryOrder);
@@ -3546,21 +3557,28 @@ void tst_qquickwindow::testChildMouseEventFilter()
QScopedPointer<EventFilter> rootFilter(new EventFilter);
root->installEventFilter(rootFilter.data());
+ const bool useMouseEvents = eventMode == "mouse";
+ const bool acceptTouchEvents = eventMode == "touch";
+
// Create 4 items; each item a child of the previous item.
EventItem *r[4];
r[0] = new EventItem(root);
r[0]->setColor(QColor(0x404040));
r[0]->setWidth(200);
r[0]->setHeight(200);
+ r[0]->setAcceptTouchEvents(acceptTouchEvents);
r[1] = new EventItem(r[0]);
r[1]->setColor(QColor(0x606060));
+ r[1]->setAcceptTouchEvents(acceptTouchEvents);
r[2] = new EventItem(r[1]);
r[2]->setColor(Qt::red);
+ r[2]->setAcceptTouchEvents(acceptTouchEvents);
r[3] = new EventItem(r[2]);
r[3]->setColor(Qt::green);
+ r[3]->setAcceptTouchEvents(acceptTouchEvents);
for (uint i = 0; i < sizeof(r)/sizeof(EventItem*); ++i) {
r[i]->setEventAccepts(inputState.r[i].eventAccepts);
@@ -3577,7 +3595,11 @@ void tst_qquickwindow::testChildMouseEventFilter()
DeliveryRecordVector &actualDeliveryOrder = EventItem::deliveryList();
actualDeliveryOrder.clear();
- QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, mousePos);
+
+ if (useMouseEvents)
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, mousePos);
+ else
+ QTest::touchEvent(&window, touchDevice).press(0, mousePos, &window);
// Check if event got delivered to the root item. If so, append it to the list of items the event got delivered to
if (rootFilter->events.contains(QEvent::MouseButtonPress))
@@ -3593,8 +3615,11 @@ void tst_qquickwindow::testChildMouseEventFilter()
QVERIFY(item->testFilterPreConditions());
}
- // "restore" mouse state
- QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, mousePos);
+ // "restore" mouse/touch state
+ if (useMouseEvents)
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, mousePos);
+ else
+ QTest::touchEvent(&window, touchDevice).release(0, mousePos, &window);
}
void tst_qquickwindow::cleanupGrabsOnRelease()
@@ -3849,7 +3874,7 @@ void tst_qquickwindow::rendererInterfaceWithRenderControl_data()
#ifdef Q_OS_WIN
QTest::newRow("D3D11") << QSGRendererInterface::Direct3D11Rhi;
#endif
-#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
+#if QT_CONFIG(metal)
QTest::newRow("Metal") << QSGRendererInterface::MetalRhi;
#endif
}
@@ -4083,6 +4108,87 @@ void tst_qquickwindow::graphicsConfiguration()
#endif
}
+void tst_qquickwindow::visibleVsVisibility_data()
+{
+ QTest::addColumn<QUrl>("qmlfile");
+ QTest::addColumn<bool>("expectVisible");
+ QTest::addColumn<bool>("expectConflictingPropertyWarning");
+
+ QTest::newRow("default invisible") << testFileUrl("window.qml") << false << false;
+ QTest::newRow("just visibility") << testFileUrl("maximized.qml") << true << false;
+ // In these conflicting cases, the 'visibility' property "wins" (see QQuickWindowQmlImpl::setWindowVisibility())
+ QTest::newRow("conflicting invisible") << testFileUrl("conflictingVisibleFalse.qml") << true << true;
+ QTest::newRow("conflicting visible") << testFileUrl("conflictingVisibleTrue.qml") << false << true;
+}
+
+void tst_qquickwindow::visibleVsVisibility()
+{
+ QFETCH(QUrl, qmlfile);
+ QFETCH(bool, expectVisible);
+ QFETCH(bool, expectConflictingPropertyWarning);
+
+ const QString warningMsg = qmlfile.toString() + ":3:1: QML Window: Conflicting properties 'visible' and 'visibility'";
+
+ QTest::failOnWarning(QRegularExpression(".*"));
+ if (expectConflictingPropertyWarning)
+ QTest::ignoreMessage(QtWarningMsg, warningMsg.toUtf8().data());
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(qmlfile);
+ QObject *created = component.create();
+ QScopedPointer<QObject> cleanup(created);
+ QVERIFY(created);
+
+ QQuickWindow *window = qobject_cast<QQuickWindow*>(created);
+ QVERIFY(window);
+ QCOMPARE(window->isVisible(), expectVisible);
+}
+
+void tst_qquickwindow::visibilityDoesntClobberWindowState()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("visibilityDoesntClobberWindowState.qml"));
+ QObject *created = component.create();
+ QScopedPointer<QObject> cleanup(created);
+ QVERIFY(created);
+
+ QQuickWindow *window = qobject_cast<QQuickWindow*>(created);
+ QVERIFY(window);
+
+ window->showMaximized();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ QCOMPARE(window->windowState(), Qt::WindowMaximized);
+
+ window->setProperty("visible", false);
+ window->setProperty("visible", true);
+
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ QCOMPARE(window->windowState(), Qt::WindowMaximized);
+
+ EventFilter eventFilter;
+ window->installEventFilter(&eventFilter);
+ window->setProperty("visibility", QWindow::FullScreen);
+ QTRY_VERIFY(eventFilter.events.contains(QEvent::WindowStateChange));
+ QTRY_COMPARE(window->windowState(), Qt::WindowFullScreen);
+
+ eventFilter.events.clear();
+ window->setWindowState(Qt::WindowMaximized);
+ QTRY_VERIFY(eventFilter.events.contains(QEvent::WindowStateChange));
+ QTRY_COMPARE(window->windowState(), Qt::WindowMaximized);
+}
+
+void tst_qquickwindow::eventTypes()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("eventTypes.qml"));
+ QObject *created = component.create();
+ QScopedPointer<QObject> cleanup(created);
+ QVERIFY(created);
+}
+
QTEST_MAIN(tst_qquickwindow)
#include "tst_qquickwindow.moc"
diff --git a/tests/auto/quick/qquickwindowcontainer/CMakeLists.txt b/tests/auto/quick/qquickwindowcontainer/CMakeLists.txt
new file mode 100644
index 0000000000..6a02080cfc
--- /dev/null
+++ b/tests/auto/quick/qquickwindowcontainer/CMakeLists.txt
@@ -0,0 +1,37 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickwindowcontainer LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+file(GLOB_RECURSE test_data_glob
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ data/*)
+list(APPEND test_data ${test_data_glob})
+
+qt_internal_add_test(tst_qquickwindowcontainer
+ SOURCES
+ tst_qquickwindowcontainer.cpp
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::Gui
+ Qt::GuiPrivate
+ Qt::QmlPrivate
+ Qt::QuickPrivate
+ Qt::QuickTestUtilsPrivate
+ TESTDATA ${test_data}
+)
+
+if(ANDROID OR IOS)
+ set(TESTDATA_DIR ":/data")
+else()
+ set(TESTDATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/data")
+endif()
+
+qt_internal_extend_target(tst_qquickwindowcontainer
+ DEFINES
+ QT_QMLTEST_DATADIR="${TESTDATA_DIR}"
+)
diff --git a/tests/auto/quick/qquickwindowcontainer/data/basicFunctionality_container.qml b/tests/auto/quick/qquickwindowcontainer/data/basicFunctionality_container.qml
new file mode 100644
index 0000000000..3e0bd8ae1c
--- /dev/null
+++ b/tests/auto/quick/qquickwindowcontainer/data/basicFunctionality_container.qml
@@ -0,0 +1,15 @@
+import QtQuick
+
+Window {
+ id: topLevel
+ Item {
+ id: childItem
+ x: 100; y: 100
+
+ WindowContainer {
+ window: Window {
+ objectName: "childWindow"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickwindowcontainer/data/basicFunctionality_item.qml b/tests/auto/quick/qquickwindowcontainer/data/basicFunctionality_item.qml
new file mode 100644
index 0000000000..301c5f1494
--- /dev/null
+++ b/tests/auto/quick/qquickwindowcontainer/data/basicFunctionality_item.qml
@@ -0,0 +1,15 @@
+import QtQuick
+
+Window {
+ id: topLevel
+ Item {
+ id: childItem
+ x: 100; y: 100
+
+ Window {
+ parent: childItem
+ objectName: "childWindow"
+ x: 100; y: 100
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickwindowcontainer/data/basicFunctionality_window.qml b/tests/auto/quick/qquickwindowcontainer/data/basicFunctionality_window.qml
new file mode 100644
index 0000000000..d6d2c9dff0
--- /dev/null
+++ b/tests/auto/quick/qquickwindowcontainer/data/basicFunctionality_window.qml
@@ -0,0 +1,10 @@
+import QtQuick
+
+Window {
+ id: topLevel
+ Window {
+ parent: topLevel
+ objectName: "childWindow"
+ x: 100; y: 100
+ }
+}
diff --git a/tests/auto/quick/qquickwindowcontainer/data/deferredVisibilityWithoutWindow.qml b/tests/auto/quick/qquickwindowcontainer/data/deferredVisibilityWithoutWindow.qml
new file mode 100644
index 0000000000..3bd882defe
--- /dev/null
+++ b/tests/auto/quick/qquickwindowcontainer/data/deferredVisibilityWithoutWindow.qml
@@ -0,0 +1,11 @@
+import QtQuick
+
+Window {
+ id: topLevel
+ visible: true
+ Window {
+ parent: topLevel
+ objectName: "childWindow"
+ visible: true
+ }
+}
diff --git a/tests/auto/quick/qquickwindowcontainer/data/windowComponent.qml b/tests/auto/quick/qquickwindowcontainer/data/windowComponent.qml
new file mode 100644
index 0000000000..48a067030b
--- /dev/null
+++ b/tests/auto/quick/qquickwindowcontainer/data/windowComponent.qml
@@ -0,0 +1,28 @@
+import QtQuick
+
+Window {
+ Item { id: itemParent; objectName: "itemParent" }
+ Window { id: windowParent; objectName: "windowParent" }
+
+ property QtObject window_item: null
+ property QtObject window_window: null
+
+ property QtObject window_item_parent: null
+ property QtObject window_window_parent: null
+
+ Component { id: windowComponent; Window{} }
+
+ Component.onCompleted: {
+ // Windows created with QObjects, Items, or Windows as their parent
+ // do not their visual parent set via auto-parenting -- only their
+ // transient parent.
+ window_item = windowComponent.createObject(itemParent);
+ window_window = windowComponent.createObject(windowParent);
+
+ // A visual parent must be set explicitly
+ window_item_parent = windowComponent.createObject(itemParent);
+ window_item_parent.parent = itemParent;
+ window_window_parent = windowComponent.createObject(windowParent);
+ window_window_parent.parent = windowParent;
+ }
+}
diff --git a/tests/auto/quick/qquickwindowcontainer/tst_qquickwindowcontainer.cpp b/tests/auto/quick/qquickwindowcontainer/tst_qquickwindowcontainer.cpp
new file mode 100644
index 0000000000..ce3cb0a802
--- /dev/null
+++ b/tests/auto/quick/qquickwindowcontainer/tst_qquickwindowcontainer.cpp
@@ -0,0 +1,200 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtTest/qtest.h>
+#include <QtTest/qsignalspy.h>
+
+#include <QtQuickTest/QtQuickTest>
+
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlfile.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlapplicationengine.h>
+
+#include <QtQuick/qquickwindow.h>
+#include <QtQuick/private/qquickwindowcontainer_p.h>
+
+#define TEST_WINDOW_PARENT 0
+
+class tst_QQuickWindowContainer : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_QQuickWindowContainer()
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
+ {
+ }
+
+private slots:
+ void init() override;
+ void cleanup();
+
+ void basicFunctionality_data();
+ void basicFunctionality();
+
+ void windowDestroyed();
+ void windowLifetimeFollowsContainer();
+#if TEST_WINDOW_PARENT
+ void deferredVisibilityWithoutWindow();
+ void windowComponent();
+#endif
+
+private:
+ std::unique_ptr<QQmlApplicationEngine> m_engine;
+};
+
+void tst_QQuickWindowContainer::init()
+{
+ QQmlDataTest::init();
+
+ QString testFile = QTest::currentTestFunction();
+ if (auto *dataTag = QTest::currentDataTag())
+ testFile += QChar('_') % dataTag;
+ testFile += ".qml";
+
+ const auto testUrl = testFileUrl(testFile);
+ if (QFileInfo::exists(QQmlFile::urlToLocalFileOrQrc(testUrl))) {
+ m_engine.reset(new QQmlApplicationEngine(testUrl));
+ QVERIFY(m_engine->rootObjects().size() > 0);
+ }
+}
+
+void tst_QQuickWindowContainer::cleanup()
+{
+ m_engine.reset(nullptr);
+}
+
+void tst_QQuickWindowContainer::basicFunctionality_data()
+{
+ QTest::addColumn<QPoint>("position");
+
+#if TEST_WINDOW_PARENT
+ QTest::newRow("window") << QPoint(100, 100);
+ QTest::newRow("item") << QPoint(200, 200);
+#endif
+ QTest::newRow("container") << QPoint(100, 100);
+}
+
+void tst_QQuickWindowContainer::basicFunctionality()
+{
+ QFETCH(QPoint, position);
+
+ auto *topLevelWindow = qobject_cast<QQuickWindow*>(m_engine->rootObjects().first());
+ auto *childWindow = topLevelWindow->findChild<QWindow*>("childWindow");
+ QVERIFY(childWindow);
+
+ // The top level isn't visible yet, so there hasn't been any
+ // polish, which we rely on for the actual reparenting.
+ QCOMPARE(childWindow->parent(), nullptr);
+
+ topLevelWindow->setVisible(true);
+ QVERIFY(QQuickTest::qWaitForPolish(topLevelWindow));
+ QCOMPARE(childWindow->parent(), topLevelWindow);
+
+ QCOMPARE(childWindow->position(), position);
+}
+
+void tst_QQuickWindowContainer::windowDestroyed()
+{
+ std::unique_ptr<QWindow> window(new QWindow);
+
+ QQuickWindowContainer container;
+ QSignalSpy spy(&container, &QQuickWindowContainer::containedWindowChanged);
+
+ container.setContainedWindow(window.get());
+ QCOMPARE(container.containedWindow(), window.get());
+ QCOMPARE(spy.size(), 1);
+
+ window.reset(nullptr);
+
+ QVERIFY(!container.containedWindow());
+ QCOMPARE(spy.size(), 2);
+}
+
+void tst_QQuickWindowContainer::windowLifetimeFollowsContainer()
+{
+ QWindow window;
+ QPointer<QWindow> windowGuard = &window;
+
+ QQuickWindowContainer container;
+ container.setContainedWindow(&window);
+
+ {
+ QQuickWindow quickWindow;
+ container.setParentItem(quickWindow.contentItem());
+ quickWindow.show();
+ QVERIFY(QQuickTest::qWaitForPolish(&quickWindow));
+ QCOMPARE(window.parent(), &quickWindow);
+
+ // Decouple container from Quick window
+ container.setParentItem(nullptr);
+ }
+
+ QVERIFY(windowGuard);
+}
+
+#if TEST_WINDOW_PARENT
+void tst_QQuickWindowContainer::deferredVisibilityWithoutWindow()
+{
+ auto *topLevelWindow = qobject_cast<QQuickWindow*>(m_engine->rootObjects().first());
+ auto *childWindow = topLevelWindow->findChild<QQuickWindow*>("childWindow");
+ QVERIFY(childWindow);
+ QVERIFY(QQuickTest::qWaitForPolish(topLevelWindow));
+
+ QSignalSpy spy(childWindow, &QWindow::visibleChanged);
+ m_engine.reset(nullptr);
+
+ // Deleting the engine should only hide the window once,
+ // not hide, show, and then hide again, which would be
+ // the result of applying visibility without a window.
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QQuickWindowContainer::windowComponent()
+{
+ auto *root = qobject_cast<QQuickWindow *>(m_engine->rootObjects().first());
+ QVERIFY(root);
+ auto *itemParent = root->findChild<QQuickItem*>("itemParent");
+ auto *windowParent = root->findChild<QQuickWindow*>("windowParent");
+ QVERIFY(itemParent);
+ QVERIFY(windowParent);
+
+ root->setVisible(true);
+ QVERIFY(QQuickTest::qWaitForPolish(root));
+ windowParent->setVisible(true);
+ QVERIFY(QQuickTest::qWaitForPolish(windowParent));
+
+ QObject *window_item = root->property("window_item").value<QObject*>();
+ QObject *window_window = root->property("window_window").value<QObject*>();
+ QObject *window_item_parent = root->property("window_item_parent").value<QObject*>();
+ QObject *window_window_parent = root->property("window_window_parent").value<QObject*>();
+
+ QVERIFY(window_item);
+ QVERIFY(window_window);
+ QVERIFY(window_item_parent);
+ QVERIFY(window_window_parent);
+
+ QCOMPARE(window_item->parent(), itemParent);
+ QCOMPARE(window_window->parent(), windowParent);
+ QCOMPARE(window_item_parent->parent(), root);
+ QCOMPARE(window_window_parent->parent(), windowParent);
+
+ QCOMPARE(qobject_cast<QQuickWindow *>(window_item)->transientParent(), root);
+ QCOMPARE(qobject_cast<QQuickWindow *>(window_window)->transientParent(), windowParent);
+ QCOMPARE(qobject_cast<QQuickWindow *>(window_item)->parent(), nullptr);
+ QCOMPARE(qobject_cast<QQuickWindow *>(window_window)->parent(), nullptr);
+
+ QEXPECT_FAIL("", "The automatic transient parent logic doesn't account for visual parent", Continue);
+ QCOMPARE(qobject_cast<QQuickWindow *>(window_item_parent)->transientParent(), nullptr);
+ QEXPECT_FAIL("", "The automatic transient parent logic doesn't account for visual parent", Continue);
+ QCOMPARE(qobject_cast<QQuickWindow *>(window_window_parent)->transientParent(), nullptr);
+ QCOMPARE(qobject_cast<QQuickWindow *>(window_item_parent)->parent(), root);
+ QCOMPARE(qobject_cast<QQuickWindow *>(window_window_parent)->parent(), windowParent);
+}
+#endif // TEST_WINDOW_PARENT
+
+QTEST_MAIN(tst_QQuickWindowContainer)
+
+#include "tst_qquickwindowcontainer.moc"
diff --git a/tests/auto/quick/rendernode/CMakeLists.txt b/tests/auto/quick/rendernode/CMakeLists.txt
index 44d1026bf8..db5fac6439 100644
--- a/tests/auto/quick/rendernode/CMakeLists.txt
+++ b/tests/auto/quick/rendernode/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_rendernode Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_rendernode LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/rendernode/data/glsimple.qml b/tests/auto/quick/rendernode/data/glsimple.qml
index 18cc98d6d0..da038476b3 100644
--- a/tests/auto/quick/rendernode/data/glsimple.qml
+++ b/tests/auto/quick/rendernode/data/glsimple.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import Test
diff --git a/tests/auto/quick/rendernode/data/simple.qml b/tests/auto/quick/rendernode/data/simple.qml
index 7a55c742c4..2194d3484f 100644
--- a/tests/auto/quick/rendernode/data/simple.qml
+++ b/tests/auto/quick/rendernode/data/simple.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import Test
diff --git a/tests/auto/quick/rendernode/tst_rendernode.cpp b/tests/auto/quick/rendernode/tst_rendernode.cpp
index 44e1123cd7..b21c1f01b1 100644
--- a/tests/auto/quick/rendernode/tst_rendernode.cpp
+++ b/tests/auto/quick/rendernode/tst_rendernode.cpp
@@ -1,12 +1,12 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
#include <private/qsgrendernode_p.h>
-#include <QtGui/private/qrhi_p.h>
+#include <rhi/qrhi.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
diff --git a/tests/auto/quick/scenegraph/BLACKLIST b/tests/auto/quick/scenegraph/BLACKLIST
deleted file mode 100644
index 80f39de9ab..0000000000
--- a/tests/auto/quick/scenegraph/BLACKLIST
+++ /dev/null
@@ -1,3 +0,0 @@
-# QTBUG-102589
-[render]
-android
diff --git a/tests/auto/quick/scenegraph/CMakeLists.txt b/tests/auto/quick/scenegraph/CMakeLists.txt
index ba6c362222..c8d8ad34c1 100644
--- a/tests/auto/quick/scenegraph/CMakeLists.txt
+++ b/tests/auto/quick/scenegraph/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_scenegraph Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_scenegraph LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -26,6 +32,16 @@ qt_internal_add_test(tst_scenegraph
TESTDATA ${test_data}
)
+qt_internal_add_shaders(tst_scenegraph "shaders"
+ BATCHABLE
+ PRECOMPILE
+ OPTIMIZED
+ PREFIX
+ "/"
+ FILES
+ "data/render_bug37422.frag"
+)
+
#### Keys ignored in scope 1:.:.:scenegraph.pro:<TRUE>:
# OTHER_FILES = "data/render_OutOfFloatRange.qml" "data/simple.qml" "data/render_ImageFiltering.qml"
diff --git a/tests/auto/quick/scenegraph/data/RenderTestBase.qml b/tests/auto/quick/scenegraph/data/RenderTestBase.qml
index 8369ddf25b..c753c76512 100644
--- a/tests/auto/quick/scenegraph/data/RenderTestBase.qml
+++ b/tests/auto/quick/scenegraph/data/RenderTestBase.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/scenegraph/data/manyWindows_dftext.qml b/tests/auto/quick/scenegraph/data/manyWindows_dftext.qml
index 7952799bc1..4e0107c416 100644
--- a/tests/auto/quick/scenegraph/data/manyWindows_dftext.qml
+++ b/tests/auto/quick/scenegraph/data/manyWindows_dftext.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/scenegraph/data/manyWindows_image.qml b/tests/auto/quick/scenegraph/data/manyWindows_image.qml
index 53e8991559..8db982ce52 100644
--- a/tests/auto/quick/scenegraph/data/manyWindows_image.qml
+++ b/tests/auto/quick/scenegraph/data/manyWindows_image.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/scenegraph/data/manyWindows_ntext.qml b/tests/auto/quick/scenegraph/data/manyWindows_ntext.qml
index 62d676c124..9792a0c3ab 100644
--- a/tests/auto/quick/scenegraph/data/manyWindows_ntext.qml
+++ b/tests/auto/quick/scenegraph/data/manyWindows_ntext.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/scenegraph/data/manyWindows_rects.qml b/tests/auto/quick/scenegraph/data/manyWindows_rects.qml
index 29cdb4959d..d2b9ace55f 100644
--- a/tests/auto/quick/scenegraph/data/manyWindows_rects.qml
+++ b/tests/auto/quick/scenegraph/data/manyWindows_rects.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/scenegraph/data/renderControl_rect.qml b/tests/auto/quick/scenegraph/data/renderControl_rect.qml
index e2c9c07430..3c24bf57fd 100644
--- a/tests/auto/quick/scenegraph/data/renderControl_rect.qml
+++ b/tests/auto/quick/scenegraph/data/renderControl_rect.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/scenegraph/data/render_AlphaOverlapRebuild.qml b/tests/auto/quick/scenegraph/data/render_AlphaOverlapRebuild.qml
index a586d7417b..e9a72cfddd 100644
--- a/tests/auto/quick/scenegraph/data/render_AlphaOverlapRebuild.qml
+++ b/tests/auto/quick/scenegraph/data/render_AlphaOverlapRebuild.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/scenegraph/data/render_BreakOpacityBatch.qml b/tests/auto/quick/scenegraph/data/render_BreakOpacityBatch.qml
index ff9e1f7412..9f4fd9b482 100644
--- a/tests/auto/quick/scenegraph/data/render_BreakOpacityBatch.qml
+++ b/tests/auto/quick/scenegraph/data/render_BreakOpacityBatch.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/scenegraph/data/render_DrawSets.qml b/tests/auto/quick/scenegraph/data/render_DrawSets.qml
index cf3f68db8c..ab1a50098b 100644
--- a/tests/auto/quick/scenegraph/data/render_DrawSets.qml
+++ b/tests/auto/quick/scenegraph/data/render_DrawSets.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import SceneGraphTest 1.0
diff --git a/tests/auto/quick/scenegraph/data/render_ImageFiltering.qml b/tests/auto/quick/scenegraph/data/render_ImageFiltering.qml
index a52265ab0c..1a2d1b2e1c 100644
--- a/tests/auto/quick/scenegraph/data/render_ImageFiltering.qml
+++ b/tests/auto/quick/scenegraph/data/render_ImageFiltering.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/scenegraph/data/render_Mipmap.qml b/tests/auto/quick/scenegraph/data/render_Mipmap.qml
index fd4f689b74..858f4b2fef 100644
--- a/tests/auto/quick/scenegraph/data/render_Mipmap.qml
+++ b/tests/auto/quick/scenegraph/data/render_Mipmap.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.3
import QtQuick.Window 2.2
diff --git a/tests/auto/quick/scenegraph/data/render_MovingOverlap.qml b/tests/auto/quick/scenegraph/data/render_MovingOverlap.qml
index 7b1cef32f2..15cc358023 100644
--- a/tests/auto/quick/scenegraph/data/render_MovingOverlap.qml
+++ b/tests/auto/quick/scenegraph/data/render_MovingOverlap.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/scenegraph/data/render_OpacityThroughBatchRoot.qml b/tests/auto/quick/scenegraph/data/render_OpacityThroughBatchRoot.qml
index 49f9fbf77b..a26ba374a6 100644
--- a/tests/auto/quick/scenegraph/data/render_OpacityThroughBatchRoot.qml
+++ b/tests/auto/quick/scenegraph/data/render_OpacityThroughBatchRoot.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/scenegraph/data/render_OutOfFloatRange.qml b/tests/auto/quick/scenegraph/data/render_OutOfFloatRange.qml
index c80256dfb2..a4262ed1f7 100644
--- a/tests/auto/quick/scenegraph/data/render_OutOfFloatRange.qml
+++ b/tests/auto/quick/scenegraph/data/render_OutOfFloatRange.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/scenegraph/data/render_Overlap.qml b/tests/auto/quick/scenegraph/data/render_Overlap.qml
index 2b2cc0b6ea..fafe103ef6 100644
--- a/tests/auto/quick/scenegraph/data/render_Overlap.qml
+++ b/tests/auto/quick/scenegraph/data/render_Overlap.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/scenegraph/data/render_StackingOrder.qml b/tests/auto/quick/scenegraph/data/render_StackingOrder.qml
index 562670f624..416a5db329 100644
--- a/tests/auto/quick/scenegraph/data/render_StackingOrder.qml
+++ b/tests/auto/quick/scenegraph/data/render_StackingOrder.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/scenegraph/data/render_bug37422.frag.qsb b/tests/auto/quick/scenegraph/data/render_bug37422.frag.qsb
deleted file mode 100644
index b8770b1332..0000000000
--- a/tests/auto/quick/scenegraph/data/render_bug37422.frag.qsb
+++ /dev/null
Binary files differ
diff --git a/tests/auto/quick/scenegraph/data/render_bug37422.qml b/tests/auto/quick/scenegraph/data/render_bug37422.qml
index 440159aef0..d9b294c766 100644
--- a/tests/auto/quick/scenegraph/data/render_bug37422.qml
+++ b/tests/auto/quick/scenegraph/data/render_bug37422.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
@@ -48,7 +48,7 @@ RenderTestBase
y: 10
fragmentShader: GraphicsInfo.shaderType === GraphicsInfo.GLSL
? "varying highp vec2 qt_TexCoord0; void main() { gl_FragColor = vec4(1, 0, 0, 1); }"
- : "file:data/render_bug37422.frag.qsb"
+ : "qrc:/data/render_bug37422.frag.qsb"
Rectangle {
width: 5
diff --git a/tests/auto/quick/scenegraph/data/simple.qml b/tests/auto/quick/scenegraph/data/simple.qml
index 97009b451d..a8eb2ad516 100644
--- a/tests/auto/quick/scenegraph/data/simple.qml
+++ b/tests/auto/quick/scenegraph/data/simple.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
index 64c50f74ae..1d76fe3181 100644
--- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp
+++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
@@ -96,6 +96,7 @@ private slots:
void createTextureFromImage();
void withAdoptedRhi();
void resizeTextureFromImage();
+ void textureNativeInterface();
private:
QQuickView *createView(const QString &file, QWindow *parent = nullptr, int x = -1, int y = -1, int w = -1, int h = -1);
@@ -289,7 +290,9 @@ struct Sample {
}
bool check(const QImage &image, qreal scale) {
- QColor color(image.pixel(x * scale, y * scale));
+ const int scaledX = qRound(x * scale);
+ const int scaledY = qRound(y * scale);
+ const QColor color(image.pixel(scaledX, scaledY));
return qAbs(color.redF() - r) <= tolerance
&& qAbs(color.greenF() - g) <= tolerance
&& qAbs(color.blueF() - b) <= tolerance;
@@ -370,16 +373,16 @@ void tst_SceneGraph::render_data()
QRegularExpression baseSamples("#base: *(\\d+) *(\\d+) *(\\d\\.\\d+) *(\\d\\.\\d+) *(\\d\\.\\d+) *(\\d\\.\\d+)");
QRegularExpression finalSamples("#final: *(\\d+) *(\\d+) *(\\d\\.\\d+) *(\\d\\.\\d+) *(\\d\\.\\d+) *(\\d\\.\\d+)");
- foreach (QString fileName, files) {
+ for (QString fileName : std::as_const(files)) {
QFile file(testFile(fileName));
if (!file.open(QFile::ReadOnly)) {
qFatal("render_data: QFile::open failed! file=%s, error=%s",
qPrintable(fileName), qPrintable(file.errorString()));
}
- QStringList contents = QString::fromLatin1(file.readAll()).split(QLatin1Char('\n'));
+ const QStringList contents = QString::fromLatin1(file.readAll()).split(QLatin1Char('\n'));
int samples = -1;
- foreach (QString line, contents) {
+ for (const QString &line : contents) {
auto match = sampleCount.match(line);
if (match.hasMatch()) {
samples = match.captured(1).toInt();
@@ -390,7 +393,7 @@ void tst_SceneGraph::render_data()
qFatal("render_data: failed to find string '#samples: [count], file=%s", qPrintable(fileName));
QList<Sample> baseStage, finalStage;
- foreach (QString line, contents) {
+ for (const QString &line : contents) {
auto match = baseSamples.match(line);
if (match.hasMatch())
baseStage << sample_from_regexp(&match);
@@ -430,6 +433,10 @@ void tst_SceneGraph::render()
// ideal world.
// Just keep this in mind when writing tests.
qreal scale = view.devicePixelRatio();
+ const bool isIntegerScale = qFuzzyIsNull(qreal(qFloor(scale)) - scale);
+
+ if (file == "render_OutOfFloatRange.qml" && !isIntegerScale)
+ QSKIP("render_OutOfFloatRange doesn't work with non-integer scaling factors");
// Grab the window and check all our base stage samples
QImage content = view.grabWindow();
@@ -777,6 +784,59 @@ void tst_SceneGraph::resizeTextureFromImage()
TestOffscreenScene::cleanup();
}
+void tst_SceneGraph::textureNativeInterface()
+{
+ if (!isRunningOnRhi())
+ QSKIP("Skipping texture native interface tests due to not running with QRhi");
+
+ // test it offscreen because we want to do QSG stuff here on the main thread
+ QScopedPointer<TestOffscreenScene> scene(createOffscreenScene(testFileUrl(QLatin1String("renderControl_rect.qml"))));
+ QVERIFY(scene->renderControl && scene->window && scene->rootItem);
+
+ QImage image(512, 512, QImage::Format_RGBA8888);
+
+ QScopedPointer<QSGTexture> texture(scene->window->createTextureFromImage(image, QQuickWindow::TextureHasAlphaChannel));
+ QVERIFY(texture.data());
+
+ commitTexture(scene->window->rhi(), texture.data());
+
+#if QT_CONFIG(metal)
+ if (scene->window->graphicsApi() == QSGRendererInterface::Metal) {
+ auto texNatIf = texture->nativeInterface<QNativeInterface::QSGMetalTexture>();
+ QVERIFY(texNatIf);
+ QVERIFY(texNatIf->nativeTexture());
+ }
+#endif
+
+#if defined(Q_OS_WIN)
+ if (scene->window->graphicsApi() == QSGRendererInterface::Direct3D11) {
+ auto texNatIf = texture->nativeInterface<QNativeInterface::QSGD3D11Texture>();
+ QVERIFY(texNatIf);
+ QVERIFY(texNatIf->nativeTexture());
+ } else if (scene->window->graphicsApi() == QSGRendererInterface::Direct3D12) {
+ auto texNatIf = texture->nativeInterface<QNativeInterface::QSGD3D12Texture>();
+ QVERIFY(texNatIf);
+ QVERIFY(texNatIf->nativeTexture());
+ }
+#endif
+
+#if QT_CONFIG(opengl)
+ if (scene->window->graphicsApi() == QSGRendererInterface::OpenGL) {
+ auto texNatIf = texture->nativeInterface<QNativeInterface::QSGOpenGLTexture>();
+ QVERIFY(texNatIf);
+ QVERIFY(texNatIf->nativeTexture());
+ }
+#endif
+
+#if QT_CONFIG(vulkan)
+ if (scene->window->graphicsApi() == QSGRendererInterface::Vulkan) {
+ auto texNatIf = texture->nativeInterface<QNativeInterface::QSGVulkanTexture>();
+ QVERIFY(texNatIf);
+ QVERIFY(texNatIf->nativeImage());
+ }
+#endif
+}
+
bool tst_SceneGraph::isRunningOnRhi()
{
static bool retval = false;
diff --git a/tests/auto/quick/sharedimage/CMakeLists.txt b/tests/auto/quick/sharedimage/CMakeLists.txt
index 642f55b0b9..c6d71896c6 100644
--- a/tests/auto/quick/sharedimage/CMakeLists.txt
+++ b/tests/auto/quick/sharedimage/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_sharedimage Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_sharedimage LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/sharedimage/tst_sharedimage.cpp b/tests/auto/quick/sharedimage/tst_sharedimage.cpp
index cdc5663710..e3d87f68dd 100644
--- a/tests/auto/quick/sharedimage/tst_sharedimage.cpp
+++ b/tests/auto/quick/sharedimage/tst_sharedimage.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest>
#include <private/qquickimage_p.h>
diff --git a/tests/auto/quick/softwarerenderer/CMakeLists.txt b/tests/auto/quick/softwarerenderer/CMakeLists.txt
index af44ced1c1..9e8433f8df 100644
--- a/tests/auto/quick/softwarerenderer/CMakeLists.txt
+++ b/tests/auto/quick/softwarerenderer/CMakeLists.txt
@@ -5,6 +5,12 @@
## tst_softwarerenderer Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_softwarerenderer LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_softwarerenderer
SOURCES
tst_softwarerenderer.cpp
diff --git a/tests/auto/quick/softwarerenderer/tst_softwarerenderer.cpp b/tests/auto/quick/softwarerenderer/tst_softwarerenderer.cpp
index 2d2581a3fa..034c6b8139 100644
--- a/tests/auto/quick/softwarerenderer/tst_softwarerenderer.cpp
+++ b/tests/auto/quick/softwarerenderer/tst_softwarerenderer.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 zccrs <zccrs@live.com>, JiDe Zhang <zhangjide@uniontech.com>.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuick>
#include <QtQml>
diff --git a/tests/auto/quick/touchmouse/BLACKLIST b/tests/auto/quick/touchmouse/BLACKLIST
index 214da65864..aaf5b8e95d 100644
--- a/tests/auto/quick/touchmouse/BLACKLIST
+++ b/tests/auto/quick/touchmouse/BLACKLIST
@@ -9,5 +9,6 @@ windows gcc developer-build
[touchButtonOnFlickable]
windows gcc developer-build
-[hoverEnabled]
-* # QTBUG-86729
+# QTBUG-118059
+[tapOnDismissiveTopMouseAreaClicksBottomOne]
+opensuse-leap
diff --git a/tests/auto/quick/touchmouse/CMakeLists.txt b/tests/auto/quick/touchmouse/CMakeLists.txt
index e664784da2..bca541bbfb 100644
--- a/tests/auto/quick/touchmouse/CMakeLists.txt
+++ b/tests/auto/quick/touchmouse/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_touchmouse Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_touchmouse LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
index 0d1256e368..501d996797 100644
--- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp
+++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -713,7 +713,7 @@ void tst_TouchMouse::touchButtonOnFlickable()
QTRY_COMPARE(eventItem2->touchUngrabCount, 1);
qCDebug(lcTests) << "expected delivered events: press(touch) move(touch)" << eventItem2->eventList;
- QCOMPARE(eventItem2->eventList.size(), 2);
+ QCOMPARE(eventItem2->eventList.size(), 3);
QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchUpdate);
QCOMPARE(grabMonitor.exclusiveGrabber, flickable);
// both EventItem and Flickable handled the actual touch, so synth-mouse doesn't happen
@@ -1440,6 +1440,7 @@ void tst_TouchMouse::hoverEnabled() // QTBUG-40856
QQuickView window;
QVERIFY(QQuickTest::showView(window, testFileUrl("hoverMouseAreas.qml")));
QQuickItem *root = window.rootObject();
+ auto deliveryAgent = QQuickWindowPrivate::get(&window)->deliveryAgentPrivate();
QQuickMouseArea *mouseArea1 = root->findChild<QQuickMouseArea*>("mouseArea1");
QVERIFY(mouseArea1 != nullptr);
@@ -1449,11 +1450,11 @@ void tst_TouchMouse::hoverEnabled() // QTBUG-40856
QSignalSpy enterSpy1(mouseArea1, SIGNAL(entered()));
QSignalSpy exitSpy1(mouseArea1, SIGNAL(exited()));
- QSignalSpy clickSpy1(mouseArea1, SIGNAL(clicked(QQuickMouseEvent *)));
+ QSignalSpy clickSpy1(mouseArea1, SIGNAL(clicked(QQuickMouseEvent*)));
QSignalSpy enterSpy2(mouseArea2, SIGNAL(entered()));
QSignalSpy exitSpy2(mouseArea2, SIGNAL(exited()));
- QSignalSpy clickSpy2(mouseArea2, SIGNAL(clicked(QQuickMouseEvent *)));
+ QSignalSpy clickSpy2(mouseArea2, SIGNAL(clicked(QQuickMouseEvent*)));
QPoint p1(150, 150);
QPoint p2(150, 250);
@@ -1467,6 +1468,7 @@ void tst_TouchMouse::hoverEnabled() // QTBUG-40856
// ------------------------- Touch click on mouseArea1
QTest::touchEvent(&window, device).press(0, p1, &window);
+ deliveryAgent->flushFrameSynchronousEvents(&window);
QCOMPARE(enterSpy1.size(), 1);
QCOMPARE(enterSpy2.size(), 0);
@@ -1475,37 +1477,42 @@ void tst_TouchMouse::hoverEnabled() // QTBUG-40856
QVERIFY(!mouseArea2->hovered());
QTest::touchEvent(&window, device).release(0, p1, &window);
+ deliveryAgent->flushFrameSynchronousEvents(&window);
QVERIFY(clickSpy1.size() == 1);
QVERIFY(mouseArea1->hovered());
QVERIFY(!mouseArea2->hovered());
// ------------------------- Touch click on mouseArea2
QTest::touchEvent(&window, device).press(0, p2, &window);
+ deliveryAgent->flushFrameSynchronousEvents(&window);
- QVERIFY(mouseArea1->hovered());
+ QVERIFY(!mouseArea1->hovered());
QVERIFY(mouseArea2->hovered());
QVERIFY(mouseArea2->isPressed());
QCOMPARE(enterSpy1.size(), 1);
QCOMPARE(enterSpy2.size(), 1);
QTest::touchEvent(&window, device).release(0, p2, &window);
+ deliveryAgent->flushFrameSynchronousEvents(&window);
QVERIFY(clickSpy2.size() == 1);
- QVERIFY(mouseArea1->hovered());
+ QVERIFY(!mouseArea1->hovered());
QVERIFY(!mouseArea2->hovered());
- QCOMPARE(exitSpy1.size(), 0);
+ QCOMPARE(exitSpy1.size(), 1);
QCOMPARE(exitSpy2.size(), 1);
// ------------------------- Another touch click on mouseArea1
QTest::touchEvent(&window, device).press(0, p1, &window);
+ deliveryAgent->flushFrameSynchronousEvents(&window);
- QCOMPARE(enterSpy1.size(), 1);
+ QCOMPARE(enterSpy1.size(), 2);
QCOMPARE(enterSpy2.size(), 1);
QVERIFY(mouseArea1->isPressed());
QVERIFY(mouseArea1->hovered());
QVERIFY(!mouseArea2->hovered());
QTest::touchEvent(&window, device).release(0, p1, &window);
+ deliveryAgent->flushFrameSynchronousEvents(&window);
QCOMPARE(clickSpy1.size(), 2);
QVERIFY(mouseArea1->hovered());
QVERIFY(!mouseArea1->isPressed());
diff --git a/tests/auto/quickcontrols/CMakeLists.txt b/tests/auto/quickcontrols/CMakeLists.txt
index 6d33fb1ae9..f4f2e6b2c6 100644
--- a/tests/auto/quickcontrols/CMakeLists.txt
+++ b/tests/auto/quickcontrols/CMakeLists.txt
@@ -10,7 +10,9 @@ endif()
add_subdirectory(cursor)
add_subdirectory(customization)
add_subdirectory(deferred)
-add_subdirectory(designer)
+if(QT_FEATURE_quick_designer)
+ add_subdirectory(designer)
+endif()
if(NOT ANDROID) # QTBUG-100258
add_subdirectory(focus)
endif()
@@ -32,6 +34,7 @@ add_subdirectory(qquickmaterialstyleconf)
add_subdirectory(qquickmenu)
add_subdirectory(qquickmenubar)
add_subdirectory(qquickninepatchimage)
+add_subdirectory(qquickoverlay)
add_subdirectory(qquickpopup)
add_subdirectory(qquickstyle)
add_subdirectory(qquicktextarea)
diff --git a/tests/auto/quickcontrols/accessibility/CMakeLists.txt b/tests/auto/quickcontrols/accessibility/CMakeLists.txt
index 3831c5863d..e1221950bc 100644
--- a/tests/auto/quickcontrols/accessibility/CMakeLists.txt
+++ b/tests/auto/quickcontrols/accessibility/CMakeLists.txt
@@ -3,14 +3,14 @@
# Generated from accessibility.pro.
-if(NOT QT_FEATURE_accessibility)
- return()
-endif()
-
-if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_accessibility LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+if(NOT QT_FEATURE_accessibility)
+ return()
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/accessibility/data/actionAccessibility/button.qml b/tests/auto/quickcontrols/accessibility/data/actionAccessibility/button.qml
new file mode 100644
index 0000000000..7e392e9cc3
--- /dev/null
+++ b/tests/auto/quickcontrols/accessibility/data/actionAccessibility/button.qml
@@ -0,0 +1,12 @@
+import QtQuick
+import QtQuick.Controls
+
+Button {
+ action: Action {
+ id: anAction
+ text: "Peaches"
+ Accessible.name: "Peach"
+ Accessible.description: "Show peaches some love"
+ }
+ text: Accessible.description
+}
diff --git a/tests/auto/quickcontrols/accessibility/tst_accessibility.cpp b/tests/auto/quickcontrols/accessibility/tst_accessibility.cpp
index 40ee98691d..8bdd9453c8 100644
--- a/tests/auto/quickcontrols/accessibility/tst_accessibility.cpp
+++ b/tests/auto/quickcontrols/accessibility/tst_accessibility.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtQml/qqmlengine.h>
@@ -31,6 +31,8 @@ private slots:
void override();
void ordering();
+
+ void actionAccessibility();
private:
QQmlEngine engine;
};
@@ -274,6 +276,26 @@ void tst_accessibility::ordering()
#endif
}
+void tst_accessibility::actionAccessibility()
+{
+#if QT_CONFIG(accessibility)
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("actionAccessibility/button.qml"));
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY2(!object.isNull(), qPrintable(component.errorString()));
+
+ QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(item);
+ const QString description = "Show peaches some love";
+ QCOMPARE(item->property("text"), description);
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(item);
+ QVERIFY(iface);
+ QCOMPARE(iface->text(QAccessible::Name), "Peach");
+ QCOMPARE(iface->text(QAccessible::Description), description);
+#endif
+}
+
QTEST_MAIN(tst_accessibility)
#include "tst_accessibility.moc"
diff --git a/tests/auto/quickcontrols/cmake/CMakeLists.txt b/tests/auto/quickcontrols/cmake/CMakeLists.txt
deleted file mode 100644
index 93ecd12386..0000000000
--- a/tests/auto/quickcontrols/cmake/CMakeLists.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
-
-cmake_minimum_required(VERSION 3.16)
-
-project(qmake_cmake_files)
-
-enable_testing()
-
-find_package(Qt5Core REQUIRED)
-
-include("${_Qt5CTestMacros}")
-
-test_module_includes(
- QuickControls2 QQuickStyle
-)
diff --git a/tests/auto/quickcontrols/controls/CMakeLists.txt b/tests/auto/quickcontrols/controls/CMakeLists.txt
index 6984315b5a..593d87fb75 100644
--- a/tests/auto/quickcontrols/controls/CMakeLists.txt
+++ b/tests/auto/quickcontrols/controls/CMakeLists.txt
@@ -8,6 +8,7 @@ add_subdirectory(fusion)
add_subdirectory(imagine)
add_subdirectory(material)
add_subdirectory(universal)
+add_subdirectory(fluentwinui3)
if(MACOS)
add_subdirectory(macos)
add_subdirectory(ios)
diff --git a/tests/auto/quickcontrols/controls/basic/BLACKLIST b/tests/auto/quickcontrols/controls/basic/BLACKLIST
index b643dd1d9c..b822193f4c 100644
--- a/tests/auto/quickcontrols/controls/basic/BLACKLIST
+++ b/tests/auto/quickcontrols/controls/basic/BLACKLIST
@@ -11,3 +11,8 @@ qnx
[ComboBox::test_keyClose]
macos arm ci # QTBUG-102817
+
+# QTBUG-126236
+[Action::test_repeater]
+macos
+linux
diff --git a/tests/auto/quickcontrols/controls/basic/CMakeLists.txt b/tests/auto/quickcontrols/controls/basic/CMakeLists.txt
index dabab76bbe..cc991ca165 100644
--- a/tests/auto/quickcontrols/controls/basic/CMakeLists.txt
+++ b/tests/auto/quickcontrols/controls/basic/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_basic LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/controls/basic/tst_basic.cpp b/tests/auto/quickcontrols/controls/basic/tst_basic.cpp
index 47cd9a393e..7e73bd2231 100644
--- a/tests/auto/quickcontrols/controls/basic/tst_basic.cpp
+++ b/tests/auto/quickcontrols/controls/basic/tst_basic.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
#include <QtQuickControls2/qquickstyle.h>
@@ -8,6 +8,9 @@ int main(int argc, char *argv[])
{
QTEST_SET_MAIN_SOURCE_PATH
qputenv("QML_NO_TOUCH_COMPRESSION", "1");
+ // The tests were originally written before native menus existed,
+ // and some of them try to open menus, which we can't test natively.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
QQuickStyle::setStyle("Basic");
return quick_test_main(argc, argv, "tst_controls::Basic", TST_CONTROLS_DATA);
}
diff --git a/tests/auto/quickcontrols/controls/data/SignalSequenceSpy.qml b/tests/auto/quickcontrols/controls/data/SignalSequenceSpy.qml
index 5e536248a8..879e7e546f 100644
--- a/tests/auto/quickcontrols/controls/data/SignalSequenceSpy.qml
+++ b/tests/auto/quickcontrols/controls/data/SignalSequenceSpy.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quickcontrols/controls/data/TestItem.qml b/tests/auto/quickcontrols/controls/data/TestItem.qml
index c36ddc2f11..7f01b2231a 100644
--- a/tests/auto/quickcontrols/controls/data/TestItem.qml
+++ b/tests/auto/quickcontrols/controls/data/TestItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quickcontrols/controls/data/TumblerDatePicker.qml b/tests/auto/quickcontrols/controls/data/TumblerDatePicker.qml
index c1b12e8fbc..bb24557fe2 100644
--- a/tests/auto/quickcontrols/controls/data/TumblerDatePicker.qml
+++ b/tests/auto/quickcontrols/controls/data/TumblerDatePicker.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/controls/data/TumblerListView.qml b/tests/auto/quickcontrols/controls/data/TumblerListView.qml
index a794f255db..ccc44cfe15 100644
--- a/tests/auto/quickcontrols/controls/data/TumblerListView.qml
+++ b/tests/auto/quickcontrols/controls/data/TumblerListView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/controls/data/TumblerPathView.qml b/tests/auto/quickcontrols/controls/data/TumblerPathView.qml
index 26de69dab2..971369a2dd 100644
--- a/tests/auto/quickcontrols/controls/data/TumblerPathView.qml
+++ b/tests/auto/quickcontrols/controls/data/TumblerPathView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/controls/data/combobox/shader.frag b/tests/auto/quickcontrols/controls/data/combobox/shader.frag
new file mode 100644
index 0000000000..fbbef218e6
--- /dev/null
+++ b/tests/auto/quickcontrols/controls/data/combobox/shader.frag
@@ -0,0 +1,19 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#version 440
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+layout(binding = 1) uniform sampler2D source; // this item
+
+layout(std140, binding = 0) uniform buf {
+ float qt_Opacity; // inherited opacity of this item
+};
+
+
+void main() {
+ vec4 p = texture(source, qt_TexCoord0);
+ lowp float g = dot(p.xyz, vec3(0.344, 0.5, 0.156));
+ fragColor = vec4(g, g, g, p.a) * qt_Opacity;
+}
diff --git a/tests/auto/quickcontrols/controls/data/combobox/shader.frag.qsb b/tests/auto/quickcontrols/controls/data/combobox/shader.frag.qsb
new file mode 100644
index 0000000000..b86ce9a76e
--- /dev/null
+++ b/tests/auto/quickcontrols/controls/data/combobox/shader.frag.qsb
Binary files differ
diff --git a/tests/auto/quickcontrols/controls/data/splitview/fillItemInMiddle.qml b/tests/auto/quickcontrols/controls/data/splitview/fillItemInMiddle.qml
index 1849e66e1c..63e0028220 100644
--- a/tests/auto/quickcontrols/controls/data/splitview/fillItemInMiddle.qml
+++ b/tests/auto/quickcontrols/controls/data/splitview/fillItemInMiddle.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/controls/data/splitview/fillItemOnLeft.qml b/tests/auto/quickcontrols/controls/data/splitview/fillItemOnLeft.qml
index 8307a05951..815e764215 100644
--- a/tests/auto/quickcontrols/controls/data/splitview/fillItemOnLeft.qml
+++ b/tests/auto/quickcontrols/controls/data/splitview/fillItemOnLeft.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/controls/data/splitview/fillItemOnTop.qml b/tests/auto/quickcontrols/controls/data/splitview/fillItemOnTop.qml
index 41ce0f386e..4d41624b7e 100644
--- a/tests/auto/quickcontrols/controls/data/splitview/fillItemOnTop.qml
+++ b/tests/auto/quickcontrols/controls/data/splitview/fillItemOnTop.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/controls/data/stackview/Rect.qml b/tests/auto/quickcontrols/controls/data/stackview/Rect.qml
new file mode 100644
index 0000000000..699cef6b5d
--- /dev/null
+++ b/tests/auto/quickcontrols/controls/data/stackview/Rect.qml
@@ -0,0 +1,8 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Rectangle {
+ color: "tomato"
+}
diff --git a/tests/auto/quickcontrols/controls/data/tst_abstractbutton.qml b/tests/auto/quickcontrols/controls/data/tst_abstractbutton.qml
index 663b152c70..bce13b37f2 100644
--- a/tests/auto/quickcontrols/controls/data/tst_abstractbutton.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_abstractbutton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -42,15 +42,56 @@ TestCase {
SignalSpy { }
}
- function test_defaults() {
+ property var expectedPressSignals: [
+ ["activeFocusChanged", { "activeFocus": true }],
+ ["pressedChanged", { "pressed": true }],
+ ["downChanged", { "down": true }],
+ "pressed"
+ ]
+
+ property var expectedReleaseSignals: [
+ ["pressedChanged", { "pressed": false }],
+ ["downChanged", { "down": false }],
+ "released",
+ "clicked"
+ ]
+
+ property var expectedClickSignals
+
+ property var expectedCheckableClickSignals: [
+ ["activeFocusChanged", { "activeFocus": true }],
+ ["pressedChanged", { "pressed": true }],
+ ["downChanged", { "down": true }],
+ "pressed",
+ ["pressedChanged", { "pressed": false }],
+ ["downChanged", { "down": false }],
+ ["checkedChanged", { "checked": true }],
+ "toggled",
+ "released",
+ "clicked"
+ ]
+
+ function initTestCase() {
+ // AbstractButton has TabFocus on macOS, not StrongFocus.
+ if (Qt.platform.os === "osx") {
+ expectedPressSignals.splice(0, 1)
+ expectedCheckableClickSignals.splice(0, 1)
+ }
+
+ expectedClickSignals = [...expectedPressSignals, ...expectedReleaseSignals]
+ }
+
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(defaultComponent, testCase)
verify(control)
}
function test_text() {
- var control = createTemporaryObject(button, testCase);
+ let control = createTemporaryObject(button, testCase);
verify(control);
compare(control.text, "");
@@ -61,7 +102,7 @@ TestCase {
}
function test_baseline() {
- var control = createTemporaryObject(button, testCase, {padding: 6})
+ let control = createTemporaryObject(button, testCase, {padding: 6})
verify(control)
compare(control.baselineOffset, 0)
control.contentItem = item.createObject(control, {baselineOffset: 12})
@@ -69,7 +110,7 @@ TestCase {
}
function test_implicitSize() {
- var control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(button, testCase)
verify(control)
compare(control.implicitWidth, 0)
@@ -96,22 +137,22 @@ TestCase {
}
function test_pressPoint(data) {
- var control = createTemporaryObject(button, testCase, {width: 100, height: 40})
+ let control = createTemporaryObject(button, testCase, {width: 100, height: 40})
verify(control)
- var pressXChanges = 0
- var pressYChanges = 0
+ let pressXChanges = 0
+ let pressYChanges = 0
- var pressXSpy = signalSpy.createObject(control, {target: control, signalName: "pressXChanged"})
+ let pressXSpy = signalSpy.createObject(control, {target: control, signalName: "pressXChanged"})
verify(pressXSpy.valid)
- var pressYSpy = signalSpy.createObject(control, {target: control, signalName: "pressYChanged"})
+ let pressYSpy = signalSpy.createObject(control, {target: control, signalName: "pressYChanged"})
verify(pressYSpy.valid)
compare(control.pressX, 0)
compare(control.pressY, 0)
- var touch = data.touch ? touchEvent(control) : null
+ let touch = data.touch ? touchEvent(control) : null
if (data.touch)
touch.press(0, control, control.width / 2, control.height / 2).commit()
@@ -196,10 +237,10 @@ TestCase {
}
function test_pressAndHold() {
- var control = createTemporaryObject(button, testCase, {checkable: true})
+ let control = createTemporaryObject(button, testCase, {checkable: true})
verify(control)
- var pressAndHoldSpy = signalSpy.createObject(control, {target: control, signalName: "pressAndHold"})
+ let pressAndHoldSpy = signalSpy.createObject(control, {target: control, signalName: "pressAndHold"})
verify(pressAndHoldSpy.valid)
mousePress(control)
@@ -215,8 +256,8 @@ TestCase {
Item {
property int lastKeyPress: -1
property int lastKeyRelease: -1
- Keys.onPressed: lastKeyPress = event.key
- Keys.onReleased: lastKeyRelease = event.key
+ Keys.onPressed: function (event) { lastKeyPress = event.key }
+ Keys.onReleased: function (event) { lastKeyRelease = event.key }
}
}
@@ -228,10 +269,10 @@ TestCase {
}
function test_keyEvents(data) {
- var container = createTemporaryObject(keyCatcher, testCase)
+ let container = createTemporaryObject(keyCatcher, testCase)
verify(container)
- var control = button.createObject(container)
+ let control = button.createObject(container)
verify(control)
control.forceActiveFocus()
@@ -245,7 +286,7 @@ TestCase {
}
function test_icon() {
- var control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(button, testCase)
verify(control)
compare(control.icon.name, "")
compare(control.icon.source, "")
@@ -253,7 +294,7 @@ TestCase {
compare(control.icon.height, 0)
compare(control.icon.color, "#00000000")
- var iconSpy = signalSpy.createObject(control, { target: control, signalName: "iconChanged"} )
+ let iconSpy = signalSpy.createObject(control, { target: control, signalName: "iconChanged"} )
verify(iconSpy.valid)
control.icon.name = "test-name"
@@ -322,14 +363,14 @@ TestCase {
}
function test_action(data) {
- var control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(button, testCase)
verify(control)
control[data.property] = data.initButton
- var act = action.createObject(control)
+ let act = action.createObject(control)
act[data.property] = data.initAction
- var spy = signalSpy.createObject(control, {target: control, signalName: data.property + "Changed"})
+ let spy = signalSpy.createObject(control, {target: control, signalName: data.property + "Changed"})
verify(spy.valid)
// assign action
@@ -362,23 +403,23 @@ TestCase {
}
function test_actionIcon_data() {
- var data = []
+ let data = []
// Save duplicating the rows by reusing them with different properties of the same type.
// This means that the first loop will test icon.name and the second one will test icon.source.
- var stringPropertyValueSuffixes = [
+ let stringPropertyValueSuffixes = [
{ propertyName: "name", valueSuffix: "IconName" },
{ propertyName: "source", valueSuffix: "IconSource" }
]
- for (var i = 0; i < stringPropertyValueSuffixes.length; ++i) {
- var propertyName = stringPropertyValueSuffixes[i].propertyName
- var valueSuffix = stringPropertyValueSuffixes[i].valueSuffix
+ for (let i = 0; i < stringPropertyValueSuffixes.length; ++i) {
+ let propertyName = stringPropertyValueSuffixes[i].propertyName
+ let valueSuffix = stringPropertyValueSuffixes[i].valueSuffix
- var buttonPropertyValue = "Button" + valueSuffix
- var buttonPropertyValue2 = "Button" + valueSuffix + "2"
- var actionPropertyValue = "Action" + valueSuffix
- var actionPropertyValue2 = "Action" + valueSuffix + "2"
+ let buttonPropertyValue = "Button" + valueSuffix
+ let buttonPropertyValue2 = "Button" + valueSuffix + "2"
+ let actionPropertyValue = "Action" + valueSuffix
+ let actionPropertyValue2 = "Action" + valueSuffix + "2"
data.push({ tag: "implicit " + propertyName, property: propertyName,
initButton: undefined, initAction: actionPropertyValue,
@@ -420,19 +461,19 @@ TestCase {
resetExpected: buttonPropertyValue, resetChanged: false })
}
- var intPropertyNames = [
+ let intPropertyNames = [
"width",
"height",
]
- for (i = 0; i < intPropertyNames.length; ++i) {
- propertyName = intPropertyNames[i]
+ for (let i = 0; i < intPropertyNames.length; ++i) {
+ let propertyName = intPropertyNames[i]
- buttonPropertyValue = 20
- buttonPropertyValue2 = 21
- actionPropertyValue = 40
- actionPropertyValue2 = 41
- var defaultValue = 0
+ let buttonPropertyValue = 20
+ let buttonPropertyValue2 = 21
+ let actionPropertyValue = 40
+ let actionPropertyValue2 = 41
+ let defaultValue = 0
data.push({ tag: "implicit " + propertyName, property: propertyName,
initButton: undefined, initAction: actionPropertyValue,
@@ -474,12 +515,12 @@ TestCase {
resetExpected: buttonPropertyValue, resetChanged: false })
}
- propertyName = "color"
- buttonPropertyValue = "#aa0000"
- buttonPropertyValue2 = "#ff0000"
- actionPropertyValue = "#0000aa"
- actionPropertyValue2 = "#0000ff"
- defaultValue = "#00000000"
+ let propertyName = "color"
+ let buttonPropertyValue = "#aa0000"
+ let buttonPropertyValue2 = "#ff0000"
+ let actionPropertyValue = "#0000aa"
+ let actionPropertyValue2 = "#0000ff"
+ let defaultValue = "#00000000"
data.push({ tag: "implicit " + propertyName, property: propertyName,
initButton: undefined, initAction: actionPropertyValue,
@@ -524,14 +565,14 @@ TestCase {
}
function test_actionIcon(data) {
- var control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(button, testCase)
verify(control)
control.icon[data.property] = data.initButton
- var act = action.createObject(control)
+ let act = action.createObject(control)
act.icon[data.property] = data.initAction
- var spy = signalSpy.createObject(control, {target: control, signalName: "iconChanged"})
+ let spy = signalSpy.createObject(control, {target: control, signalName: "iconChanged"})
verify(spy.valid)
// assign action
@@ -580,7 +621,7 @@ TestCase {
}
function test_actionButton() {
- var control = createTemporaryObject(actionButton, testCase)
+ let control = createTemporaryObject(actionButton, testCase)
verify(control)
// initial values
@@ -590,7 +631,7 @@ TestCase {
compare(control.enabled, false)
compare(control.icon.name, "checked")
- var textSpy = signalSpy.createObject(control, { target: control, signalName: "textChanged" })
+ let textSpy = signalSpy.createObject(control, { target: control, signalName: "textChanged" })
verify(textSpy.valid)
// changes via action
@@ -631,7 +672,7 @@ TestCase {
// setting an action while button has a particular property set
// shouldn't cause a change in the button's effective property value
- var secondAction = createTemporaryObject(action, testCase)
+ let secondAction = createTemporaryObject(action, testCase)
verify(secondAction)
secondAction.text = "SecondAction"
control.action = secondAction
@@ -639,7 +680,7 @@ TestCase {
compare(textSpy.count, 2)
// test setting an action whose properties aren't set
- var thirdAction = createTemporaryObject(action, testCase)
+ let thirdAction = createTemporaryObject(action, testCase)
verify(thirdAction)
control.action = thirdAction
compare(control.text, "Button")
@@ -657,7 +698,7 @@ TestCase {
}
function test_checkable_button() {
- var control = createTemporaryObject(checkableButton, testCase)
+ let control = createTemporaryObject(checkableButton, testCase)
verify(control)
control.checked = false
control.forceActiveFocus()
@@ -681,9 +722,9 @@ TestCase {
compare(control.action.checked, false)
compare(control.checked, false)
- var checkedSpy = signalSpy.createObject(control, {target: control.action, signalName: "checkedChanged"})
- var toggledSpy = signalSpy.createObject(control, {target: control, signalName: "toggled"})
- var actionToggledSpy = signalSpy.createObject(control, {target: control.action, signalName: "toggled"})
+ let checkedSpy = signalSpy.createObject(control, {target: control.action, signalName: "checkedChanged"})
+ let toggledSpy = signalSpy.createObject(control, {target: control, signalName: "toggled"})
+ let actionToggledSpy = signalSpy.createObject(control, {target: control.action, signalName: "toggled"})
verify(checkedSpy.valid)
verify(toggledSpy.valid)
@@ -723,16 +764,16 @@ TestCase {
}
function test_trigger(data) {
- var control = createTemporaryObject(actionButton, testCase, {"action.enabled": data.action, "enabled": data.button})
+ let control = createTemporaryObject(actionButton, testCase, {"action.enabled": data.action, "enabled": data.button})
verify(control)
compare(control.enabled, data.button)
compare(control.action.enabled, data.action)
- var buttonSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
+ let buttonSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
verify(buttonSpy.valid)
- var actionSpy = signalSpy.createObject(control, {target: control.action, signalName: "triggered"})
+ let actionSpy = signalSpy.createObject(control, {target: control.action, signalName: "triggered"})
verify(actionSpy.valid)
if (data.click)
@@ -748,13 +789,13 @@ TestCase {
if (Qt.platform.os === "osx" || Qt.platform.os === "macos")
skip("Mnemonics are not used on macOS")
- var control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(button, testCase)
verify(control)
control.text = "&Hello"
compare(control.text, "&Hello")
- var clickSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
+ let clickSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
verify(clickSpy.valid)
keyClick(Qt.Key_H, Qt.AltModifier)
@@ -789,7 +830,7 @@ TestCase {
control.text = undefined
control.action = action.createObject(control, {text: "&Action"})
- var actionSpy = signalSpy.createObject(control, {target: control.action, signalName: "triggered"})
+ let actionSpy = signalSpy.createObject(control, {target: control.action, signalName: "triggered"})
verify(actionSpy.valid)
keyClick(Qt.Key_A, Qt.AltModifier)
@@ -814,12 +855,12 @@ TestCase {
}
function test_actionGroup() {
- var group = createTemporaryObject(actionGroup, testCase)
+ let group = createTemporaryObject(actionGroup, testCase)
verify(group)
- var button1 = createTemporaryObject(button, testCase, {action: group.actions[0], width: 10, height: 10})
- var button2 = createTemporaryObject(button, testCase, {action: group.actions[1], width: 10, height: 10, y: 10})
- var button3 = createTemporaryObject(button, testCase, {action: group.actions[2], width: 10, height: 10, y: 20})
+ let button1 = createTemporaryObject(button, testCase, {action: group.actions[0], width: 10, height: 10})
+ let button2 = createTemporaryObject(button, testCase, {action: group.actions[1], width: 10, height: 10, y: 10})
+ let button3 = createTemporaryObject(button, testCase, {action: group.actions[2], width: 10, height: 10, y: 20})
verify(button1)
compare(button1.checked, true)
@@ -846,10 +887,10 @@ TestCase {
}
function test_clickedAfterLongPress() {
- var control = createTemporaryObject(button, testCase, { text: "Hello" })
+ let control = createTemporaryObject(button, testCase, { text: "Hello" })
verify(control)
- var clickedSpy = signalSpy.createObject(control, { target: control, signalName: "clicked" })
+ let clickedSpy = signalSpy.createObject(control, { target: control, signalName: "clicked" })
verify(clickedSpy.valid)
mousePress(control)
@@ -967,5 +1008,172 @@ TestCase {
verify(control)
verify(!control.checkable)
- }
+ }
+
+ function test_rightMouseButton() {
+ let control = createTemporaryObject(button, testCase)
+ verify(control)
+
+ let pressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" })
+ verify(pressedSpy.valid)
+
+ let releasedSpy = signalSpy.createObject(control, { target: control, signalName: "released" })
+ verify(releasedSpy.valid)
+
+ let clickedSpy = signalSpy.createObject(control, { target: control, signalName: "clicked" })
+ verify(clickedSpy.valid)
+
+ // button should not react on the right mouse button by defualt
+ mousePress(control, control.width / 2, control.height / 2, Qt.RightButton)
+ mouseRelease(control, control.width / 2, control.height / 2, Qt.RightButton)
+
+ compare(pressedSpy.count, 0)
+ compare(releasedSpy.count, 0)
+ compare(clickedSpy.count, 0)
+
+ // QTBUG-116289 - adding a HoverHandler into the button should not affect the handling of the right mouse button
+ let hoverHandler = createTemporaryQmlObject("import QtQuick; HoverHandler {}", control)
+ verify(hoverHandler)
+ compare(hoverHandler.target, control)
+
+ mousePress(control, control.width / 2, control.height / 2, Qt.RightButton)
+ mouseRelease(control, control.width / 2, control.height / 2, Qt.RightButton)
+
+ compare(pressedSpy.count, 0)
+ compare(releasedSpy.count, 0)
+ compare(clickedSpy.count, 0)
+ }
+
+ Component {
+ id: signalSequenceSpy
+ SignalSequenceSpy {
+ // List all signals, even ones we might not be interested in for a particular test,
+ // so that it can catch unwanted ones and fail the test.
+ signals: ["pressed", "released", "canceled", "clicked", "toggled", "doubleClicked",
+ "pressedChanged", "downChanged", "checkedChanged", "activeFocusChanged"]
+ }
+ }
+
+ function test_click() {
+ let control = createTemporaryObject(button, testCase)
+ verify(control)
+
+ let sequenceSpy = signalSequenceSpy.createObject(control, { target: control })
+ sequenceSpy.expectedSequence = testCase.expectedClickSignals
+ control.click()
+ verify(sequenceSpy.success)
+ }
+
+ function test_clickCheckableButton() {
+ let control = createTemporaryObject(button, testCase, { checkable: true })
+ verify(control)
+
+ let sequenceSpy = signalSequenceSpy.createObject(control, { target: control })
+ sequenceSpy.expectedSequence = testCase.expectedCheckableClickSignals
+ control.click()
+ verify(sequenceSpy.success)
+ }
+
+ function test_animateClick() {
+ let control = createTemporaryObject(button, testCase)
+ verify(control)
+
+ let sequenceSpy = signalSequenceSpy.createObject(control, { target: control })
+ sequenceSpy.expectedSequence = testCase.expectedClickSignals
+ control.animateClick()
+ tryVerify(() => { return sequenceSpy.success }, 1000)
+ }
+
+ function test_animateClickCheckableButton() {
+ let control = createTemporaryObject(button, testCase, { checkable: true })
+ verify(control)
+
+ let sequenceSpy = signalSequenceSpy.createObject(control, { target: control })
+ sequenceSpy.expectedSequence = testCase.expectedCheckableClickSignals
+ control.animateClick()
+ tryVerify(() => { return sequenceSpy.success }, 1000)
+ }
+
+ function test_animateClickTwice() {
+ let control = createTemporaryObject(button, testCase)
+ verify(control)
+
+ let sequenceSpy = signalSequenceSpy.createObject(control, { target: control })
+ sequenceSpy.expectedSequence = testCase.expectedPressSignals
+ // Check that calling it again before it finishes works as expected.
+ control.animateClick()
+ verify(sequenceSpy.success)
+ // Let the timer progress a bit.
+ wait(0)
+ sequenceSpy.expectedSequence = testCase.expectedReleaseSignals
+ control.animateClick()
+ tryVerify(() => { return sequenceSpy.success }, 1000)
+ }
+
+ function test_clickOnDisabledButton() {
+ let control = createTemporaryObject(button, testCase, { enabled: false })
+ verify(control)
+
+ let sequenceSpy = signalSequenceSpy.createObject(control, { target: control })
+ sequenceSpy.expectedSequence = []
+ control.click()
+ verify(sequenceSpy.success)
+ }
+
+ function test_animateClickOnDisabledButton() {
+ let control = createTemporaryObject(button, testCase, { enabled: false })
+ verify(control)
+
+ let sequenceSpy = signalSequenceSpy.createObject(control, { target: control })
+ sequenceSpy.expectedSequence = []
+ control.animateClick()
+ verify(sequenceSpy.success)
+ }
+
+ Component {
+ id: destroyOnPressButtonComponent
+
+ AbstractButton {
+ width: 100
+ height: 50
+
+ onPressed: destroy(this)
+ }
+ }
+
+ function test_clickDestroyOnPress() {
+ let control = createTemporaryObject(destroyOnPressButtonComponent, testCase)
+ verify(control)
+
+ // Parent it to the testCase, otherwise it will be destroyed when the control is.
+ let destructionSpy = createTemporaryObject(signalSpy, testCase,
+ { target: control.Component, signalName: "destruction" })
+ verify(destructionSpy.valid)
+
+ let sequenceSpy = signalSequenceSpy.createObject(control, { target: control })
+ sequenceSpy.expectedSequence = testCase.expectedClickSignals
+ // Shouldn't crash, etc. Note that destroy() isn't synchronous, and so
+ // the destruction will happen after the release.
+ control.click()
+ verify(sequenceSpy.success)
+ tryCompare(destructionSpy, "count", 1)
+ }
+
+ function test_animateClickDestroyOnPress() {
+ let control = createTemporaryObject(destroyOnPressButtonComponent, testCase)
+ verify(control)
+
+ // Parent it to the testCase, otherwise it will be destroyed when the control is.
+ let destructionSpy = createTemporaryObject(signalSpy, testCase,
+ { target: control.Component, signalName: "destruction" })
+ verify(destructionSpy.valid)
+
+ let sequenceSpy = signalSequenceSpy.createObject(control, { target: control })
+ sequenceSpy.expectedSequence = testCase.expectedPressSignals
+ // Shouldn't crash, etc. Note that destroy() isn't synchronous, but it is processed
+ // on the next frame, so should always come before the release's 100 ms delay.
+ control.animateClick()
+ verify(sequenceSpy.success)
+ tryCompare(destructionSpy, "count", 1)
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_action.qml b/tests/auto/quickcontrols/controls/data/tst_action.qml
index 845a6507af..f2b7a8674d 100644
--- a/tests/auto/quickcontrols/controls/data/tst_action.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_action.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -24,18 +24,20 @@ TestCase {
SignalSpy { }
}
- function test_empty() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_empty() {
let control = createTemporaryObject(component, testCase)
verify(control)
}
function test_enabled() {
- var action = createTemporaryObject(component, testCase)
+ let action = createTemporaryObject(component, testCase)
verify(action)
- var spy = createTemporaryObject(signalSpy, testCase, {target: action, signalName: "triggered"})
+ let spy = createTemporaryObject(signalSpy, testCase, {target: action, signalName: "triggered"})
verify(spy.valid)
action.trigger()
@@ -53,24 +55,34 @@ TestCase {
Component {
id: buttonAndMenu
Item {
+ objectName: "container"
+
property alias button: button
property alias menu: menu
property alias menuItem: menuItem
property alias action: sharedAction
property var lastSource
+
Action {
id: sharedAction
+ objectName: "sharedAction"
text: "Shared"
shortcut: "Ctrl+B"
onTriggered: (source) => lastSource = source
}
Button {
id: button
+ objectName: "button"
action: sharedAction
+
Menu {
id: menu
+ objectName: "menu"
+ contentItem.objectName: "menuContentItem"
+
MenuItem {
id: menuItem
+ objectName: "menuItem"
action: sharedAction
}
}
@@ -79,7 +91,7 @@ TestCase {
}
function test_shared() {
- var container = createTemporaryObject(buttonAndMenu, testCase)
+ let container = createTemporaryObject(buttonAndMenu, testCase)
verify(container)
keyClick(Qt.Key_B, Qt.ControlModifier)
@@ -116,10 +128,10 @@ TestCase {
}
function test_repeater() {
- var container = createTemporaryObject(actionAndRepeater, testCase)
+ let container = createTemporaryObject(actionAndRepeater, testCase)
verify(container)
- var spy = signalSpy.createObject(container, {target: container.action, signalName: "triggered"})
+ let spy = signalSpy.createObject(container, {target: container.action, signalName: "triggered"})
verify(spy.valid)
keyClick(Qt.Key_A, Qt.ControlModifier)
@@ -150,7 +162,7 @@ TestCase {
}
function test_shortcutBinding() {
- var container = createTemporaryObject(shortcutBinding, testCase);
+ let container = createTemporaryObject(shortcutBinding, testCase);
verify(container)
compare(container.indirect.nativeText, container.direct.nativeText);
}
@@ -178,7 +190,7 @@ TestCase {
function test_shortcutCleanup() {
{
- var container = createTemporaryObject(shortcutCleanup, testCase);
+ let container = createTemporaryObject(shortcutCleanup, testCase);
verify(container)
container.action.shortcut = "Delete"
container.menu.open()
diff --git a/tests/auto/quickcontrols/controls/data/tst_actiongroup.qml b/tests/auto/quickcontrols/controls/data/tst_actiongroup.qml
index 4b5fdc7d65..dc17d554a4 100644
--- a/tests/auto/quickcontrols/controls/data/tst_actiongroup.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_actiongroup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -37,8 +37,12 @@ TestCase {
SignalSpy { }
}
+ function init() {
+ failOnWarning(/.?/)
+ }
+
function test_null() {
- var group = createTemporaryObject(actionGroup, testCase)
+ let group = createTemporaryObject(actionGroup, testCase)
verify(group)
group.addAction(null)
@@ -51,9 +55,7 @@ TestCase {
}
function test_defaults() {
- failOnWarning(/.?/)
-
- var group = createTemporaryObject(actionGroup, testCase)
+ let group = createTemporaryObject(actionGroup, testCase)
verify(group)
compare(group.actions.length, 0)
compare(group.checkedAction, null)
@@ -61,16 +63,16 @@ TestCase {
}
function test_current() {
- var group = createTemporaryObject(actionGroup, testCase)
+ let group = createTemporaryObject(actionGroup, testCase)
verify(group)
- var checkedActionSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "checkedActionChanged"})
+ let checkedActionSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "checkedActionChanged"})
verify(checkedActionSpy.valid)
verify(!group.checkedAction)
- var action1 = createTemporaryObject(action, testCase, {checked: true})
- var action2 = createTemporaryObject(action, testCase, {checked: false})
- var action3 = createTemporaryObject(action, testCase, {checked: true, objectName: "3"})
+ let action1 = createTemporaryObject(action, testCase, {checked: true})
+ let action2 = createTemporaryObject(action, testCase, {checked: false})
+ let action3 = createTemporaryObject(action, testCase, {checked: true, objectName: "3"})
// add checked
group.addAction(action1)
@@ -130,17 +132,17 @@ TestCase {
}
function test_actions() {
- var group = createTemporaryObject(actionGroup, testCase)
+ let group = createTemporaryObject(actionGroup, testCase)
verify(group)
- var actionsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "actionsChanged"})
+ let actionsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "actionsChanged"})
verify(actionsSpy.valid)
compare(group.actions.length, 0)
compare(group.checkedAction, null)
- var action1 = createTemporaryObject(action, testCase, {checked: true})
- var action2 = createTemporaryObject(action, testCase, {checked: false})
+ let action1 = createTemporaryObject(action, testCase, {checked: true})
+ let action2 = createTemporaryObject(action, testCase, {checked: false})
group.actions = [action1, action2]
compare(group.actions.length, 2)
@@ -149,7 +151,7 @@ TestCase {
compare(group.checkedAction, action1)
compare(actionsSpy.count, 2)
- var action3 = createTemporaryObject(action, testCase, {checked: true})
+ let action3 = createTemporaryObject(action, testCase, {checked: true})
group.addAction(action3)
compare(group.actions.length, 3)
@@ -173,7 +175,7 @@ TestCase {
}
function test_declarative() {
- var group = createTemporaryObject(declarativeGroup, testCase)
+ let group = createTemporaryObject(declarativeGroup, testCase)
verify(group)
compare(group.actions.length, 3)
@@ -190,14 +192,14 @@ TestCase {
}
function test_triggered(data) {
- var group = createTemporaryObject(actionGroup, testCase, {exclusive: data.exclusive})
+ let group = createTemporaryObject(actionGroup, testCase, {exclusive: data.exclusive})
verify(group)
- var triggeredSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "triggered"})
+ let triggeredSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "triggered"})
verify(triggeredSpy.valid)
- var action1 = createTemporaryObject(action, testCase)
- var action2 = createTemporaryObject(action, testCase)
+ let action1 = createTemporaryObject(action, testCase)
+ let action2 = createTemporaryObject(action, testCase)
group.addAction(action1)
group.addAction(action2)
@@ -222,7 +224,7 @@ TestCase {
}
function test_attached() {
- var container = createTemporaryObject(attachedGroup, testCase)
+ let container = createTemporaryObject(attachedGroup, testCase)
verify(container)
verify(!container.group.checkedAction)
@@ -247,13 +249,13 @@ TestCase {
}
function test_actionDestroyed() {
- var group = createTemporaryObject(actionGroup, testCase)
+ let group = createTemporaryObject(actionGroup, testCase)
verify(group)
- var actionsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "actionsChanged"})
+ let actionsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "actionsChanged"})
verify(actionsSpy.valid)
- var action1 = createTemporaryObject(action, testCase, {objectName: "action1", checked: true})
+ let action1 = createTemporaryObject(action, testCase, {objectName: "action1", checked: true})
group.addAction(action1)
compare(group.actions.length, 1)
@@ -269,15 +271,15 @@ TestCase {
}
function test_nonExclusive() {
- var group = createTemporaryObject(nonExclusiveGroup, testCase)
+ let group = createTemporaryObject(nonExclusiveGroup, testCase)
verify(group)
- var action1 = createTemporaryObject(action, testCase, {checked: true})
+ let action1 = createTemporaryObject(action, testCase, {checked: true})
group.addAction(action1)
compare(action1.checked, true)
compare(group.checkedAction, null)
- var action2 = createTemporaryObject(action, testCase, {checked: true})
+ let action2 = createTemporaryObject(action, testCase, {checked: true})
group.addAction(action2)
compare(action1.checked, true)
compare(action2.checked, true)
@@ -305,18 +307,18 @@ TestCase {
}
function test_enabled() {
- var group = createTemporaryObject(actionGroup, testCase)
+ let group = createTemporaryObject(actionGroup, testCase)
verify(group)
compare(group.enabled, true)
- var action1 = createTemporaryObject(action, testCase)
- var action2 = createTemporaryObject(action, testCase)
+ let action1 = createTemporaryObject(action, testCase)
+ let action2 = createTemporaryObject(action, testCase)
compare(action1.enabled, true)
compare(action2.enabled, true)
- var action1Spy = createTemporaryObject(signalSpy, testCase, {target: action1, signalName: "enabledChanged"})
- var action2Spy = createTemporaryObject(signalSpy, testCase, {target: action2, signalName: "enabledChanged"})
+ let action1Spy = createTemporaryObject(signalSpy, testCase, {target: action1, signalName: "enabledChanged"})
+ let action2Spy = createTemporaryObject(signalSpy, testCase, {target: action2, signalName: "enabledChanged"})
verify(action1Spy.valid && action2Spy.valid)
group.addAction(action1)
@@ -352,4 +354,130 @@ TestCase {
compare(action2Spy.count, 2)
compare(action2Spy.signalArguments[1][0], true)
}
+
+ Component {
+ id: checkBoxes
+ Item {
+ property ActionGroup group: ActionGroup { id: group }
+ property CheckBox control1: CheckBox { action: Action { ActionGroup.group: group } }
+ property CheckBox control2: CheckBox { action: Action { ActionGroup.group: group } }
+ property CheckBox control3: CheckBox { action: Action { ActionGroup.group: group } }
+ }
+ }
+
+ Component {
+ id: radioButtons
+ Item {
+ property ActionGroup group: ActionGroup { id: group }
+ property RadioButton control1: RadioButton { action: Action { ActionGroup.group: group } }
+ property RadioButton control2: RadioButton { action: Action { ActionGroup.group: group } }
+ property RadioButton control3: RadioButton { action: Action { ActionGroup.group: group } }
+ }
+ }
+
+ Component {
+ id: switches
+ Item {
+ property ActionGroup group: ActionGroup { id: group }
+ property Switch control1: Switch { action: Action { ActionGroup.group: group } }
+ property Switch control2: Switch { action: Action { ActionGroup.group: group } }
+ property Switch control3: Switch { action: Action { ActionGroup.group: group } }
+ }
+ }
+
+ function test_controls_data() {
+ return [
+ { tag: "CheckBox", component: checkBoxes },
+ { tag: "RadioButton", component: radioButtons },
+ { tag: "Switch", component: switches },
+ ]
+ }
+
+ function test_controls(data) {
+ let container = createTemporaryObject(data.component, testCase)
+ verify(container)
+
+ verify(!container.group.checkedAction)
+
+ container.control1.checked = true
+ compare(container.group.checkedAction, container.control1.action)
+ compare(container.control1.checked, true)
+ compare(container.control2.checked, false)
+ compare(container.control3.checked, false)
+
+ container.control2.checked = true
+ compare(container.group.checkedAction, container.control2.action)
+ compare(container.control1.checked, false)
+ compare(container.control2.checked, true)
+ compare(container.control3.checked, false)
+
+ container.control3.checked = true
+ compare(container.group.checkedAction, container.control3.action)
+ compare(container.control1.checked, false)
+ compare(container.control2.checked, false)
+ compare(container.control3.checked, true)
+ }
+
+ Component {
+ id: exclusiveMenus
+ Column {
+ property ActionGroup group: ActionGroup { id: group }
+ property alias control1: control1
+ property alias control2: control2
+ property alias control3: control3
+ MenuItem {
+ id: control1
+ action: Action {
+ checkable: true
+ ActionGroup.group: group
+ }
+ }
+ MenuItem {
+ id: control2
+ action: Action {
+ checkable: true
+ ActionGroup.group: group
+ }
+ }
+ MenuItem {
+ id: control3
+ action: Action {
+ checkable: true
+ ActionGroup.group: group
+ }
+ }
+ }
+ }
+
+ function test_exclusiveActionButtons() {
+ const container = createTemporaryObject(exclusiveMenus, testCase)
+ verify(container)
+
+ verify(!container.group.checkedAction)
+
+ mouseClick(container.control1)
+ compare(container.group.checkedAction, container.control1.action)
+ compare(container.control1.checked, true)
+ compare(container.control2.checked, false)
+ compare(container.control3.checked, false)
+
+ mouseClick(container.control2)
+ compare(container.group.checkedAction, container.control2.action)
+ compare(container.control1.checked, false)
+ compare(container.control2.checked, true)
+ compare(container.control3.checked, false)
+
+ mouseClick(container.control3)
+ compare(container.group.checkedAction, container.control3.action)
+ compare(container.control1.checked, false)
+ compare(container.control2.checked, false)
+ compare(container.control3.checked, true)
+
+ // here comes the tricky part: clicking on checked control must not uncheck it
+ mouseClick(container.control3)
+ compare(container.group.checkedAction, container.control3.action)
+ compare(container.control1.checked, false)
+ compare(container.control2.checked, false)
+ compare(container.control3.checked, true)
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_busyindicator.qml b/tests/auto/quickcontrols/controls/data/tst_busyindicator.qml
index a50fd1bfab..001b0c474f 100644
--- a/tests/auto/quickcontrols/controls/data/tst_busyindicator.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_busyindicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -22,17 +22,26 @@ TestCase {
id: mouseArea
MouseArea { }
}
-
- function test_defaults() {
+
+ Component {
+ id: busyIndicatorInItem
+ Item {
+ BusyIndicator { }
+ }
+ }
+
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(busyIndicator, testCase)
verify(control)
compare(control.running, true)
}
function test_running() {
- var control = createTemporaryObject(busyIndicator, testCase)
+ let control = createTemporaryObject(busyIndicator, testCase)
verify(control)
compare(control.running, true)
@@ -42,10 +51,10 @@ TestCase {
// QTBUG-61785
function test_mouseArea() {
- var ma = createTemporaryObject(mouseArea, testCase, {width: testCase.width, height: testCase.height})
+ let ma = createTemporaryObject(mouseArea, testCase, {width: testCase.width, height: testCase.height})
verify(ma)
- var control = busyIndicator.createObject(ma, {width: testCase.width, height: testCase.height})
+ let control = busyIndicator.createObject(ma, {width: testCase.width, height: testCase.height})
verify(control)
mousePress(control)
@@ -54,11 +63,23 @@ TestCase {
mouseRelease(control)
verify(!ma.pressed)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
touch.press(0, control).commit()
verify(ma.pressed)
touch.release(0, control).commit()
verify(!ma.pressed)
}
+
+ // QTBUG-108808
+ function test_visibility() {
+ let control = createTemporaryObject(busyIndicatorInItem, testCase, {visible: false})
+ verify(control)
+
+ let invisibleImage = grabImage(control)
+ control.visible = true
+ let visibleImage = grabImage(control)
+
+ verify(!invisibleImage.equals(visibleImage))
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_button.qml b/tests/auto/quickcontrols/controls/data/tst_button.qml
index 9ddfa0885d..eaf38610cc 100644
--- a/tests/auto/quickcontrols/controls/data/tst_button.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_button.qml
@@ -1,9 +1,10 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
import QtQuick.Controls
+import Qt.test.controls
TestCase {
id: testCase
@@ -30,9 +31,11 @@ TestCase {
SignalSpy { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(button, testCase)
verify(control)
compare(control.highlighted, false)
@@ -40,7 +43,7 @@ TestCase {
}
function test_text() {
- var control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(button, testCase)
verify(control)
compare(control.text, "")
@@ -51,10 +54,10 @@ TestCase {
}
function test_mouse() {
- var control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(button, testCase)
verify(control)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
// click
sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
@@ -120,11 +123,11 @@ TestCase {
}
function test_touch() {
- var control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(button, testCase)
verify(control)
- var touch = touchEvent(control)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let touch = touchEvent(control)
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
// click
sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
@@ -163,15 +166,15 @@ TestCase {
}
function test_multiTouch() {
- var control1 = createTemporaryObject(button, testCase)
+ let control1 = createTemporaryObject(button, testCase)
verify(control1)
- var pressedCount1 = 0
+ let pressedCount1 = 0
- var pressedSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "pressedChanged"})
+ let pressedSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "pressedChanged"})
verify(pressedSpy1.valid)
- var touch = touchEvent(control1)
+ let touch = touchEvent(control1)
touch.press(0, control1, 0, 0).commit().move(0, control1, control1.width - 1, control1.height - 1).commit()
compare(pressedSpy1.count, ++pressedCount1)
@@ -185,12 +188,12 @@ TestCase {
compare(pressedSpy1.count, pressedCount1)
compare(control1.pressed, true)
- var control2 = createTemporaryObject(button, testCase, {y: control1.height})
+ let control2 = createTemporaryObject(button, testCase, {y: control1.height})
verify(control2)
- var pressedCount2 = 0
+ let pressedCount2 = 0
- var pressedSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "pressedChanged"})
+ let pressedSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "pressedChanged"})
verify(pressedSpy2.valid)
// press the second button
@@ -213,13 +216,13 @@ TestCase {
}
function test_keys() {
- var control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(button, testCase)
verify(control)
control.forceActiveFocus()
verify(control.activeFocus)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
// click
sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
@@ -236,8 +239,8 @@ TestCase {
sequenceSpy.expectedSequence = []
// Not testing Key_Enter and Key_Return because QGnomeTheme uses them for
// pressing buttons and the CI uses the QGnomeTheme platform theme.
- var keys = [Qt.Key_Escape, Qt.Key_Tab]
- for (var i = 0; i < keys.length; ++i) {
+ let keys = [Qt.Key_Escape, Qt.Key_Tab]
+ for (let i = 0; i < keys.length; ++i) {
sequenceSpy.reset()
keyClick(keys[i])
verify(sequenceSpy.success)
@@ -249,7 +252,7 @@ TestCase {
}
function test_autoRepeat() {
- var control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(button, testCase)
verify(control)
compare(control.autoRepeat, false)
@@ -259,11 +262,11 @@ TestCase {
control.forceActiveFocus()
verify(control.activeFocus)
- var clickSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
+ let clickSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
verify(clickSpy.valid)
- var pressSpy = signalSpy.createObject(control, {target: control, signalName: "pressed"})
+ let pressSpy = signalSpy.createObject(control, {target: control, signalName: "pressed"})
verify(pressSpy.valid)
- var releaseSpy = signalSpy.createObject(control, {target: control, signalName: "released"})
+ let releaseSpy = signalSpy.createObject(control, {target: control, signalName: "released"})
verify(releaseSpy.valid)
// auto-repeat mouse click
@@ -333,18 +336,18 @@ TestCase {
}
function test_baseline() {
- var control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(button, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
}
function test_checkable() {
- var control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(button, testCase)
verify(control)
verify(control.hasOwnProperty("checkable"))
verify(!control.checkable)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
["downChanged", { "down": true }],
@@ -386,7 +389,7 @@ TestCase {
}
function test_highlighted() {
- var control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(button, testCase)
verify(control)
verify(!control.highlighted)
@@ -395,11 +398,11 @@ TestCase {
}
function test_spacing() {
- var control = createTemporaryObject(button, testCase, { text: "Some long, long, long text" })
+ let control = createTemporaryObject(button, testCase, { text: "Some long, long, long text" })
verify(control)
verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth)
- var textLabel = findChild(control.contentItem, "label")
+ let textLabel = findChild(control.contentItem, "label")
verify(textLabel)
// The implicitWidth of the IconLabel that all buttons use as their contentItem
@@ -428,7 +431,7 @@ TestCase {
}
function test_display(data) {
- var control = createTemporaryObject(button, testCase, {
+ let control = createTemporaryObject(button, testCase, {
text: "Button",
display: data.display,
"icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png",
@@ -437,8 +440,8 @@ TestCase {
verify(control)
compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png")
- var iconImage = findChild(control.contentItem, "image")
- var textLabel = findChild(control.contentItem, "label")
+ let iconImage = findChild(control.contentItem, "image")
+ let textLabel = findChild(control.contentItem, "label")
switch (control.display) {
case Button.IconOnly:
@@ -446,12 +449,20 @@ TestCase {
verify(!textLabel)
compare(iconImage.x, (control.availableWidth - iconImage.width) / 2)
compare(iconImage.y, (control.availableHeight - iconImage.height) / 2)
+ if (StyleInfo.styleName === "Material") {
+ compare(control.leftPadding, Material.buttonLeftPadding(false, true))
+ compare(control.rightPadding, Material.buttonRightPadding(false, true, false))
+ }
break;
case Button.TextOnly:
verify(!iconImage)
verify(textLabel)
compare(textLabel.x, (control.availableWidth - textLabel.width) / 2)
compare(textLabel.y, (control.availableHeight - textLabel.height) / 2)
+ if (StyleInfo.styleName === "Material") {
+ compare(control.leftPadding, Material.buttonLeftPadding(false, false))
+ compare(control.rightPadding, Material.buttonRightPadding(false, false, true))
+ }
break;
case Button.TextUnderIcon:
verify(iconImage)
@@ -459,6 +470,10 @@ TestCase {
compare(iconImage.x, (control.availableWidth - iconImage.width) / 2)
compare(textLabel.x, (control.availableWidth - textLabel.width) / 2)
verify(iconImage.y < textLabel.y)
+ if (StyleInfo.styleName === "Material") {
+ compare(control.leftPadding, Material.buttonLeftPadding(false, true))
+ compare(control.rightPadding, Material.buttonRightPadding(false, true, true))
+ }
break;
case Button.TextBesideIcon:
verify(iconImage)
@@ -469,6 +484,10 @@ TestCase {
verify(iconImage.x < textLabel.x)
compare(iconImage.y, (control.availableHeight - iconImage.height) / 2)
compare(textLabel.y, (control.availableHeight - textLabel.height) / 2)
+ if (StyleInfo.styleName === "Material") {
+ compare(control.leftPadding, Material.buttonLeftPadding(false, true))
+ compare(control.rightPadding, Material.buttonRightPadding(false, true, true))
+ }
break;
}
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_buttongroup.qml b/tests/auto/quickcontrols/controls/data/tst_buttongroup.qml
index 2ae86d1737..c628a5cb02 100644
--- a/tests/auto/quickcontrols/controls/data/tst_buttongroup.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_buttongroup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -28,14 +28,6 @@ TestCase {
SignalSpy { }
}
- function test_null() {
- var group = createTemporaryObject(buttonGroup, testCase)
- verify(group)
-
- group.addButton(null)
- group.removeButton(null)
- }
-
Component {
id: button
Button { }
@@ -46,10 +38,12 @@ TestCase {
QtObject { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
- var group = createTemporaryObject(buttonGroup, testCase)
+ function test_defaults() {
+ let group = createTemporaryObject(buttonGroup, testCase)
verify(group)
compare(group.buttons.length, 0)
compare(group.checkedButton, null)
@@ -57,17 +51,25 @@ TestCase {
compare(group.checkState, Qt.Unchecked)
}
+ function test_null() {
+ let group = createTemporaryObject(buttonGroup, testCase)
+ verify(group)
+
+ group.addButton(null)
+ group.removeButton(null)
+ }
+
function test_current() {
- var group = createTemporaryObject(buttonGroup, testCase)
+ let group = createTemporaryObject(buttonGroup, testCase)
verify(group)
- var checkedButtonSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "checkedButtonChanged"})
+ let checkedButtonSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "checkedButtonChanged"})
verify(checkedButtonSpy.valid)
verify(!group.checkedButton)
- var button1 = createTemporaryObject(button, testCase, {checked: true})
- var button2 = createTemporaryObject(button, testCase, {checked: false})
- var button3 = createTemporaryObject(button, testCase, {checked: true, objectName: "3"})
+ let button1 = createTemporaryObject(button, testCase, {checked: true})
+ let button2 = createTemporaryObject(button, testCase, {checked: false})
+ let button3 = createTemporaryObject(button, testCase, {checked: true, objectName: "3"})
// add checked
group.addButton(button1)
@@ -127,17 +129,17 @@ TestCase {
}
function test_buttons() {
- var group = createTemporaryObject(buttonGroup, testCase)
+ let group = createTemporaryObject(buttonGroup, testCase)
verify(group)
- var buttonsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "buttonsChanged"})
+ let buttonsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "buttonsChanged"})
verify(buttonsSpy.valid)
compare(group.buttons.length, 0)
compare(group.checkedButton, null)
- var button1 = createTemporaryObject(button, testCase, {checked: true})
- var button2 = createTemporaryObject(button, testCase, {checked: false})
+ let button1 = createTemporaryObject(button, testCase, {checked: true})
+ let button2 = createTemporaryObject(button, testCase, {checked: false})
group.buttons = [button1, button2]
compare(group.buttons.length, 2)
@@ -146,7 +148,7 @@ TestCase {
compare(group.checkedButton, button1)
compare(buttonsSpy.count, 2)
- var button3 = createTemporaryObject(button, testCase, {checked: true})
+ let button3 = createTemporaryObject(button, testCase, {checked: true})
group.addButton(button3)
compare(group.buttons.length, 3)
@@ -177,14 +179,14 @@ TestCase {
}
function test_clicked(data) {
- var group = createTemporaryObject(buttonGroup, testCase, {exclusive: data.exclusive})
+ let group = createTemporaryObject(buttonGroup, testCase, {exclusive: data.exclusive})
verify(group)
- var clickedSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "clicked"})
+ let clickedSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "clicked"})
verify(clickedSpy.valid)
- var button1 = createTemporaryObject(button, testCase)
- var button2 = createTemporaryObject(button, testCase)
+ let button1 = createTemporaryObject(button, testCase)
+ let button2 = createTemporaryObject(button, testCase)
group.addButton(button1)
group.addButton(button2)
@@ -252,7 +254,7 @@ TestCase {
}
function test_controls(data) {
- var container = createTemporaryObject(data.component, testCase)
+ let container = createTemporaryObject(data.component, testCase)
verify(container)
verify(!container.group.checkedButton)
@@ -277,13 +279,13 @@ TestCase {
}
function test_buttonDestroyed() {
- var group = createTemporaryObject(buttonGroup, testCase)
+ let group = createTemporaryObject(buttonGroup, testCase)
verify(group)
- var buttonsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "buttonsChanged"})
+ let buttonsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "buttonsChanged"})
verify(buttonsSpy.valid)
- var button1 = createTemporaryObject(button, testCase, {objectName: "button1", checked: true})
+ let button1 = createTemporaryObject(button, testCase, {objectName: "button1", checked: true})
group.addButton(button1)
compare(group.buttons.length, 1)
@@ -316,7 +318,7 @@ TestCase {
}
function test_repeater() {
- var container = createTemporaryObject(repeater, testCase)
+ let container = createTemporaryObject(repeater, testCase)
verify(container)
verify(container.group.checkedButton)
@@ -324,25 +326,25 @@ TestCase {
}
function test_nonExclusive() {
- var group = createTemporaryObject(nonExclusiveGroup, testCase)
+ let group = createTemporaryObject(nonExclusiveGroup, testCase)
verify(group)
compare(group.checkState, Qt.Unchecked)
- var button1 = createTemporaryObject(button, testCase, {checked: true})
+ let button1 = createTemporaryObject(button, testCase, {checked: true})
group.addButton(button1)
compare(button1.checked, true)
compare(group.checkedButton, null)
compare(group.checkState, Qt.Checked)
- var button2 = createTemporaryObject(button, testCase, {checked: true})
+ let button2 = createTemporaryObject(button, testCase, {checked: true})
group.addButton(button2)
compare(button1.checked, true)
compare(button2.checked, true)
compare(group.checkedButton, null)
compare(group.checkState, Qt.Checked)
- var button3 = createTemporaryObject(button, testCase, {checked: false})
+ let button3 = createTemporaryObject(button, testCase, {checked: false})
group.addButton(button3)
compare(button1.checked, true)
compare(button2.checked, true)
@@ -401,7 +403,7 @@ TestCase {
model: ListModel {
id: listModel
Component.onCompleted: {
- for (var i = 0; i < 10; ++i)
+ for (let i = 0; i < 10; ++i)
append({text: i})
}
}
@@ -410,11 +412,63 @@ TestCase {
}
function test_checkedButtonDestroyed() {
- var column = createTemporaryObject(checkedButtonColumn, testCase)
+ let column = createTemporaryObject(checkedButtonColumn, testCase)
verify(column)
waitForRendering(column)
mouseClick(column.children[0])
wait(0) // don't crash (QTBUG-62946, QTBUG-63470)
}
+
+ Component {
+ id: buttonGroupComp
+
+ Item {
+
+ property ButtonGroup buttonGroup: ButtonGroup { }
+ property int buttonGroupCount: buttonGroup.buttons.length
+ property int buttonGrpSigCnt: 0
+
+ function clearButtonGroup() {
+ buttonGroup.buttons = []
+ }
+ function assignButtonGroup() {
+ radioButton1.ButtonGroup.group = buttonGroup
+ }
+
+ Column {
+ RadioButton {
+ id: radioButton1
+ visible: false
+ ButtonGroup.group: buttonGroup
+ ButtonGroup.onGroupChanged: { (ButtonGroup.group === null) ? --buttonGrpSigCnt : ++buttonGrpSigCnt }
+ }
+ RadioButton {
+ id: radioButton2
+ visible: false
+ ButtonGroup.group: buttonGroup
+ ButtonGroup.onGroupChanged: { (ButtonGroup.group === null) ? --buttonGrpSigCnt : ++buttonGrpSigCnt }
+ }
+ }
+ }
+ }
+
+ function test_resetButtonGroup() {
+ let container = createTemporaryObject(buttonGroupComp, testCase)
+ verify(container)
+
+ // Check for initial buttons assigned to button group
+ compare(container.buttonGroupCount, 2)
+ compare(container.buttonGrpSigCnt, 2)
+ // Clear buttons in the button group
+ container.clearButtonGroup()
+ // Check for buttons in the group and group changed event for buttons
+ compare(container.buttonGroupCount, 0)
+ compare(container.buttonGrpSigCnt, 0)
+ // Assign same group to the button
+ container.assignButtonGroup()
+ // Check for group change event from the button
+ compare(container.buttonGroupCount, 1)
+ compare(container.buttonGrpSigCnt, 1)
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_calendarmodel.qml b/tests/auto/quickcontrols/controls/data/tst_calendarmodel.qml
index 19070e074d..3cb35ab266 100644
--- a/tests/auto/quickcontrols/controls/data/tst_calendarmodel.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_calendarmodel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QtQuick
@@ -29,32 +29,45 @@ TestCase {
}
}
+ function init() {
+ failOnWarning(/.?/)
+ }
+
function test_indices_data() {
return [
+ // "from" and "to" must currently be in the same year.
{ tag: "2013", from: "2013-01-01", to: "2013-12-31", count: 12 },
- { tag: "2016", from: "2016-01-01", to: "2016-03-31", count: 3 }
+ { tag: "2016", from: "2016-01-01", to: "2016-03-31", count: 3 },
+ { tag: "2016-02-01 to 2016-12-31", from: "2016-02-01", to: "2016-12-31", count: 11 },
+ { tag: "2014-11-30 to 2016-01-01", from: "2014-11-30", to: "2016-01-01", count: 15 }
]
}
function test_indices(data) {
- var model = calendarModel.createObject(testCase, {from: data.from, to: data.to})
+ let model = calendarModel.createObject(testCase, {from: data.from, to: data.to})
verify(model)
compare(model.count, data.count)
- var y = parseInt(data.tag)
- for (var m = 0; m < 12; ++m) {
- compare(model.yearAt(m), y)
- compare(model.indexOf(y, m), m)
- compare(model.indexOf(new Date(y, m, 1)), m)
- compare(model.monthAt(m), m)
+ const from = new Date(data.from)
+ const to = new Date(data.to)
+ let index = 0
+ for (let date = from; date <= to; date.setMonth(date.getMonth() + 1, 28), ++index) {
+ compare(model.yearAt(index), date.getFullYear(),
+ `yearAt(${index}) returned incorrect value`)
+ compare(model.indexOf(date.getFullYear(), date.getMonth()), index,
+ `indexOf(${date.getFullYear()}, ${date.getMonth()}) returned incorrect value`)
+ compare(model.indexOf(date), index,
+ `indexOf(${date}) returned incorrect value`)
+ compare(model.monthAt(index), date.getMonth(),
+ `monthAt(${index}) returned incorrect value`)
}
model.destroy()
}
function test_invalid() {
- var model = calendarModel.createObject(testCase)
+ let model = calendarModel.createObject(testCase)
verify(model)
compare(model.indexOf(-1, -1), -1)
@@ -64,11 +77,11 @@ TestCase {
}
function test_instantiator() {
- var inst = instantiator.createObject(testCase)
+ let inst = instantiator.createObject(testCase)
verify(inst)
compare(inst.count, 12)
- for (var m = 0; m < inst.count; ++m) {
+ for (let m = 0; m < inst.count; ++m) {
compare(inst.objectAt(m).month, m)
compare(inst.objectAt(m).year, 2016)
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_checkbox.qml b/tests/auto/quickcontrols/controls/data/tst_checkbox.qml
index 5991ae9008..6c3b859e40 100644
--- a/tests/auto/quickcontrols/controls/data/tst_checkbox.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_checkbox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -25,9 +25,11 @@ TestCase {
}
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(checkBox, testCase)
verify(control)
compare(control.tristate, false)
@@ -35,7 +37,7 @@ TestCase {
}
function test_text() {
- var control = createTemporaryObject(checkBox, testCase)
+ let control = createTemporaryObject(checkBox, testCase)
verify(control)
compare(control.text, "")
@@ -46,10 +48,10 @@ TestCase {
}
function test_checked() {
- var control = createTemporaryObject(checkBox, testCase)
+ let control = createTemporaryObject(checkBox, testCase)
verify(control)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
sequenceSpy.expectedSequence = []
compare(control.checked, false)
@@ -72,10 +74,10 @@ TestCase {
}
function test_checkState() {
- var control = createTemporaryObject(checkBox, testCase)
+ let control = createTemporaryObject(checkBox, testCase)
verify(control)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
sequenceSpy.expectedSequence = []
compare(control.checked, false)
@@ -98,10 +100,10 @@ TestCase {
}
function test_mouse() {
- var control = createTemporaryObject(checkBox, testCase)
+ let control = createTemporaryObject(checkBox, testCase)
verify(control)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
// check
sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }],
@@ -169,12 +171,12 @@ TestCase {
}
function test_touch() {
- var control = createTemporaryObject(checkBox, testCase)
+ let control = createTemporaryObject(checkBox, testCase)
verify(control)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
// check
sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }],
@@ -235,10 +237,10 @@ TestCase {
}
function test_keys() {
- var control = createTemporaryObject(checkBox, testCase)
+ let control = createTemporaryObject(checkBox, testCase)
verify(control)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
sequenceSpy.expectedSequence = []
control.forceActiveFocus()
@@ -277,8 +279,8 @@ TestCase {
sequenceSpy.expectedSequence = []
// Not testing Key_Enter and Key_Return because QGnomeTheme uses them for
// pressing buttons and the CI uses the QGnomeTheme platform theme.
- var keys = [Qt.Key_Escape, Qt.Key_Tab]
- for (var i = 0; i < keys.length; ++i) {
+ let keys = [Qt.Key_Escape, Qt.Key_Tab]
+ for (let i = 0; i < keys.length; ++i) {
sequenceSpy.reset()
keyClick(keys[i])
compare(control.checked, false)
@@ -295,7 +297,7 @@ TestCase {
}
function test_checked_binding() {
- var container = createTemporaryObject(checkedBoundBoxes, testCase)
+ let container = createTemporaryObject(checkedBoundBoxes, testCase)
verify(container)
compare(container.cb1.checked, false)
@@ -325,7 +327,7 @@ TestCase {
}
function test_checkState_binding() {
- var container = createTemporaryObject(checkStateBoundBoxes, testCase)
+ let container = createTemporaryObject(checkStateBoundBoxes, testCase)
verify(container)
compare(container.cb1.checked, false)
@@ -361,9 +363,9 @@ TestCase {
}
function test_tristate() {
- var control = createTemporaryObject(checkBox, testCase, {tristate: true})
+ let control = createTemporaryObject(checkBox, testCase, {tristate: true})
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
sequenceSpy.expectedSequence = []
control.forceActiveFocus()
@@ -457,7 +459,7 @@ TestCase {
}
function test_baseline() {
- var control = createTemporaryObject(checkBox, testCase)
+ let control = createTemporaryObject(checkBox, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
}
@@ -484,7 +486,7 @@ TestCase {
}
function test_nextCheckState(data) {
- var control = createTemporaryObject(nextCheckStateBox, testCase)
+ let control = createTemporaryObject(nextCheckStateBox, testCase)
verify(control)
// mouse
@@ -496,7 +498,7 @@ TestCase {
// touch
control.checkState = data.checkState
compare(control.checkState, data.checkState)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
touch.press(0, control).commit().release(0, control).commit()
compare(control.checkState, data.expectedState)
diff --git a/tests/auto/quickcontrols/controls/data/tst_checkdelegate.qml b/tests/auto/quickcontrols/controls/data/tst_checkdelegate.qml
index d3e0910e83..acb6ebc653 100644
--- a/tests/auto/quickcontrols/controls/data/tst_checkdelegate.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_checkdelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -20,16 +20,18 @@ TestCase {
// TODO: data-fy tst_checkbox (rename to tst_check?) so we don't duplicate its tests here?
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(checkDelegate, testCase);
+ function test_defaults() {
+ let control = createTemporaryObject(checkDelegate, testCase);
verify(control);
verify(!control.checked);
}
function test_checked() {
- var control = createTemporaryObject(checkDelegate, testCase);
+ let control = createTemporaryObject(checkDelegate, testCase);
verify(control);
mouseClick(control);
@@ -40,17 +42,17 @@ TestCase {
}
function test_baseline() {
- var control = createTemporaryObject(checkDelegate, testCase);
+ let control = createTemporaryObject(checkDelegate, testCase);
verify(control);
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset);
}
function test_spacing() {
- var control = createTemporaryObject(checkDelegate, testCase, { text: "Some long, long, long text" })
+ let control = createTemporaryObject(checkDelegate, testCase, { text: "Some long, long, long text" })
verify(control)
verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth)
- var textLabel = findChild(control.contentItem, "label")
+ let textLabel = findChild(control.contentItem, "label")
verify(textLabel)
// The implicitWidth of the IconLabel that all buttons use as their contentItem should be
@@ -77,7 +79,7 @@ TestCase {
}
function test_display(data) {
- var control = createTemporaryObject(checkDelegate, testCase, {
+ let control = createTemporaryObject(checkDelegate, testCase, {
text: "CheckDelegate",
display: data.display,
width: 400,
@@ -87,11 +89,11 @@ TestCase {
verify(control)
compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png")
- var iconImage = findChild(control.contentItem, "image")
- var textLabel = findChild(control.contentItem, "label")
+ let iconImage = findChild(control.contentItem, "image")
+ let textLabel = findChild(control.contentItem, "label")
- var availableWidth = control.availableWidth - control.indicator.width - control.spacing
- var indicatorOffset = control.mirrored ? control.indicator.width + control.spacing : 0
+ let availableWidth = control.availableWidth - control.indicator.width - control.spacing
+ let indicatorOffset = control.mirrored ? control.indicator.width + control.spacing : 0
switch (control.display) {
case CheckDelegate.IconOnly:
@@ -148,7 +150,7 @@ TestCase {
}
function test_nextCheckState(data) {
- var control = createTemporaryObject(nextCheckStateDelegate, testCase)
+ let control = createTemporaryObject(nextCheckStateDelegate, testCase)
verify(control)
// mouse
@@ -160,7 +162,7 @@ TestCase {
// touch
control.checkState = data.checkState
compare(control.checkState, data.checkState)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
touch.press(0, control).commit().release(0, control).commit()
compare(control.checkState, data.expectedState)
diff --git a/tests/auto/quickcontrols/controls/data/tst_combobox.qml b/tests/auto/quickcontrols/controls/data/tst_combobox.qml
index 5bb9d61815..3027d70440 100644
--- a/tests/auto/quickcontrols/controls/data/tst_combobox.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_combobox.qml
@@ -1,10 +1,11 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
import QtTest
import QtQuick.Controls
+import Qt.test.controls
import QtQuick.NativeStyle as NativeStyle
TestCase {
@@ -74,16 +75,7 @@ TestCase {
objectName: "ShaderFX"
width: rect.width
height: rect.height
- fragmentShader: "
- uniform lowp sampler2D source; // this item
- uniform lowp float qt_Opacity; // inherited opacity of this item
- varying highp vec2 qt_TexCoord0;
- void main() {
- lowp vec4 p = texture2D(source, qt_TexCoord0);
- lowp float g = dot(p.xyz, vec3(0.344, 0.5, 0.156));
- gl_FragColor = vec4(g, g, g, p.a) * qt_Opacity;
- }"
-
+ fragmentShader: "combobox/shader.frag.qsb"
}
}
}
@@ -878,22 +870,27 @@ TestCase {
// Account for when a transition of a scale from 0.9-1.0 that it is placed above right away and not below
// first just because there is room at the 0.9 scale
if (control.popup.enter !== null) {
- // hide
- mouseClick(control)
- compare(control.pressed, false)
- tryCompare(control.popup, "visible", false)
- control.y = control.Window.height - (control.popup.contentItem.height * 0.99)
- var popupYSpy = createTemporaryObject(signalSpy, testCase, {target: control.popup, signalName: "yChanged"})
- verify(popupYSpy.valid)
- mousePress(control)
- compare(control.pressed, true)
- compare(control.popup.visible, false)
- mouseRelease(control)
- compare(control.pressed, false)
- compare(control.popup.visible, true)
- tryCompare(control.popup.enter, "running", false)
- verify(control.popup.contentItem.y < control.y)
- verify(popupYSpy.count === 1)
+ // test only if there is a scale animation
+ let scaleAnimation = control.popup.enter.animations.some((animation) => {
+ return (animation instanceof PropertyAnimation && animation.property === "scale")
+ });
+ if (scaleAnimation) {
+ // hide
+ mouseClick(control)
+ compare(control.pressed, false)
+ tryCompare(control.popup, "visible", false)
+ control.y = control.Window.height - (control.popup.contentItem.height * 0.99)
+ var popupYSpy = createTemporaryObject(signalSpy, testCase, {target: control.popup, signalName: "yChanged"})
+ verify(popupYSpy.valid)
+ mousePress(control)
+ compare(control.pressed, true)
+ compare(control.popup.visible, false)
+ mouseRelease(control)
+ compare(control.pressed, false)
+ tryCompare(control.popup, "opened", true)
+ verify(control.popup.contentItem.y < control.y)
+ verify(popupYSpy.count === 1)
+ }
}
var leftLayoutMargin = control.background.layoutMargins === undefined ? 0 : control.popup.layoutMargins.left
@@ -949,7 +946,8 @@ TestCase {
// Check on the second opening that it has the same y position as before
if (i !== 0) {
// y should not have changed again
- verify(popupYSpy.count === 0)
+ if (StyleInfo.styleName !== "FluentWinUI3") // the popup y in FluentWinUI3 depends on the implicitHeight
+ verify(popupYSpy.count === 0)
verify(y === control.innerCombo.popup.y)
} else {
// In some cases on the initial show, y changes more than once
@@ -1024,6 +1022,7 @@ TestCase {
compare(activatedSpy.count, 0)
compare(highlightedSpy.count, 0)
compare(control.popup.visible, true)
+ tryCompare(control.popup, "opened", true)
// press - move - release inside - activated - closed
touch.press(0, content).commit()
@@ -1710,7 +1709,7 @@ TestCase {
ComboBox {
editable: true
property bool gotit: false
- Keys.onPressed: {
+ Keys.onPressed: function (event) {
if (!gotit && event.key === Qt.Key_B) {
gotit = true
event.accepted = true
@@ -1787,7 +1786,7 @@ TestCase {
// Ensure that it's open so that the popup's implicitHeight changes when we increase the model count.
control.popup.open()
- tryCompare(control.popup, "visible", true)
+ tryCompare(control.popup, "opened", true)
// Add lots of items to the model. The popup should take up the entire height of the window.
control.model = 100
@@ -1799,6 +1798,8 @@ TestCase {
control.model = 0
control.popup.open()
tryCompare(control.popup, "visible", true)
+ if (control.popup.enter !== null)
+ tryCompare(control.popup.enter, "running", false)
compare(control.popup.height, control.popup.topPadding + control.popup.bottomPadding)
}
@@ -2004,11 +2005,16 @@ TestCase {
compare(currentIndexSpy.count, 1)
}
+ readonly property font testFont: ({
+ family: "Arial",
+ pixelSize: 12
+ })
+
Component {
- id: appFontTextFieldComponent
+ id: fixedFontTextFieldComponent
TextField {
objectName: "appFontTextField"
- font: Qt.application.font
+ font: testCase.testFont
// We don't want the background's implicit width to interfere with our tests,
// which are about implicit width of the contentItem of ComboBox, which is by default TextField.
background: null
@@ -2016,14 +2022,14 @@ TestCase {
}
Component {
- id: appFontContentItemComboBoxComponent
+ id: fixedFontContentItemComboBoxComponent
ComboBox {
// Override the contentItem so that the font doesn't vary between styles.
contentItem: TextField {
objectName: "appFontContentItemTextField"
// We do this just to be extra sure that the font never comes from the control,
- // as we want it to match that of the TextField in the appFontTextFieldComponent.
- font: Qt.application.font
+ // as we want it to match that of the TextField in the fixedFontTextFieldComponent.
+ font: testCase.testFont
background: null
}
}
@@ -2077,14 +2083,14 @@ TestCase {
function test_implicitContentWidthPolicy_ContentItemImplicitWidth() {
// Set ContentItemImplicitWidth and ensure that implicitContentWidth is as wide as the current item
// by comparing it against the implicitWidth of an identical TextField
- let control = createTemporaryObject(appFontContentItemComboBoxComponent, testCase, {
+ let control = createTemporaryObject(fixedFontContentItemComboBoxComponent, testCase, {
model: ["Short", "Kinda long"],
implicitContentWidthPolicy: ComboBox.ContentItemImplicitWidth
})
verify(control)
compare(control.implicitContentWidthPolicy, ComboBox.ContentItemImplicitWidth)
- let textField = createTemporaryObject(appFontTextFieldComponent, testCase)
+ let textField = createTemporaryObject(fixedFontTextFieldComponent, testCase)
verify(textField)
// Don't set any text on textField because we're not accounting for the widest
// text here, so we want to compare it against an empty TextField.
@@ -2103,14 +2109,14 @@ TestCase {
}
function test_implicitContentWidthPolicy_WidestText(data) {
- let control = createTemporaryObject(appFontContentItemComboBoxComponent, testCase, {
+ let control = createTemporaryObject(fixedFontContentItemComboBoxComponent, testCase, {
model: data.model,
implicitContentWidthPolicy: ComboBox.WidestText
})
verify(control)
compare(control.implicitContentWidthPolicy, ComboBox.WidestText)
- let textField = createTemporaryObject(appFontTextFieldComponent, testCase)
+ let textField = createTemporaryObject(fixedFontTextFieldComponent, testCase)
verify(textField)
textField.text = "Kinda long"
// Note that we don't need to change the current index here, as the implicitContentWidth
@@ -2137,7 +2143,7 @@ TestCase {
// Changes in font should result in the implicitContentWidth being updated.
textField.font.pixelSize *= 2
// We have to change the contentItem's font size manually since we break the
- // style's binding to the control's font when we set Qt.application.font to it.
+ // style's binding to the control's font when we set the fixed font on it.
control.contentItem.font.pixelSize *= 2
control.font.pixelSize *= 2
compare(Math.ceil(control.implicitContentWidth), Math.ceil(textField.implicitWidth))
@@ -2148,14 +2154,14 @@ TestCase {
}
function test_implicitContentWidthPolicy_WidestTextWhenCompleted(data) {
- let control = createTemporaryObject(appFontContentItemComboBoxComponent, testCase, {
+ let control = createTemporaryObject(fixedFontContentItemComboBoxComponent, testCase, {
model: data.model,
implicitContentWidthPolicy: ComboBox.WidestTextWhenCompleted
})
verify(control)
compare(control.implicitContentWidthPolicy, ComboBox.WidestTextWhenCompleted)
- let textField = createTemporaryObject(appFontTextFieldComponent, testCase)
+ let textField = createTemporaryObject(fixedFontTextFieldComponent, testCase)
verify(textField)
textField.text = "Kinda long"
compare(Math.ceil(control.implicitContentWidth), Math.ceil(textField.implicitWidth))
@@ -2277,6 +2283,35 @@ TestCase {
compare(control.currentIndex, 1)
}
+ // QTBUG-109721 - verify that an eaten press event for the space key
+ // doesn't open the popup when the key is released.
+ Component {
+ id: comboboxEatsSpace
+ ComboBox {
+ id: nonEditableComboBox
+ editable: false
+ model: ["NonEditable", "Delta", "Echo", "Foxtrot"]
+ Keys.onSpacePressed: (event) => event.accept
+ }
+ }
+
+ function test_spacePressEaten() {
+ let control = createTemporaryObject(comboboxEatsSpace, testCase)
+ verify(control)
+ control.forceActiveFocus()
+
+ var visibleChangedSpy = signalSpy.createObject(control, {target: control.popup, signalName: "visibleChanged"})
+ verify(visibleChangedSpy.valid)
+
+ // press doesn't open
+ keyPress(Qt.Key_Space)
+ verify(!control.pressed)
+ compare(visibleChangedSpy.count, 0)
+ // neither does release
+ keyRelease(Qt.Key_Space)
+ compare(visibleChangedSpy.count, 0)
+ }
+
Component {
id: listOfGadgets
QtObject {
@@ -2295,4 +2330,25 @@ TestCase {
control.currentIndex = 1;
compare(control.displayText, "7");
}
+
+ function test_contextObject() {
+ // We use the default delegate with required properties and pass
+ // an array of objects as model. This should work despite
+ // ComboBox setting itself as model object for the delegate.
+
+ let control = createTemporaryObject(
+ comboBox, testCase, {model: fruitarray, textRole: "color"});
+ verify(control);
+ compare(control.popup.contentItem.itemAtIndex(0).text, "red");
+
+ // Now we pass an AbstractItemModel with 2 roles. Since we use required properties
+ // the model object should still have the anonymous property, and it should be a
+ // QQmlDMAbstractItemModelData.
+
+ control = createTemporaryObject(comboBox, testCase, { model: fruitmodel });
+ verify(control);
+ for (var i = 0; i < 3; ++i)
+ ignoreWarning(/ComboBox\.qml\:[0-9]+\:[0-9]+\: Unable to assign QQmlDMAbstractItemModelData to QString/);
+ compare(control.popup.contentItem.itemAtIndex(0).text, "");
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_container.qml b/tests/auto/quickcontrols/controls/data/tst_container.qml
index 9988625744..35c9f93b05 100644
--- a/tests/auto/quickcontrols/controls/data/tst_container.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_container.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -24,16 +24,18 @@ TestCase {
Rectangle { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(container, testCase)
verify(control)
compare(control.count, 0)
}
function test_implicitSize() {
- var control = createTemporaryObject(container, testCase)
+ let control = createTemporaryObject(container, testCase)
verify(control)
compare(control.implicitWidth, 0)
@@ -53,16 +55,16 @@ TestCase {
}
function test_currentIndex() {
- var control1 = createTemporaryObject(container, testCase)
+ let control1 = createTemporaryObject(container, testCase)
verify(control1)
- var control2 = createTemporaryObject(container, testCase)
+ let control2 = createTemporaryObject(container, testCase)
verify(control2)
compare(control1.currentIndex, -1)
compare(control2.currentIndex, -1)
- for (var i = 0; i < 3; ++i) {
+ for (let i = 0; i < 3; ++i) {
control1.addItem(rectangle.createObject(control1))
control2.addItem(rectangle.createObject(control2))
}
@@ -130,7 +132,7 @@ TestCase {
// don't crash (QTBUG-61310)
function test_repeater(data) {
- var control = createTemporaryObject(data.component, testCase)
+ let control = createTemporaryObject(data.component, testCase)
verify(control)
compare(control.itemAt(0).objectName, "0")
@@ -140,12 +142,12 @@ TestCase {
}
function test_removeTakeItem() {
- var control = createTemporaryObject(container, testCase)
+ let control = createTemporaryObject(container, testCase)
verify(control)
- var item1 = rectangle.createObject(control)
- var item2 = rectangle.createObject(control)
- var item3 = rectangle.createObject(control)
+ let item1 = rectangle.createObject(control)
+ let item2 = rectangle.createObject(control)
+ let item3 = rectangle.createObject(control)
item1.Component.onDestruction.connect(function() { item1 = null })
item2.Component.onDestruction.connect(function() { item2 = null })
@@ -210,9 +212,9 @@ TestCase {
}
function test_contentItemDeletionOrder() {
- var control1 = createTemporaryObject(contentItemDeletionOrder1, testCase)
+ let control1 = createTemporaryObject(contentItemDeletionOrder1, testCase)
verify(control1)
- var control2 = createTemporaryObject(contentItemDeletionOrder2, testCase)
+ let control2 = createTemporaryObject(contentItemDeletionOrder2, testCase)
verify(control2)
}
@@ -251,9 +253,9 @@ TestCase {
}
function test_backgroundDeletionOrder() {
- var control1 = createTemporaryObject(backgroundDeletionOrder1, testCase)
+ let control1 = createTemporaryObject(backgroundDeletionOrder1, testCase)
verify(control1)
- var control2 = createTemporaryObject(backgroundDeletionOrder2, testCase)
+ let control2 = createTemporaryObject(backgroundDeletionOrder2, testCase)
verify(control2)
}
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_control.qml b/tests/auto/quickcontrols/controls/data/tst_control.qml
index 0747943421..a3e65f2b0f 100644
--- a/tests/auto/quickcontrols/controls/data/tst_control.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_control.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -34,9 +34,11 @@ TestCase {
SignalSpy { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(component, testCase)
verify(control)
compare(control.background, null)
@@ -44,37 +46,37 @@ TestCase {
}
function test_padding() {
- var control = createTemporaryObject(component, testCase)
+ let control = createTemporaryObject(component, testCase)
verify(control)
- var paddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "paddingChanged"})
+ let paddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "paddingChanged"})
verify(paddingSpy.valid)
- var topPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topPaddingChanged"})
+ let topPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topPaddingChanged"})
verify(topPaddingSpy.valid)
- var leftPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftPaddingChanged"})
+ let leftPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftPaddingChanged"})
verify(leftPaddingSpy.valid)
- var rightPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightPaddingChanged"})
+ let rightPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightPaddingChanged"})
verify(rightPaddingSpy.valid)
- var bottomPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomPaddingChanged"})
+ let bottomPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomPaddingChanged"})
verify(bottomPaddingSpy.valid)
- var horizontalPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "horizontalPaddingChanged"})
+ let horizontalPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "horizontalPaddingChanged"})
verify(horizontalPaddingSpy.valid)
- var verticalPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "verticalPaddingChanged"})
+ let verticalPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "verticalPaddingChanged"})
verify(verticalPaddingSpy.valid)
- var paddingChanges = 0
- var topPaddingChanges = 0
- var leftPaddingChanges = 0
- var rightPaddingChanges = 0
- var bottomPaddingChanges = 0
- var horizontalPaddingChanges = 0
- var verticalPaddingChanges = 0
+ let paddingChanges = 0
+ let topPaddingChanges = 0
+ let leftPaddingChanges = 0
+ let rightPaddingChanges = 0
+ let bottomPaddingChanges = 0
+ let horizontalPaddingChanges = 0
+ let verticalPaddingChanges = 0
compare(control.padding, 0)
compare(control.topPadding, 0)
@@ -315,17 +317,17 @@ TestCase {
}
function test_availableSize() {
- var control = createTemporaryObject(component, testCase)
+ let control = createTemporaryObject(component, testCase)
verify(control)
- var availableWidthSpy = signalSpy.createObject(control, {target: control, signalName: "availableWidthChanged"})
+ let availableWidthSpy = signalSpy.createObject(control, {target: control, signalName: "availableWidthChanged"})
verify(availableWidthSpy.valid)
- var availableHeightSpy = signalSpy.createObject(control, {target: control, signalName: "availableHeightChanged"})
+ let availableHeightSpy = signalSpy.createObject(control, {target: control, signalName: "availableHeightChanged"})
verify(availableHeightSpy.valid)
- var availableWidthChanges = 0
- var availableHeightChanges = 0
+ let availableWidthChanges = 0
+ let availableHeightChanges = 0
control.width = 100
compare(control.availableWidth, 100)
@@ -385,10 +387,10 @@ TestCase {
}
function test_mirrored() {
- var control = createTemporaryObject(component, testCase)
+ let control = createTemporaryObject(component, testCase)
verify(control)
- var mirroredSpy = signalSpy.createObject(control, {target: control, signalName: "mirroredChanged"})
+ let mirroredSpy = signalSpy.createObject(control, {target: control, signalName: "mirroredChanged"})
verify(mirroredSpy.valid)
control.locale = Qt.locale("en_US")
@@ -414,7 +416,7 @@ TestCase {
}
function test_background() {
- var control = createTemporaryObject(component, testCase)
+ let control = createTemporaryObject(component, testCase)
verify(control)
control.background = component.createObject(control)
@@ -465,6 +467,36 @@ TestCase {
}
Component {
+ id: backgroundTest2
+ Button {
+ id: btn
+ width: 100
+ height: 100
+ topInset: 0
+ objectName: ""
+
+ background: Rectangle {
+ id: bg
+ implicitHeight: 80
+ border.color: "red"
+ y: btn.objectName === "aaa" ? 20 : 0
+ }
+ }
+ }
+
+ // QTBUG-120033: Make sure that the binding for y on the tab button's background doesn't get removed
+ function test_background2() {
+ let button = createTemporaryObject(backgroundTest2, testCase)
+ verify(button)
+
+ verify(button.background.y === 0)
+ button.objectName = "aaa"
+ verify(button.background.y === 20)
+ button.objectName = ""
+ verify(button.background.y === 0)
+ }
+
+ Component {
id: component2
T.Control {
id: item2
@@ -502,7 +534,7 @@ TestCase {
}
function test_font() {
- var control2 = createTemporaryObject(component2, testCase)
+ let control2 = createTemporaryObject(component2, testCase)
verify(control2)
verify(control2.item2_2)
verify(control2.item2_3)
@@ -645,7 +677,7 @@ TestCase {
}
function test_font_2() {
- var control3 = createTemporaryObject(component3, testCase)
+ let control3 = createTemporaryObject(component3, testCase)
verify(control3)
verify(control3.item3_2)
verify(control3.item3_3)
@@ -760,14 +792,14 @@ TestCase {
}
function test_font_3() {
- var control4 = createTemporaryObject(component4, testCase)
+ let control4 = createTemporaryObject(component4, testCase)
verify(control4)
verify(control4.item4_2)
verify(control4.item4_3)
verify(control4.item4_4)
- var family = control4.font.family
- var ps = control4.font.pixelSize
+ let family = control4.font.family
+ let ps = control4.font.pixelSize
compare(control4.item4_2.font.family, control4.font.family)
compare(control4.item4_3.font.family, control4.font.family)
@@ -797,19 +829,19 @@ TestCase {
}
function test_font_explicit_attributes(data) {
- var control = createTemporaryObject(component, testCase)
+ let control = createTemporaryObject(component, testCase)
verify(control)
- var child = component.createObject(control)
+ let child = component.createObject(control)
verify(child)
- var controlSpy = signalSpy.createObject(control, {target: control, signalName: "fontChanged"})
+ let controlSpy = signalSpy.createObject(control, {target: control, signalName: "fontChanged"})
verify(controlSpy.valid)
- var childSpy = signalSpy.createObject(child, {target: child, signalName: "fontChanged"})
+ let childSpy = signalSpy.createObject(child, {target: child, signalName: "fontChanged"})
verify(childSpy.valid)
- var defaultValue = control.font[data.tag]
+ let defaultValue = control.font[data.tag]
child.font[data.tag] = defaultValue
compare(child.font[data.tag], defaultValue)
@@ -825,7 +857,7 @@ TestCase {
}
function test_locale() {
- var control = createTemporaryObject(component, testCase)
+ let control = createTemporaryObject(component, testCase)
verify(control)
control.locale = Qt.locale("en_US")
@@ -896,12 +928,12 @@ TestCase {
}
function test_locale_2() {
- var control = createTemporaryObject(component5, testCase)
+ let control = createTemporaryObject(component5, testCase)
verify(control)
verify(control.item2_2)
verify(control.item2_3)
- var defaultLocale = Qt.locale()
+ let defaultLocale = Qt.locale()
compare(control.locale.name, defaultLocale.name)
compare(control.item2_2.locale.name, defaultLocale.name)
@@ -989,14 +1021,14 @@ TestCase {
}
function test_locale_3() {
- var control = createTemporaryObject(component6, testCase)
+ let control = createTemporaryObject(component6, testCase)
verify(control)
verify(control.item6_2)
verify(control.item6_3)
verify(control.item6_4)
verify(control.item6_5)
- var defaultLocale = Qt.locale()
+ let defaultLocale = Qt.locale()
compare(control.locale.name, defaultLocale.name)
compare(control.item6_5.locale.name, defaultLocale.name)
@@ -1028,7 +1060,7 @@ TestCase {
}
function test_hover(data) {
- var control = createTemporaryObject(data.target, testCase, {width: 100, height: 100})
+ let control = createTemporaryObject(data.target, testCase, {width: 100, height: 100})
verify(control)
compare(control.hovered, false)
@@ -1065,17 +1097,17 @@ TestCase {
}
function test_hoverEnabled() {
- var control = createTemporaryObject(component, testCase)
+ let control = createTemporaryObject(component, testCase)
compare(control.hoverEnabled, Qt.styleHints.useHoverEffects)
- var child = component.createObject(control)
- var grandChild = component.createObject(child)
+ let child = component.createObject(control)
+ let grandChild = component.createObject(child)
- var childExplicitHoverEnabled = component.createObject(control, {hoverEnabled: true})
- var grandChildExplicitHoverDisabled = component.createObject(childExplicitHoverEnabled, {hoverEnabled: false})
+ let childExplicitHoverEnabled = component.createObject(control, {hoverEnabled: true})
+ let grandChildExplicitHoverDisabled = component.createObject(childExplicitHoverEnabled, {hoverEnabled: false})
- var childExplicitHoverDisabled = component.createObject(control, {hoverEnabled: false})
- var grandChildExplicitHoverEnabled = component.createObject(childExplicitHoverDisabled, {hoverEnabled: true})
+ let childExplicitHoverDisabled = component.createObject(control, {hoverEnabled: false})
+ let grandChildExplicitHoverEnabled = component.createObject(childExplicitHoverDisabled, {hoverEnabled: true})
control.hoverEnabled = false
compare(control.hoverEnabled, false)
@@ -1099,33 +1131,33 @@ TestCase {
}
function test_implicitSize() {
- var control = createTemporaryObject(component, testCase)
+ let control = createTemporaryObject(component, testCase)
verify(control)
- var implicitWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitWidthChanged"})
+ let implicitWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitWidthChanged"})
verify(implicitWidthSpy.valid)
- var implicitHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitHeightChanged"})
+ let implicitHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitHeightChanged"})
verify(implicitHeightSpy.valid)
- var implicitContentWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitContentWidthChanged"})
+ let implicitContentWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitContentWidthChanged"})
verify(implicitContentWidthSpy.valid)
- var implicitContentHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitContentHeightChanged"})
+ let implicitContentHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitContentHeightChanged"})
verify(implicitContentHeightSpy.valid)
- var implicitBackgroundWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundWidthChanged"})
+ let implicitBackgroundWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundWidthChanged"})
verify(implicitBackgroundWidthSpy.valid)
- var implicitBackgroundHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundHeightChanged"})
+ let implicitBackgroundHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundHeightChanged"})
verify(implicitBackgroundHeightSpy.valid)
- var implicitWidthChanges = 0
- var implicitHeightChanges = 0
- var implicitContentWidthChanges = 0
- var implicitContentHeightChanges = 0
- var implicitBackgroundWidthChanges = 0
- var implicitBackgroundHeightChanges = 0
+ let implicitWidthChanges = 0
+ let implicitHeightChanges = 0
+ let implicitContentWidthChanges = 0
+ let implicitContentHeightChanges = 0
+ let implicitBackgroundWidthChanges = 0
+ let implicitBackgroundHeightChanges = 0
compare(control.implicitWidth, 0)
compare(control.implicitHeight, 0)
@@ -1194,12 +1226,12 @@ TestCase {
}
function test_baseline() {
- var control = createTemporaryObject(component, testCase)
+ let control = createTemporaryObject(component, testCase)
verify(control)
compare(control.baselineOffset, 0)
- var baselineSpy = signalSpy.createObject(control, {target: control, signalName: "baselineOffsetChanged"})
+ let baselineSpy = signalSpy.createObject(control, {target: control, signalName: "baselineOffsetChanged"})
verify(baselineSpy.valid)
control.contentItem = rectangle.createObject(control, {baselineOffset: 12})
@@ -1232,25 +1264,25 @@ TestCase {
}
function test_inset() {
- var control = createTemporaryObject(component, testCase, {background: rectangle.createObject(control)})
+ let control = createTemporaryObject(component, testCase, {background: rectangle.createObject(null)})
verify(control)
- var topInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topInsetChanged"})
+ let topInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topInsetChanged"})
verify(topInsetSpy.valid)
- var leftInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftInsetChanged"})
+ let leftInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftInsetChanged"})
verify(leftInsetSpy.valid)
- var rightInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightInsetChanged"})
+ let rightInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightInsetChanged"})
verify(rightInsetSpy.valid)
- var bottomInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomInsetChanged"})
+ let bottomInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomInsetChanged"})
verify(bottomInsetSpy.valid)
- var topInsetChanges = 0
- var leftInsetChanges = 0
- var rightInsetChanges = 0
- var bottomInsetChanges = 0
+ let topInsetChanges = 0
+ let leftInsetChanges = 0
+ let rightInsetChanges = 0
+ let bottomInsetChanges = 0
compare(control.topInset, 0)
compare(control.leftInset, 0)
@@ -1412,9 +1444,9 @@ TestCase {
}
function test_contentItemDeletionOrder() {
- var control1 = createTemporaryObject(contentItemDeletionOrder1, testCase)
+ let control1 = createTemporaryObject(contentItemDeletionOrder1, testCase)
verify(control1)
- var control2 = createTemporaryObject(contentItemDeletionOrder2, testCase)
+ let control2 = createTemporaryObject(contentItemDeletionOrder2, testCase)
verify(control2)
}
@@ -1453,9 +1485,9 @@ TestCase {
}
function test_backgroundDeletionOrder() {
- var control1 = createTemporaryObject(backgroundDeletionOrder1, testCase)
+ let control1 = createTemporaryObject(backgroundDeletionOrder1, testCase)
verify(control1)
- var control2 = createTemporaryObject(backgroundDeletionOrder2, testCase)
+ let control2 = createTemporaryObject(backgroundDeletionOrder2, testCase)
verify(control2)
}
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_dayofweekrow.qml b/tests/auto/quickcontrols/controls/data/tst_dayofweekrow.qml
index 67403e240a..b93337e62d 100644
--- a/tests/auto/quickcontrols/controls/data/tst_dayofweekrow.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_dayofweekrow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
@@ -18,15 +18,17 @@ TestCase {
DayOfWeekRow { }
}
- function test_defaults() {
+ function init () {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(component, testCase)
verify(control)
}
function test_locale() {
- var control = component.createObject(testCase)
+ let control = component.createObject(testCase)
verify(control.contentItem.children[0])
@@ -43,7 +45,7 @@ TestCase {
}
function test_font() {
- var control = component.createObject(testCase)
+ let control = component.createObject(testCase)
verify(control.contentItem.children[0])
diff --git a/tests/auto/quickcontrols/controls/data/tst_delaybutton.qml b/tests/auto/quickcontrols/controls/data/tst_delaybutton.qml
index e2abe389ca..708e6a8a22 100644
--- a/tests/auto/quickcontrols/controls/data/tst_delaybutton.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_delaybutton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -38,18 +38,20 @@ TestCase {
SignalSpy { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(defaultComponent, testCase)
verify(control)
}
function test_mouse() {
- var control = createTemporaryObject(delayButton, testCase)
+ let control = createTemporaryObject(delayButton, testCase)
verify(control)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
// click
sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
@@ -145,12 +147,12 @@ TestCase {
}
function test_touch() {
- var control = createTemporaryObject(delayButton, testCase)
+ let control = createTemporaryObject(delayButton, testCase)
verify(control)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
// click
sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
@@ -224,13 +226,13 @@ TestCase {
}
function test_keys() {
- var control = createTemporaryObject(delayButton, testCase)
+ let control = createTemporaryObject(delayButton, testCase)
verify(control)
control.forceActiveFocus()
verify(control.activeFocus)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
// click
sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
@@ -275,8 +277,8 @@ TestCase {
sequenceSpy.expectedSequence = []
// Not testing Key_Enter and Key_Return because QGnomeTheme uses them for
// pressing buttons and the CI uses the QGnomeTheme platform theme.
- var keys = [Qt.Key_Escape, Qt.Key_Tab]
- for (var i = 0; i < keys.length; ++i) {
+ let keys = [Qt.Key_Escape, Qt.Key_Tab]
+ for (let i = 0; i < keys.length; ++i) {
sequenceSpy.reset()
keyClick(keys[i])
verify(sequenceSpy.success)
@@ -284,10 +286,10 @@ TestCase {
}
function test_progress() {
- var control = createTemporaryObject(delayButton, testCase)
+ let control = createTemporaryObject(delayButton, testCase)
verify(control)
- var progressSpy = signalSpy.createObject(control, {target: control, signalName: "progressChanged"})
+ let progressSpy = signalSpy.createObject(control, {target: control, signalName: "progressChanged"})
verify(progressSpy.valid)
compare(control.progress, 0.0)
@@ -297,7 +299,7 @@ TestCase {
}
function test_baseline() {
- var control = createTemporaryObject(delayButton, testCase)
+ let control = createTemporaryObject(delayButton, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_dial.qml b/tests/auto/quickcontrols/controls/data/tst_dial.qml
index 3fcf8c7e88..1f2b9fdd5c 100644
--- a/tests/auto/quickcontrols/controls/data/tst_dial.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_dial.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -27,10 +27,13 @@ TestCase {
SignalSpy {}
}
- function test_instance() {
+ function init() {
+ // Fail on any warning that we don't expect.
failOnWarning(/.?/)
+ }
- var dial = createTemporaryObject(dialComponent, testCase);
+ function test_instance() {
+ let dial = createTemporaryObject(dialComponent, testCase);
verify(dial);
compare(dial.value, 0.0);
compare(dial.from, 0.0);
@@ -41,7 +44,7 @@ TestCase {
}
function test_value() {
- var dial = createTemporaryObject(dialComponent, testCase);
+ let dial = createTemporaryObject(dialComponent, testCase);
verify(dial);
compare(dial.value, 0.0);
@@ -59,7 +62,7 @@ TestCase {
}
function test_range() {
- var dial = createTemporaryObject(dialComponent, testCase);
+ let dial = createTemporaryObject(dialComponent, testCase);
verify(dial);
dial.from = 0;
@@ -94,7 +97,7 @@ TestCase {
}
function test_inverted() {
- var dial = createTemporaryObject(dialComponent, testCase, { from: 1.0, to: -1.0 });
+ let dial = createTemporaryObject(dialComponent, testCase, { from: 1.0, to: -1.0 });
verify(dial);
compare(dial.from, 1.0);
compare(dial.to, -1.0);
@@ -120,7 +123,7 @@ TestCase {
}
function test_pressed() {
- var dial = createTemporaryObject(dialComponent, testCase);
+ let dial = createTemporaryObject(dialComponent, testCase);
verify(dial);
pressSpy.target = dial;
@@ -135,7 +138,7 @@ TestCase {
verify(!dial.pressed);
compare(pressSpy.count, 2);
- var touch = touchEvent(dial);
+ let touch = touchEvent(dial);
touch.press(0).commit();
verify(dial.pressed);
compare(pressSpy.count, 3);
@@ -160,7 +163,7 @@ TestCase {
}
function test_dragging(data) {
- var dial = createTemporaryObject(dialComponent, testCase);
+ let dial = createTemporaryObject(dialComponent, testCase);
verify(dial);
dial.wrap = true;
@@ -172,10 +175,10 @@ TestCase {
valueSpy.target = dial;
verify(valueSpy.valid);
- var moveSpy = createTemporaryObject(signalSpy, testCase, {target: dial, signalName: "moved"});
+ let moveSpy = createTemporaryObject(signalSpy, testCase, {target: dial, signalName: "moved"});
verify(moveSpy.valid);
- var minimumExpectedValueCount = data.live ? 2 : 1;
+ let minimumExpectedValueCount = data.live ? 2 : 1;
// drag to the left
// we always add or subtract 1 to ensure we start the drag from the opposite side
@@ -217,55 +220,56 @@ TestCase {
}
function test_nonWrapping() {
- var dial = createTemporaryObject(dialComponent, testCase);
+ let dial = createTemporaryObject(dialComponent, testCase);
verify(dial);
compare(dial.wrap, false);
dial.value = 0;
// Ensure that dragging from bottom left to bottom right doesn't work.
- var yPos = dial.height * 0.75;
+ let yPos = dial.height * 0.75;
mousePress(dial, dial.width * 0.25, yPos, Qt.LeftButton);
- var positionAtPress = dial.position;
+ let positionAtPress = dial.position;
mouseMove(dial, dial.width * 0.5, yPos);
- compare(dial.position, positionAtPress);
+ verify(dial.position < positionAtPress);
mouseMove(dial, dial.width * 0.75, yPos);
- compare(dial.position, positionAtPress);
+ verify(dial.position < positionAtPress);
mouseRelease(dial, dial.width * 0.75, yPos, Qt.LeftButton);
- compare(dial.position, positionAtPress);
+ verify(dial.position < positionAtPress);
// Try the same thing, but a bit higher.
yPos = dial.height * 0.6;
mousePress(dial, dial.width * 0.25, yPos, Qt.LeftButton);
positionAtPress = dial.position;
mouseMove(dial, dial.width * 0.5, yPos);
- compare(dial.position, positionAtPress);
+ verify(dial.position < positionAtPress);
mouseMove(dial, dial.width * 0.75, yPos);
- compare(dial.position, positionAtPress);
+ verify(dial.position < positionAtPress);
mouseRelease(dial, dial.width * 0.75, yPos, Qt.LeftButton);
- compare(dial.position, positionAtPress);
+ verify(dial.position < positionAtPress);
// Going from below the center of the dial to above it should work (once it gets above the center).
mousePress(dial, dial.width * 0.25, dial.height * 0.75, Qt.LeftButton);
positionAtPress = dial.position;
mouseMove(dial, dial.width * 0.5, dial.height * 0.6);
- compare(dial.position, positionAtPress);
- mouseMove(dial, dial.width * 0.75, dial.height * 0.4);
+ verify(dial.position < positionAtPress);
+ mouseMove(dial, dial.width * 0.5, dial.height * 0.4); //move over the top
+ mouseMove(dial, dial.width * 0.75, dial.height * 0.6); //and back down again
verify(dial.position > positionAtPress);
mouseRelease(dial, dial.width * 0.75, dial.height * 0.3, Qt.LeftButton);
verify(dial.position > positionAtPress);
}
function test_touch() {
- var dial = createTemporaryObject(dialComponent, testCase);
+ let dial = createTemporaryObject(dialComponent, testCase);
verify(dial);
- var touch = touchEvent(dial);
+ let touch = touchEvent(dial);
// Ensure that dragging from bottom left to bottom right doesn't work.
- var yPos = dial.height * 0.75;
+ let yPos = dial.height * 0.75;
touch.press(0, dial, dial.width * 0.25, yPos).commit();
- var positionAtPress = dial.position;
+ let positionAtPress = dial.position;
touch.move(0, dial, dial.width * 0.5, yPos).commit();
compare(dial.position, positionAtPress);
touch.move(0, dial, dial.width * 0.75, yPos).commit();
@@ -289,22 +293,23 @@ TestCase {
positionAtPress = dial.position;
touch.move(0, dial, dial.width * 0.5, dial.height * 0.6).commit();
compare(dial.position, positionAtPress);
- touch.move(0, dial, dial.width * 0.75, dial.height * 0.4).commit();
+ touch.move(0, dial, dial.width * 0.5, dial.height * 0.4).commit(); //move over the top
+ touch.move(0, dial, dial.width * 0.75, dial.height * 0.6).commit(); //and back down again
verify(dial.position > positionAtPress);
touch.release(0, dial, dial.width * 0.75, dial.height * 0.3).commit();
verify(dial.position > positionAtPress);
}
function test_multiTouch() {
- var dial1 = createTemporaryObject(dialComponent, testCase);
+ let dial1 = createTemporaryObject(dialComponent, testCase);
verify(dial1);
- var touch = touchEvent(dial1);
+ let touch = touchEvent(dial1);
touch.press(0, dial1).commit().move(0, dial1, dial1.width / 4, dial1.height / 4).commit();
compare(dial1.pressed, true);
verify(dial1.position > 0.0);
- var pos1Before = dial1.position;
+ let pos1Before = dial1.position;
// second touch point on the same control is ignored
touch.stationary(0).press(1, dial1, 0, 0).commit()
@@ -313,7 +318,7 @@ TestCase {
compare(dial1.pressed, true);
compare(dial1.position, pos1Before);
- var dial2 = createTemporaryObject(dialComponent, testCase, {y: dial1.height});
+ let dial2 = createTemporaryObject(dialComponent, testCase, {y: dial1.height});
verify(dial2);
// press the second dial
@@ -322,7 +327,7 @@ TestCase {
compare(dial2.position, 0.0);
pos1Before = dial1.position;
- var pos2Before = dial2.position;
+ let pos2Before = dial2.position;
// move both dials
touch.move(0, dial1).move(2, dial2, dial2.width / 4, dial2.height / 4).commit();
@@ -354,19 +359,19 @@ TestCase {
}
function test_keyboardNavigation() {
- var dial = createTemporaryObject(dialComponent, testCase);
+ let dial = createTemporaryObject(dialComponent, testCase);
verify(dial);
- var focusScope = createTemporaryObject(focusTest, testCase);
+ let focusScope = createTemporaryObject(focusTest, testCase);
verify(focusScope);
- var moveCount = 0;
+ let moveCount = 0;
// Tests that we've accepted events that we're interested in.
parentEventSpy.target = focusScope;
parentEventSpy.signalName = "receivedKeyPress";
- var moveSpy = createTemporaryObject(signalSpy, testCase, {target: dial, signalName: "moved"});
+ let moveSpy = createTemporaryObject(signalSpy, testCase, {target: dial, signalName: "moved"});
verify(moveSpy.valid);
dial.parent = focusScope;
@@ -382,10 +387,10 @@ TestCase {
compare(moveSpy.count, moveCount);
compare(dial.value, 0);
- var oldValue = 0.0;
- var keyPairs = [[Qt.Key_Left, Qt.Key_Right], [Qt.Key_Down, Qt.Key_Up]];
- for (var keyPairIndex = 0; keyPairIndex < 2; ++keyPairIndex) {
- for (var i = 1; i <= 10; ++i) {
+ let oldValue = 0.0;
+ let keyPairs = [[Qt.Key_Left, Qt.Key_Right], [Qt.Key_Down, Qt.Key_Up]];
+ for (let keyPairIndex = 0; keyPairIndex < 2; ++keyPairIndex) {
+ for (let i = 1; i <= 10; ++i) {
oldValue = dial.value;
keyClick(keyPairs[keyPairIndex][1]);
compare(parentEventSpy.count, 0);
@@ -396,7 +401,7 @@ TestCase {
compare(dial.value, dial.to);
- for (i = 10; i > 0; --i) {
+ for (let i = 10; i > 0; --i) {
oldValue = dial.value;
keyClick(keyPairs[keyPairIndex][0]);
compare(parentEventSpy.count, 0);
@@ -434,7 +439,7 @@ TestCase {
{ tag: "NoSnap", snapMode: Dial.NoSnap, from: 0, to: 2, values: [0, 0, 1], positions: [0, 0.5, 0.5] },
{ tag: "SnapAlways (0..2)", snapMode: Dial.SnapAlways, from: 0, to: 2, values: [0.0, 0.0, 1.0], positions: [0.0, 0.5, 0.5] },
{ tag: "SnapAlways (1..3)", snapMode: Dial.SnapAlways, from: 1, to: 3, values: [1.0, 1.0, 2.0], positions: [0.0, 0.5, 0.5] },
- { tag: "SnapAlways (-1..1)", snapMode: Dial.SnapAlways, from: -1, to: 1, values: [0.0, 0.0, 0.0], positions: [0.5, 0.5, 0.5] },
+ { tag: "SnapAlways (-1..1)", snapMode: Dial.SnapAlways, from: -1, to: 1, values: [0.0, 0.0, 0.0], positions: [immediate ? 0.0 : 0.5, 0.5, 0.5] },
{ tag: "SnapAlways (1..-1)", snapMode: Dial.SnapAlways, from: 1, to: -1, values: [1.0, 1.0, 0.0], positions: [0.0, 0.5, 0.5] },
{ tag: "SnapOnRelease (0..2)", snapMode: Dial.SnapOnRelease, from: 0, to: 2, values: [0.0, 0.0, 1.0], positions: [0.0, 0.5, 0.5] },
{ tag: "SnapOnRelease (1..3)", snapMode: Dial.SnapOnRelease, from: 1, to: 3, values: [1.0, 1.0, 2.0], positions: [0.0, 0.5, 0.5] },
@@ -448,7 +453,7 @@ TestCase {
}
function test_snapMode_mouse(data) {
- var dial = createTemporaryObject(dialComponent, testCase, {live: false});
+ let dial = createTemporaryObject(dialComponent, testCase, {live: false});
verify(dial);
dial.snapMode = data.snapMode;
@@ -456,7 +461,7 @@ TestCase {
dial.to = data.to;
dial.stepSize = 0.2;
- var fuzz = 0.055;
+ let fuzz = 0.055;
mousePress(dial, dial.width * 0.25, dial.height * 0.75);
fuzzyCompare(dial.value, data.values[0], fuzz);
@@ -476,7 +481,7 @@ TestCase {
}
function test_snapMode_touch(data) {
- var dial = createTemporaryObject(dialComponent, testCase, {live: false});
+ let dial = createTemporaryObject(dialComponent, testCase, {live: false});
verify(dial);
dial.snapMode = data.snapMode;
@@ -484,9 +489,9 @@ TestCase {
dial.to = data.to;
dial.stepSize = 0.2;
- var fuzz = 0.05;
+ let fuzz = 0.05;
- var touch = touchEvent(dial);
+ let touch = touchEvent(dial);
touch.press(0, dial, dial.width * 0.25, dial.height * 0.75).commit()
compare(dial.value, data.values[0]);
compare(dial.position, data.positions[0]);
@@ -502,13 +507,13 @@ TestCase {
function test_wheel_data() {
return [
- { tag: "horizontal", orientation: Qt.Horizontal, dx: 120, dy: 0 },
- { tag: "vertical", orientation: Qt.Vertical, dx: 0, dy: 120 }
+ { tag: "horizontal", dx: 120, dy: 0 },
+ { tag: "vertical", dx: 0, dy: 120 }
]
}
function test_wheel(data) {
- var control = createTemporaryObject(dialComponent, testCase, {wheelEnabled: true, orientation: data.orientation})
+ let control = createTemporaryObject(dialComponent, testCase, {wheelEnabled: true})
verify(control)
compare(control.value, 0.0)
@@ -546,7 +551,7 @@ TestCase {
}
function test_nullHandle() {
- var control = createTemporaryObject(dialComponent, testCase)
+ let control = createTemporaryObject(dialComponent, testCase)
verify(control)
control.handle = null
@@ -562,7 +567,7 @@ TestCase {
if (inputEventType === "mouseInput") {
mouseMove(control, x, y);
} else {
- var touch = touchEvent(control);
+ let touch = touchEvent(control);
touch.move(0, control, x, y).commit();
}
}
@@ -571,7 +576,7 @@ TestCase {
if (inputEventType === "mouseInput") {
mousePress(control, x, y);
} else {
- var touch = touchEvent(control);
+ let touch = touchEvent(control);
touch.press(0, control, x, y).commit();
}
}
@@ -580,13 +585,13 @@ TestCase {
if (inputEventType === "mouseInput") {
mouseRelease(control, x, y);
} else {
- var touch = touchEvent(control);
+ let touch = touchEvent(control);
touch.release(0, control, x, y).commit();
}
}
function test_horizontalAndVertical_data() {
- var data = [
+ let data = [
{ eventType: "mouseInput", inputMode: Dial.Vertical, moveToX: 0.5, moveToY: 0.25, expectedPosition: 0.125 },
// Horizontal movement should have no effect on a vertical dial.
{ eventType: "mouseInput", inputMode: Dial.Vertical, moveToX: 2.0, moveToY: 0.25, expectedPosition: 0.125 },
@@ -612,15 +617,15 @@ TestCase {
];
// Do the same tests for touch by copying the mouse tests and adding them to the end of the array.
- var mouseTestCount = data.length;
- for (var i = mouseTestCount; i < mouseTestCount * 2; ++i) {
+ let mouseTestCount = data.length;
+ for (let i = mouseTestCount; i < mouseTestCount * 2; ++i) {
// Shallow-copy the object.
data[i] = JSON.parse(JSON.stringify(data[i - mouseTestCount]));
data[i].eventType = "touchInput";
}
- for (i = 0; i < data.length; ++i) {
- var row = data[i];
+ for (let i = 0; i < data.length; ++i) {
+ let row = data[i];
row.tag = "eventType=" + row.eventType + ", "
+ "inputMode=" + (row.inputMode === Dial.Vertical ? "Vertical" : "Horizontal") + ", "
+ "moveToX=" + row.moveToX + ", moveToY=" + row.moveToY + ", "
@@ -631,7 +636,7 @@ TestCase {
}
function test_horizontalAndVertical(data) {
- var control = createTemporaryObject(dialComponent, testCase, { inputMode: data.inputMode });
+ let control = createTemporaryObject(dialComponent, testCase, { inputMode: data.inputMode });
verify(control);
press(data.eventType, control);
@@ -648,7 +653,7 @@ TestCase {
}
function test_integerStepping() {
- var dial = createTemporaryObject(dialComponent, testCase)
+ let dial = createTemporaryObject(dialComponent, testCase)
verify(dial)
dial.from = 1
@@ -661,4 +666,202 @@ TestCase {
keyClick(Qt.Key_Right)
}
}
+
+ function test_startEndAngle_data() {
+ return [
+ {
+ tag: "Default wrap", startAngle: -140, endAngle: 140, from: 0, to: 1, wrap: true,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49, 0.51],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99, 0.99],
+ values: [0.0, 0.5-0.32, 0.5, 0.5+0.32, 1.0, 0.0, 1.0], //140/90*0.5 = 0.32
+ angles: [-140.0, -90.0, 0.0, 90.0, 140.0, -140.0, 140.0],
+ wrapClockwise: 1,
+ wrapCounterClockwise: 1
+ },
+ {
+ tag: "-30..30 wrap", startAngle: -30, endAngle: 30, from: 0, to: 1, wrap: true,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49, 0.51],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99, 0.99],
+ values: [0.0, 0.0, 0.5, 1.0, 1.0, 0.0, 1.0],
+ angles: [-30.0, -30.0, 0.0, 30.0, 30.0, -30.0, 30.0],
+ wrapClockwise: 0, //no wrap if angle < 180
+ wrapCounterClockwise: 0
+ },
+ {
+ tag: "-180..180 wrap", startAngle: -180, endAngle: 180, from: 0, to: 1, wrap: true,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49, 0.51],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99, 0.99],
+ values: [0.0, 0.25, 0.5, 0.75, 1.0, 0.0, 1.0],
+ angles: [-180.0, -90.0, 0.0, 90.0, 180.0, -180.0, 180.0],
+ wrapClockwise: 1,
+ wrapCounterClockwise: 1
+ },
+ {
+ tag: "90..360 wrap", startAngle: 90, endAngle: 360, from: 0, to: 1, wrap: true,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49, 0.5],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99, 0.01],
+ values: [0.33, 0.66, 1.0, 0.0, 0.33, 0.33, 1.0],
+ angles: [180.0, 270.0, 360.0, 90.0, 180.0, 180.0, 360.0],
+ wrapClockwise: 1,
+ wrapCounterClockwise: 1
+ },
+ {
+ tag: "90..450 wrap", startAngle: 90, endAngle: 450, from: 0, to: 1, wrap: true,
+ x: [0.49, 0.25, 0.5, 0.75, 0.75, 0.51, 0.49, 0.75, 0.75],
+ y: [0.99, 0.5, 0.01, 0.49, 0.501, 0.99, 0.99, 0.49, 0.501],
+ values: [0.25, 0.5, 0.75, 1.0, 0.0, 0.25, 0.25, 1.0, 0.0],
+ angles: [180.0, 270.0, 360.0, 450.0, 90.0, 180.0, 180.0, 450.0, 90.0],
+ wrapClockwise: 2,
+ wrapCounterClockwise: 1
+ },
+ {
+ tag: "Default nowrap", startAngle: -140, endAngle: 140, from: 0, to: 1, wrap: false,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99],
+ values: [0.0, 0.5-0.32, 0.5, 0.5+0.32, 1.0, 1.0], //140/90*0.5 = 0.32
+ angles: [-140.0, -90.0, 0.0, 90.0, 140.0, 140.0],
+ wrapClockwise: 0,
+ wrapCounterClockwise: 0
+ },
+ {
+ tag: "-30..30 nowrap", startAngle: -30, endAngle: 30, from: 0, to: 1, wrap: false,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99],
+ values: [0.0, 0.0, 0.5, 1.0, 1.0, 1.0],
+ angles: [-30.0, -30.0, 0.0, 30.0, 30.0, 30.0],
+ wrapClockwise: 0,
+ wrapCounterClockwise: 0
+ },
+ {
+ tag: "-180..180 nowrap", startAngle: -180, endAngle: 180, from: 0, to: 1, wrap: false,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99],
+ values: [0.0, 0.25, 0.5, 0.75, 1.0, 1.0],
+ angles: [-180.0, -90.0, 0.0, 90.0, 180.0, 180.0],
+ wrapClockwise: 0,
+ wrapCounterClockwise: 0
+ },
+ {
+ tag: "90..360 nowrap", startAngle: 90, endAngle: 360, from: 0, to: 1, wrap: false,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99],
+ values: [0.33, 0.66, 1.0, 1.0, 1.0, 1.0],
+ angles: [180.0, 270.0, 360.0, 360.0, 360.0, 360.0],
+ wrapClockwise: 0,
+ wrapCounterClockwise: 0
+ }
+ ]
+ }
+
+ function test_startEndAngle(data) {
+ let dial = createTemporaryObject(dialComponent, testCase)
+ verify(dial)
+
+ dial.startAngle = data.startAngle
+ dial.endAngle = data.endAngle
+ dial.from = data.from
+ dial.to = data.to
+ //Give a defined start in case wrap = true
+ dial.value = data.values[0]
+ dial.wrap = data.wrap
+
+ compare(dial.startAngle, data.startAngle)
+ compare(dial.endAngle, data.endAngle)
+
+ let wrappedSpy = signalSpy.createObject(dial, {target: dial, signalName: "wrapped"})
+ verify(wrappedSpy.valid)
+
+ for (let i = 0; i < data.x.length; i++) {
+ mousePress(dial, dial.width * data.x[i], dial.height * 0.5 + dial.width * ( data.y[i] - 0.5))
+ fuzzyCompare(dial.angle, data.angles[i], 3.0)
+ fuzzyCompare(dial.value, data.values[i], 0.1)
+ }
+
+ let clockwiseCount = 0
+ let counterClockwiseCount = 0
+ for (let i = 0; i < wrappedSpy.count; i++) {
+ if (wrappedSpy.signalArguments[i][0] == 0)
+ clockwiseCount++;
+ else
+ counterClockwiseCount++;
+ }
+
+ compare(clockwiseCount, data.wrapClockwise)
+ compare(counterClockwiseCount, data.wrapCounterClockwise)
+ }
+
+ function test_startEndAngleWarnings(data) {
+ let dial = createTemporaryObject(dialComponent, testCase)
+ verify(dial)
+
+ dial.startAngle = -180.
+ dial.endAngle = 180.
+
+ //provoke warning
+ ignoreWarning(new RegExp("Changing endAngle to avoid overlaps"))
+ dial.startAngle = -270.
+ dial.endAngle = 90.
+
+ compare(dial.startAngle, -270.)
+ compare(dial.endAngle, 90.)
+
+
+ dial.startAngle = -180.
+ dial.endAngle = 180.
+
+ //provoke warning
+ ignoreWarning(new RegExp("Changing startAngle to avoid overlaps"))
+ dial.endAngle = 270.
+ dial.startAngle = -90.
+
+ compare(dial.startAngle, -90.)
+ compare(dial.endAngle, 270.)
+
+ {
+ // Should not warn since we delay the setting of start and end angles to avoid
+ // binding order evaluation conflicts.
+ let dial = createTemporaryObject(dialComponent, testCase, { startAngle: -10, endAngle: 300 })
+ verify(dial)
+ compare(dial.startAngle, -10.)
+ compare(dial.endAngle, 300.)
+ }
+ }
+
+ function test_notSquareGeometry() {
+ let dial = createTemporaryObject(dialComponent, testCase)
+ verify(dial);
+ if (!dial.handle) {
+ skip("Test cannot run on styles where handle == null (macOS style)")
+ }
+ dial.from = 0
+ dial.to = 1
+ dial.live = true
+ dial.wrap = true
+ dial.startAngle = -180
+ dial.endAngle = 180
+
+ // Dial input handling always assumes that the dial is in the *center*.
+ // Instantiate a Dial with a geometries of 400x100 and then 100x400
+ // Some styles always could wrongly align the Dial background and handle in the topLeft
+ // corner. Pressing in the handle would cause the Dial to move because the dial
+ // assumes that the "Dial circle" is center aligned in its geometry.
+ for (let pass = 0; pass < 2; ++pass) {
+ if (pass === 0) {
+ dial.width = testCase.width
+ dial.height = 100
+ } else {
+ dial.width = 100
+ dial.height = testCase.height
+ }
+
+ let val = pass * 0.25
+ dial.value = val
+ // find coordinates in the middle of the handle
+ let pt2 = dial.mapFromItem(dial.handle, dial.handle.width/2, dial.handle.height/2)
+ // press the knob in the middle. It shouldn't move (except from due to rounding errors)
+ mousePress(dial, pt2.x, pt2.y)
+ fuzzyCompare(dial.value, val, 0.1)
+ }
+ }
+
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_dialog.qml b/tests/auto/quickcontrols/controls/data/tst_dialog.qml
index 76ff95a32a..8c888be98f 100644
--- a/tests/auto/quickcontrols/controls/data/tst_dialog.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_dialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
@@ -39,13 +39,12 @@ TestCase {
}
function init() {
+ failOnWarning(/.?/)
tryCompare(testCase.Window.window, "active", true)
}
function test_defaults() {
- failOnWarning(/.?/)
-
- var control = createTemporaryObject(dialog, testCase)
+ let control = createTemporaryObject(dialog, testCase)
verify(control)
verify(control.header)
verify(control.footer)
@@ -54,9 +53,9 @@ TestCase {
}
function test_accept() {
- var control = createTemporaryObject(dialog, testCase)
+ let control = createTemporaryObject(dialog, testCase)
- var openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"})
+ let openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"})
verify(openedSpy.valid)
control.open()
@@ -64,10 +63,10 @@ TestCase {
compare(openedSpy.count, 1)
verify(control.visible)
- var acceptedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "accepted"})
+ let acceptedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "accepted"})
verify(acceptedSpy.valid)
- var closedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "closed"})
+ let closedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "closed"})
verify(closedSpy.valid)
control.accept()
@@ -80,9 +79,9 @@ TestCase {
}
function test_reject() {
- var control = createTemporaryObject(dialog, testCase)
+ let control = createTemporaryObject(dialog, testCase)
- var openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"})
+ let openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"})
verify(openedSpy.valid)
control.open()
@@ -90,10 +89,10 @@ TestCase {
compare(openedSpy.count, 1)
verify(control.visible)
- var rejectedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rejected"})
+ let rejectedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rejected"})
verify(rejectedSpy.valid)
- var closedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "closed"})
+ let closedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "closed"})
verify(closedSpy.valid)
control.reject()
@@ -127,6 +126,8 @@ TestCase {
control.closePolicy = Popup.CloseOnPressOutside
control.open()
verify(control.visible)
+ // wait for enter transitions to finish
+ openedSpy.wait()
mousePress(testCase, 1, 1)
compare(rejectedSpy.count, 3)
@@ -145,6 +146,7 @@ TestCase {
control.closePolicy = Popup.CloseOnReleaseOutside
control.open()
verify(control.visible)
+ openedSpy.wait()
mousePress(testCase, 1, 1)
compare(rejectedSpy.count, 3)
@@ -165,46 +167,46 @@ TestCase {
}
function test_buttonBox(data) {
- var control = createTemporaryObject(dialog, testCase)
+ let control = createTemporaryObject(dialog, testCase)
if (data.custom)
control.footer = buttonBox.createObject(testCase)
control.standardButtons = Dialog.Ok | Dialog.Cancel
- var box = control.footer
+ let box = control.footer
verify(box)
compare(box.standardButtons, Dialog.Ok | Dialog.Cancel)
- var acceptedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "accepted"})
+ let acceptedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "accepted"})
verify(acceptedSpy.valid)
box.accepted()
compare(acceptedSpy.count, 1)
- var rejectedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rejected"})
+ let rejectedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rejected"})
verify(rejectedSpy.valid)
box.rejected()
compare(rejectedSpy.count, 1)
}
function test_qtbug71444() {
- var control = createTemporaryObject(qtbug71444, testCase)
+ let control = createTemporaryObject(qtbug71444, testCase)
verify(control)
}
function test_standardButtons() {
- var control = createTemporaryObject(dialog, testCase)
+ let control = createTemporaryObject(dialog, testCase)
control.standardButtons = Dialog.Ok
- var box = control.footer ? control.footer : control.header
+ let box = control.footer ? control.footer : control.header
verify(box)
compare(box.count, 1)
- var okButton = box.itemAt(0)
+ let okButton = box.itemAt(0)
verify(okButton)
compare(okButton.text.toUpperCase(), "OK")
control.standardButtons = Dialog.Cancel
compare(box.count, 1)
- var cancelButton = control.footer.itemAt(0)
+ let cancelButton = control.footer.itemAt(0)
verify(cancelButton)
compare(cancelButton.text.toUpperCase(), "CANCEL")
@@ -227,10 +229,10 @@ TestCase {
}
function test_layout() {
- var control = createTemporaryObject(dialog, testCase, {width: 100, height: 100})
+ let control = createTemporaryObject(dialog, testCase, {width: 100, height: 100})
verify(control)
- var openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"})
+ let openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"})
verify(openedSpy.valid)
control.open()
@@ -300,6 +302,7 @@ TestCase {
compare(control.implicitHeight, control.contentItem.implicitHeight + control.topPadding + control.bottomPadding
+ control.header.implicitHeight + control.footer.implicitHeight)
+ control.footer.implicitWidth = 0
control.header.implicitWidth = 150
compare(control.implicitWidth, control.header.implicitWidth)
@@ -320,10 +323,10 @@ TestCase {
}
function test_spacing(data) {
- var control = createTemporaryObject(dialog, testCase, {spacing: 20, width: 100, height: 100})
+ let control = createTemporaryObject(dialog, testCase, {spacing: 20, width: 100, height: 100})
verify(control)
- var openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"})
+ let openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"})
verify(openedSpy.valid)
control.open()
@@ -377,14 +380,14 @@ TestCase {
}
function test_signals(data) {
- var control = createTemporaryObject(dialog, testCase)
+ let control = createTemporaryObject(dialog, testCase)
verify(control)
control.standardButtons = data.standardButton
- var button = control.standardButton(data.standardButton)
+ let button = control.standardButton(data.standardButton)
verify(button)
- var buttonSpy = signalSpy.createObject(control.contentItem, {target: control, signalName: data.signalName})
+ let buttonSpy = signalSpy.createObject(control.contentItem, {target: control, signalName: data.signalName})
verify(buttonSpy.valid)
button.clicked()
@@ -428,7 +431,7 @@ TestCase {
if (Qt.platform.pluginName === "offscreen")
skip("QTBUG-89909")
- var window = createTemporaryObject(qtbug85884, testCase)
+ let window = createTemporaryObject(qtbug85884, testCase)
verify(window)
tryCompare(window, "focusItemActiveFocus", true)
diff --git a/tests/auto/quickcontrols/controls/data/tst_dialogbuttonbox.qml b/tests/auto/quickcontrols/controls/data/tst_dialogbuttonbox.qml
index 6eb339a192..2fa26881bc 100644
--- a/tests/auto/quickcontrols/controls/data/tst_dialogbuttonbox.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_dialogbuttonbox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -28,10 +28,12 @@ TestCase {
SignalSpy { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(buttonBox, testCase)
+ function test_defaults() {
+ let control = createTemporaryObject(buttonBox, testCase)
verify(control)
compare(control.count, 0)
verify(control.delegate)
@@ -39,19 +41,19 @@ TestCase {
}
function test_standardButtons() {
- var control = createTemporaryObject(buttonBox, testCase)
+ let control = createTemporaryObject(buttonBox, testCase)
verify(control)
compare(control.count, 0)
control.standardButtons = DialogButtonBox.Ok
compare(control.count, 1)
- var okButton = control.itemAt(0)
+ let okButton = control.itemAt(0)
verify(okButton)
compare(okButton.text.toUpperCase(), "OK")
control.standardButtons = DialogButtonBox.Cancel
compare(control.count, 1)
- var cancelButton = control.itemAt(0)
+ let cancelButton = control.itemAt(0)
verify(cancelButton)
compare(cancelButton.text.toUpperCase(), "CANCEL")
@@ -79,21 +81,21 @@ TestCase {
}
function test_attached() {
- var control = createTemporaryObject(buttonBox, testCase)
+ let control = createTemporaryObject(buttonBox, testCase)
verify(control)
control.standardButtons = DialogButtonBox.Ok
- var okButton = control.itemAt(0)
+ let okButton = control.itemAt(0)
compare(okButton.DialogButtonBox.buttonBox, control)
compare(okButton.DialogButtonBox.buttonRole, DialogButtonBox.AcceptRole)
- var saveButton = button.createObject(control, {text: "Save"})
+ let saveButton = button.createObject(control, {text: "Save"})
compare(saveButton.DialogButtonBox.buttonBox, control)
compare(saveButton.DialogButtonBox.buttonRole, DialogButtonBox.InvalidRole)
saveButton.DialogButtonBox.buttonRole = DialogButtonBox.AcceptRole
compare(saveButton.DialogButtonBox.buttonRole, DialogButtonBox.AcceptRole)
- var closeButton = createTemporaryObject(button, null, {text: "Save"})
+ let closeButton = createTemporaryObject(button, null, {text: "Save"})
compare(closeButton.DialogButtonBox.buttonBox, null)
compare(closeButton.DialogButtonBox.buttonRole, DialogButtonBox.InvalidRole)
closeButton.DialogButtonBox.buttonRole = DialogButtonBox.DestructiveRole
@@ -131,18 +133,18 @@ TestCase {
}
function test_signals(data) {
- var control = createTemporaryObject(buttonBox, testCase)
+ let control = createTemporaryObject(buttonBox, testCase)
verify(control)
control.standardButtons = data.standardButton
compare(control.count, 1)
- var button = control.itemAt(0)
+ let button = control.itemAt(0)
verify(button)
compare(button.DialogButtonBox.buttonRole, data.buttonRole)
- var clickedSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
+ let clickedSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
verify(clickedSpy.valid)
- var roleSpy = signalSpy.createObject(control, {target: control, signalName: data.signalName})
+ let roleSpy = signalSpy.createObject(control, {target: control, signalName: data.signalName})
verify(roleSpy.valid)
button.clicked()
@@ -162,16 +164,16 @@ TestCase {
}
function test_buttonLayout(data) {
- var control = createTemporaryObject(buttonBox, testCase, {buttonLayout: data.buttonLayout, standardButtons: DialogButtonBox.Ok|DialogButtonBox.Cancel})
+ let control = createTemporaryObject(buttonBox, testCase, {buttonLayout: data.buttonLayout, standardButtons: DialogButtonBox.Ok|DialogButtonBox.Cancel})
verify(control)
compare(control.count, 2)
- var button1 = control.itemAt(0)
+ let button1 = control.itemAt(0)
verify(button1)
compare(button1.DialogButtonBox.buttonRole, data.button1Role)
- var button2 = control.itemAt(1)
+ let button2 = control.itemAt(1)
verify(button2)
compare(button2.DialogButtonBox.buttonRole, data.button2Role)
}
@@ -185,16 +187,16 @@ TestCase {
// QTBUG-59719
function test_implicitSize(data) {
- var control = createTemporaryObject(buttonBox, testCase, {standardButtons: data.standardButtons})
+ let control = createTemporaryObject(buttonBox, testCase, {standardButtons: data.standardButtons})
verify(control)
- var listView = control.contentItem
+ let listView = control.contentItem
verify(listView && listView.hasOwnProperty("contentWidth"))
waitForRendering(listView)
- var implicitContentWidth = control.leftPadding + control.rightPadding
- for (var i = 0; i < listView.contentItem.children.length; ++i) {
- var button = listView.contentItem.children[i]
+ let implicitContentWidth = control.leftPadding + control.rightPadding
+ for (let i = 0; i < listView.contentItem.children.length; ++i) {
+ let button = listView.contentItem.children[i]
if (!button.hasOwnProperty("text"))
continue
implicitContentWidth += button.implicitWidth
@@ -217,14 +219,14 @@ TestCase {
}
function test_buttonSize() {
- var control = createTemporaryObject(okCancelBox, testCase)
+ let control = createTemporaryObject(okCancelBox, testCase)
verify(control)
- var okButton = control.itemAt(0)
+ let okButton = control.itemAt(0)
verify(okButton)
verify(okButton.width > 0)
- var cancelButton = control.itemAt(1)
+ let cancelButton = control.itemAt(1)
verify(cancelButton)
verify(cancelButton.width > 0)
@@ -232,14 +234,14 @@ TestCase {
}
function test_oneButtonInFixedWidthBox() {
- var control = createTemporaryObject(buttonBox, testCase,
+ let control = createTemporaryObject(buttonBox, testCase,
{ width: 400, standardButtons: Dialog.Close })
verify(control)
- var listView = control.contentItem
+ let listView = control.contentItem
waitForRendering(listView)
- var button = control.itemAt(0)
+ let button = control.itemAt(0)
verify(button)
// The button should never go outside of the box.
@@ -280,14 +282,14 @@ TestCase {
// QTBUG-73860
function test_oneButtonAlignedRightInImplicitWidthBox() {
- var dialog = createTemporaryObject(dialogComponent, testCase)
+ let dialog = createTemporaryObject(dialogComponent, testCase)
verify(dialog)
- var box = dialog.footer
- var listView = box.contentItem
+ let box = dialog.footer
+ let listView = box.contentItem
waitForRendering(listView)
- var button = box.itemAt(0)
+ let button = box.itemAt(0)
verify(button)
// The button should never go outside of the box.
@@ -353,13 +355,13 @@ TestCase {
// QTBUG-72886
function test_changeCustomButtonText(data) {
- var control = createTemporaryObject(data.component, testCase, {})
+ let control = createTemporaryObject(data.component, testCase, {})
verify(control)
- var listView = control.contentItem
+ let listView = control.contentItem
waitForRendering(listView)
- var button = control.okButton
+ let button = control.okButton
verify(button)
button.text = "some longer text";
@@ -519,9 +521,9 @@ TestCase {
}
function test_contentItemDeletionOrder() {
- var control1 = createTemporaryObject(contentItemDeletionOrder1, testCase)
+ let control1 = createTemporaryObject(contentItemDeletionOrder1, testCase)
verify(control1)
- var control2 = createTemporaryObject(contentItemDeletionOrder2, testCase)
+ let control2 = createTemporaryObject(contentItemDeletionOrder2, testCase)
verify(control2)
}
@@ -560,9 +562,9 @@ TestCase {
}
function test_backgroundDeletionOrder() {
- var control1 = createTemporaryObject(backgroundDeletionOrder1, testCase)
+ let control1 = createTemporaryObject(backgroundDeletionOrder1, testCase)
verify(control1)
- var control2 = createTemporaryObject(backgroundDeletionOrder2, testCase)
+ let control2 = createTemporaryObject(backgroundDeletionOrder2, testCase)
verify(control2)
}
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_frame.qml b/tests/auto/quickcontrols/controls/data/tst_frame.qml
index bef46f7650..141940edc3 100644
--- a/tests/auto/quickcontrols/controls/data/tst_frame.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_frame.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -52,10 +52,12 @@ TestCase {
}
}
- function test_empty() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(frame, testCase)
+ function test_empty() {
+ let control = createTemporaryObject(frame, testCase)
verify(control)
verify(control.contentItem)
@@ -66,7 +68,7 @@ TestCase {
}
function test_oneChild() {
- var control = createTemporaryObject(oneChildFrame, testCase)
+ let control = createTemporaryObject(oneChildFrame, testCase)
verify(control)
compare(control.contentWidth, 100)
@@ -78,7 +80,7 @@ TestCase {
}
function test_twoChildren() {
- var control = createTemporaryObject(twoChildrenFrame, testCase)
+ let control = createTemporaryObject(twoChildrenFrame, testCase)
verify(control)
compare(control.contentWidth, 0)
@@ -90,7 +92,7 @@ TestCase {
}
function test_contentItem() {
- var control = createTemporaryObject(contentFrame, testCase)
+ let control = createTemporaryObject(contentFrame, testCase)
verify(control)
compare(control.contentWidth, 100)
diff --git a/tests/auto/quickcontrols/controls/data/tst_groupbox.qml b/tests/auto/quickcontrols/controls/data/tst_groupbox.qml
index b5867dd956..501870e1bc 100644
--- a/tests/auto/quickcontrols/controls/data/tst_groupbox.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_groupbox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -52,10 +52,12 @@ TestCase {
}
}
- function test_empty() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(groupBox, testCase)
+ function test_empty() {
+ let control = createTemporaryObject(groupBox, testCase)
verify(control)
verify(control.contentItem)
@@ -66,7 +68,7 @@ TestCase {
}
function test_oneChild() {
- var control = createTemporaryObject(oneChildBox, testCase)
+ let control = createTemporaryObject(oneChildBox, testCase)
verify(control)
compare(control.contentWidth, 100)
@@ -78,7 +80,7 @@ TestCase {
}
function test_twoChildren() {
- var control = createTemporaryObject(twoChildrenBox, testCase)
+ let control = createTemporaryObject(twoChildrenBox, testCase)
verify(control)
compare(control.contentWidth, 0)
@@ -90,7 +92,7 @@ TestCase {
}
function test_contentItem() {
- var control = createTemporaryObject(contentBox, testCase)
+ let control = createTemporaryObject(contentBox, testCase)
verify(control)
compare(control.contentWidth, 100)
diff --git a/tests/auto/quickcontrols/controls/data/tst_itemdelegate.qml b/tests/auto/quickcontrols/controls/data/tst_itemdelegate.qml
index 9d4847b4b1..db78299c25 100644
--- a/tests/auto/quickcontrols/controls/data/tst_itemdelegate.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_itemdelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -18,21 +18,23 @@ TestCase {
ItemDelegate { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(itemDelegate, testCase)
verify(control)
}
function test_baseline() {
- var control = createTemporaryObject(itemDelegate, testCase)
+ let control = createTemporaryObject(itemDelegate, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
}
function test_highlighted() {
- var control = createTemporaryObject(itemDelegate, testCase)
+ let control = createTemporaryObject(itemDelegate, testCase)
verify(control)
verify(!control.highlighted)
@@ -41,11 +43,11 @@ TestCase {
}
function test_spacing() {
- var control = createTemporaryObject(itemDelegate, testCase, { text: "Some long, long, long text" })
+ let control = createTemporaryObject(itemDelegate, testCase, { text: "Some long, long, long text" })
verify(control)
verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth)
- var textLabel = findChild(control.contentItem, "label")
+ let textLabel = findChild(control.contentItem, "label")
verify(textLabel)
// The implicitWidth of the IconLabel that all buttons use as their contentItem
@@ -74,7 +76,7 @@ TestCase {
}
function test_display(data) {
- var control = createTemporaryObject(itemDelegate, testCase, {
+ let control = createTemporaryObject(itemDelegate, testCase, {
text: "ItemDelegate",
display: data.display,
width: 400,
@@ -84,8 +86,8 @@ TestCase {
verify(control)
compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png")
- var iconImage = findChild(control.contentItem, "image")
- var textLabel = findChild(control.contentItem, "label")
+ let iconImage = findChild(control.contentItem, "image")
+ let textLabel = findChild(control.contentItem, "label")
switch (control.display) {
case ItemDelegate.IconOnly:
diff --git a/tests/auto/quickcontrols/controls/data/tst_label.qml b/tests/auto/quickcontrols/controls/data/tst_label.qml
index 853d5ba686..2477ce338d 100644
--- a/tests/auto/quickcontrols/controls/data/tst_label.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_label.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -35,10 +35,12 @@ TestCase {
SignalSpy { }
}
- function test_creation() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(label, testCase)
+ function test_creation() {
+ let control = createTemporaryObject(label, testCase)
verify(control)
}
@@ -46,7 +48,7 @@ TestCase {
return [
{tag: "bold", value: true},
{tag: "capitalization", value: Font.Capitalize},
- {tag: "family", value: "Courier"},
+ {tag: "family", value: "Tahoma"},
{tag: "italic", value: true},
{tag: "strikeout", value: true},
{tag: "underline", value: true},
@@ -56,19 +58,19 @@ TestCase {
}
function test_font_explicit_attributes(data) {
- var control = createTemporaryObject(label, testCase)
+ let control = createTemporaryObject(label, testCase)
verify(control)
- var child = label.createObject(control)
+ let child = label.createObject(control)
verify(child)
- var controlSpy = signalSpy.createObject(control, {target: control, signalName: "fontChanged"})
+ let controlSpy = signalSpy.createObject(control, {target: control, signalName: "fontChanged"})
verify(controlSpy.valid)
- var childSpy = signalSpy.createObject(child, {target: child, signalName: "fontChanged"})
+ let childSpy = signalSpy.createObject(child, {target: child, signalName: "fontChanged"})
verify(childSpy.valid)
- var defaultValue = control.font[data.tag]
+ let defaultValue = control.font[data.tag]
child.font[data.tag] = defaultValue
compare(child.font[data.tag], defaultValue)
@@ -84,7 +86,7 @@ TestCase {
}
function test_background() {
- var control = createTemporaryObject(backgroundLabel, testCase, {text: "Label"})
+ let control = createTemporaryObject(backgroundLabel, testCase, {text: "Label"})
verify(control)
compare(control.background.width, control.width)
@@ -102,25 +104,25 @@ TestCase {
}
function test_inset() {
- var control = createTemporaryObject(label, testCase, {background: rectangle.createObject(control)})
+ let control = createTemporaryObject(label, testCase, {background: rectangle.createObject(testCase)})
verify(control)
- var topInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topInsetChanged"})
+ let topInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topInsetChanged"})
verify(topInsetSpy.valid)
- var leftInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftInsetChanged"})
+ let leftInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftInsetChanged"})
verify(leftInsetSpy.valid)
- var rightInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightInsetChanged"})
+ let rightInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightInsetChanged"})
verify(rightInsetSpy.valid)
- var bottomInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomInsetChanged"})
+ let bottomInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomInsetChanged"})
verify(bottomInsetSpy.valid)
- var topInsetChanges = 0
- var leftInsetChanges = 0
- var rightInsetChanges = 0
- var bottomInsetChanges = 0
+ let topInsetChanges = 0
+ let leftInsetChanges = 0
+ let rightInsetChanges = 0
+ let bottomInsetChanges = 0
compare(control.topInset, 0)
compare(control.leftInset, 0)
diff --git a/tests/auto/quickcontrols/controls/data/tst_menuitem.qml b/tests/auto/quickcontrols/controls/data/tst_menuitem.qml
index d1ed076705..35335ec88d 100644
--- a/tests/auto/quickcontrols/controls/data/tst_menuitem.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_menuitem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -23,21 +23,23 @@ TestCase {
Menu { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(menuItem, testCase)
verify(control)
}
function test_baseline() {
- var control = createTemporaryObject(menuItem, testCase)
+ let control = createTemporaryObject(menuItem, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
}
function test_checkable() {
- var control = createTemporaryObject(menuItem, testCase)
+ let control = createTemporaryObject(menuItem, testCase)
verify(control)
verify(control.hasOwnProperty("checkable"))
verify(!control.checkable)
@@ -54,7 +56,7 @@ TestCase {
}
function test_highlighted() {
- var control = createTemporaryObject(menuItem, testCase)
+ let control = createTemporaryObject(menuItem, testCase)
verify(control)
verify(!control.highlighted)
@@ -76,7 +78,7 @@ TestCase {
}
function test_display(data) {
- var control = createTemporaryObject(menuItem, testCase, {
+ let control = createTemporaryObject(menuItem, testCase, {
text: "MenuItem",
display: data.display,
"icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png",
@@ -85,9 +87,9 @@ TestCase {
verify(control)
compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png")
- var padding = data.mirrored ? control.contentItem.rightPadding : control.contentItem.leftPadding
- var iconImage = findChild(control.contentItem, "image")
- var textLabel = findChild(control.contentItem, "label")
+ let padding = data.mirrored ? control.contentItem.rightPadding : control.contentItem.leftPadding
+ let iconImage = findChild(control.contentItem, "image")
+ let textLabel = findChild(control.contentItem, "label")
switch (control.display) {
case MenuItem.IconOnly:
@@ -123,14 +125,14 @@ TestCase {
}
function test_menu() {
- var control = createTemporaryObject(menu, testCase)
+ let control = createTemporaryObject(menu, testCase)
verify(control)
- var item1 = createTemporaryObject(menuItem, testCase)
+ let item1 = createTemporaryObject(menuItem, testCase)
verify(item1)
compare(item1.menu, null)
- var item2 = createTemporaryObject(menuItem, testCase)
+ let item2 = createTemporaryObject(menuItem, testCase)
verify(item2)
compare(item2.menu, null)
diff --git a/tests/auto/quickcontrols/controls/data/tst_monthgrid.qml b/tests/auto/quickcontrols/controls/data/tst_monthgrid.qml
index 5b1081675e..d0d66442c0 100644
--- a/tests/auto/quickcontrols/controls/data/tst_monthgrid.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_monthgrid.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
@@ -37,15 +37,17 @@ TestCase {
SignalSpy { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(defaultGrid, testCase)
verify(control)
}
function test_locale() {
- var control = delegateGrid.createObject(testCase, {month: 0, year: 2013})
+ let control = delegateGrid.createObject(testCase, {month: 0, year: 2013})
compare(control.contentItem.children.length, 6 * 7 + 1)
@@ -58,15 +60,15 @@ TestCase {
compare(control.locale.name, "en_GB")
// M T W T F S S
- var en_GB = ["2012-12-31", "2013-01-01", "2013-01-02", "2013-01-03", "2013-01-04", "2013-01-05", "2013-01-06",
+ let en_GB = ["2012-12-31", "2013-01-01", "2013-01-02", "2013-01-03", "2013-01-04", "2013-01-05", "2013-01-06",
"2013-01-07", "2013-01-08", "2013-01-09", "2013-01-10", "2013-01-11", "2013-01-12", "2013-01-13",
"2013-01-14", "2013-01-15", "2013-01-16", "2013-01-17", "2013-01-18", "2013-01-19", "2013-01-20",
"2013-01-21", "2013-01-22", "2013-01-23", "2013-01-24", "2013-01-25", "2013-01-26", "2013-01-27",
"2013-01-28", "2013-01-29", "2013-01-30", "2013-01-31", "2013-02-01", "2013-02-02", "2013-02-03",
"2013-02-04", "2013-02-05", "2013-02-06", "2013-02-07", "2013-02-08", "2013-02-09", "2013-02-10"]
- for (var i = 0; i < 42; ++i) {
- var cellDate = new Date(en_GB[i])
+ for (let i = 0; i < 42; ++i) {
+ let cellDate = new Date(en_GB[i])
compare(control.contentItem.children[i].date.getFullYear(), cellDate.getUTCFullYear())
compare(control.contentItem.children[i].date.getMonth(), cellDate.getUTCMonth())
compare(control.contentItem.children[i].date.getDate(), cellDate.getUTCDate())
@@ -81,15 +83,15 @@ TestCase {
compare(control.locale.name, "en_US")
// S M T W T F S
- var en_US = ["2012-12-30", "2012-12-31", "2013-01-01", "2013-01-02", "2013-01-03", "2013-01-04", "2013-01-05",
+ let en_US = ["2012-12-30", "2012-12-31", "2013-01-01", "2013-01-02", "2013-01-03", "2013-01-04", "2013-01-05",
"2013-01-06", "2013-01-07", "2013-01-08", "2013-01-09", "2013-01-10", "2013-01-11", "2013-01-12",
"2013-01-13", "2013-01-14", "2013-01-15", "2013-01-16", "2013-01-17", "2013-01-18", "2013-01-19",
"2013-01-20", "2013-01-21", "2013-01-22", "2013-01-23", "2013-01-24", "2013-01-25", "2013-01-26",
"2013-01-27", "2013-01-28", "2013-01-29", "2013-01-30", "2013-01-31", "2013-02-01", "2013-02-02",
"2013-02-03", "2013-02-04", "2013-02-05", "2013-02-06", "2013-02-07", "2013-02-08", "2013-02-09"]
- for (var j = 0; j < 42; ++j) {
- cellDate = new Date(en_US[j])
+ for (let j = 0; j < 42; ++j) {
+ let cellDate = new Date(en_US[j])
compare(control.contentItem.children[j].date.getFullYear(), cellDate.getUTCFullYear())
compare(control.contentItem.children[j].date.getMonth(), cellDate.getUTCMonth())
compare(control.contentItem.children[j].date.getDate(), cellDate.getUTCDate())
@@ -103,7 +105,7 @@ TestCase {
}
function test_range() {
- var control = defaultGrid.createObject(testCase)
+ let control = defaultGrid.createObject(testCase)
control.month = 0
compare(control.month, 0)
@@ -138,7 +140,7 @@ TestCase {
}
function test_bce() {
- var control = defaultGrid.createObject(testCase)
+ let control = defaultGrid.createObject(testCase)
compare(control.contentItem.children.length, 6 * 7 + 1)
@@ -153,14 +155,14 @@ TestCase {
compare(control.year, -1)
// M T W T F S S
- var jan1bce = [27, 28, 29, 30, 31, 1, 2,
+ let jan1bce = [27, 28, 29, 30, 31, 1, 2,
3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30,
31, 1, 2, 3, 4, 5, 6]
- for (var i = 0; i < 42; ++i)
+ for (let i = 0; i < 42; ++i)
compare(control.contentItem.children[i].text, jan1bce[i].toString())
// February 1 BCE
@@ -170,21 +172,21 @@ TestCase {
compare(control.year, -1)
// M T W T F S S
- var feb1bce = [31, 1, 2, 3, 4, 5, 6,
+ let feb1bce = [31, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27,
28, 29, 1, 2, 3, 4, 5,
6, 7, 8, 9, 10, 11, 12]
- for (var j = 0; j < 42; ++j)
+ for (let j = 0; j < 42; ++j)
compare(control.contentItem.children[j].text, feb1bce[j].toString())
control.destroy()
}
function test_font() {
- var control = defaultGrid.createObject(testCase)
+ let control = defaultGrid.createObject(testCase)
verify(control.contentItem.children[0])
@@ -202,24 +204,24 @@ TestCase {
}
function test_clicked(data) {
- var control = createTemporaryObject(defaultGrid, testCase)
+ let control = createTemporaryObject(defaultGrid, testCase)
verify(control)
compare(control.contentItem.children.length, 6 * 7 + 1)
- var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressed"})
+ let pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressed"})
verify(pressedSpy.valid)
- var releasedSpy = signalSpy.createObject(control, {target: control, signalName: "released"})
+ let releasedSpy = signalSpy.createObject(control, {target: control, signalName: "released"})
verify(releasedSpy.valid)
- var clickedSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
+ let clickedSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
verify(clickedSpy.valid)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
- for (var i = 0; i < 42; ++i) {
- var cell = control.contentItem.children[i]
+ for (let i = 0; i < 42; ++i) {
+ let cell = control.contentItem.children[i]
verify(cell)
if (data.touch)
diff --git a/tests/auto/quickcontrols/controls/data/tst_page.qml b/tests/auto/quickcontrols/controls/data/tst_page.qml
index ca816d963b..2396b30dff 100644
--- a/tests/auto/quickcontrols/controls/data/tst_page.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_page.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -69,10 +69,12 @@ TestCase {
ToolBar { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(page, testCase)
+ function test_defaults() {
+ let control = createTemporaryObject(page, testCase)
verify(control)
verify(control.contentItem)
@@ -81,9 +83,7 @@ TestCase {
}
function test_empty() {
- failOnWarning(/.?/)
-
- var control = createTemporaryObject(page, testCase)
+ let control = createTemporaryObject(page, testCase)
verify(control)
verify(control.contentItem)
@@ -94,7 +94,7 @@ TestCase {
}
function test_oneChild() {
- var control = createTemporaryObject(oneChildPage, testCase)
+ let control = createTemporaryObject(oneChildPage, testCase)
verify(control)
compare(control.contentWidth, 100)
@@ -106,7 +106,7 @@ TestCase {
}
function test_twoChildren() {
- var control = createTemporaryObject(twoChildrenPage, testCase)
+ let control = createTemporaryObject(twoChildrenPage, testCase)
verify(control)
compare(control.contentWidth, 0)
@@ -120,7 +120,7 @@ TestCase {
}
function test_contentItem() {
- var control = createTemporaryObject(contentPage, testCase)
+ let control = createTemporaryObject(contentPage, testCase)
verify(control)
compare(control.contentWidth, 100)
@@ -132,7 +132,7 @@ TestCase {
}
function test_layout() {
- var control = createTemporaryObject(page, testCase, {width: 100, height: 100})
+ let control = createTemporaryObject(page, testCase, {width: 100, height: 100})
verify(control)
compare(control.width, 100)
@@ -220,7 +220,7 @@ TestCase {
}
function test_spacing(data) {
- var control = createTemporaryObject(page, testCase, {spacing: 20, width: 100, height: 100})
+ let control = createTemporaryObject(page, testCase, {spacing: 20, width: 100, height: 100})
verify(control)
control.contentItem.visible = data.content
@@ -246,7 +246,7 @@ TestCase {
}
function test_headerFooter() {
- var control = createTemporaryObject(headerFooterPage, testCase, {width: 100, height: 100})
+ let control = createTemporaryObject(headerFooterPage, testCase, {width: 100, height: 100})
verify(control)
compare(control.width, 100)
@@ -268,5 +268,18 @@ TestCase {
compare(control.contentItem.y, control.header.height)
compare(control.contentItem.width, control.width)
compare(control.contentItem.height, control.height - control.header.height - control.footer.height)
+
+ // swap places and make sure geometry is updated correctly
+ const oldHeader = control.header
+ const oldFooter = control.footer
+ // reset both first, so one item does not end up in two places at once
+ control.header = null
+ control.footer = null
+ control.header = oldFooter
+ control.footer = oldHeader
+ verify(control.header.visible)
+ verify(control.footer.visible)
+ compare(control.header.y, 0)
+ compare(control.footer.y, control.height - control.footer.height)
}
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_pageindicator.qml b/tests/auto/quickcontrols/controls/data/tst_pageindicator.qml
index 837972cdc2..391eb91248 100644
--- a/tests/auto/quickcontrols/controls/data/tst_pageindicator.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_pageindicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -15,23 +15,30 @@ TestCase {
Component {
id: pageIndicator
- PageIndicator { }
+ PageIndicator {
+ objectName: "pageIndicator"
+ contentItem.objectName: "pageIndicatorContentItem"
+ }
}
Component {
id: mouseArea
- MouseArea { }
+ MouseArea {
+ objectName: "mouseArea"
+ }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(pageIndicator, testCase)
verify(control)
}
function test_count() {
- var control = createTemporaryObject(pageIndicator, testCase)
+ let control = createTemporaryObject(pageIndicator, testCase)
verify(control)
compare(control.count, 0)
@@ -40,7 +47,7 @@ TestCase {
}
function test_currentIndex() {
- var control = createTemporaryObject(pageIndicator, testCase)
+ let control = createTemporaryObject(pageIndicator, testCase)
verify(control)
compare(control.currentIndex, 0)
@@ -56,13 +63,13 @@ TestCase {
}
function test_interactive(data) {
- var control = createTemporaryObject(pageIndicator, testCase, {count: 5, spacing: 10, topPadding: 10, leftPadding: 10, rightPadding: 10, bottomPadding: 10})
+ let control = createTemporaryObject(pageIndicator, testCase, {count: 5, spacing: 10, topPadding: 10, leftPadding: 10, rightPadding: 10, bottomPadding: 10})
verify(control)
verify(!control.interactive)
compare(control.currentIndex, 0)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
if (data.touch)
touch.press(0, control).commit().release(0, control).commit()
@@ -80,10 +87,10 @@ TestCase {
compare(control.currentIndex, 2)
// test also clicking outside delegates => the nearest should be selected
- for (var i = 0; i < control.count; ++i) {
- var child = control.contentItem.children[i]
+ for (let i = 0; i < control.count; ++i) {
+ let child = control.contentItem.children[i]
- var points = [
+ let points = [
Qt.point(child.width / 2, -2), // top
Qt.point(-2, child.height / 2), // left
Qt.point(child.width + 2, child.height / 2), // right
@@ -95,12 +102,12 @@ TestCase {
Qt.point(child.width + 2, child.height + 2), // bottom-right
]
- for (var j = 0; j < points.length; ++j) {
+ for (let j = 0; j < points.length; ++j) {
control.currentIndex = -1
compare(control.currentIndex, -1)
- var point = points[j]
- var pos = control.mapFromItem(child, x, y)
+ let point = points[j]
+ let pos = control.mapFromItem(child, x, y)
if (data.touch)
touch.press(0, control, pos.x, pos.y).commit().release(0, control, pos.x, pos.y).commit()
else
@@ -119,10 +126,10 @@ TestCase {
// QTBUG-61785
function test_mouseArea(data) {
- var ma = createTemporaryObject(mouseArea, testCase, {width: testCase.width, height: testCase.height})
+ let ma = createTemporaryObject(mouseArea, testCase, {width: testCase.width, height: testCase.height})
verify(ma)
- var control = pageIndicator.createObject(ma, {count: 5, interactive: data.interactive, width: testCase.width, height: testCase.height})
+ let control = pageIndicator.createObject(ma, {count: 5, interactive: data.interactive, width: testCase.width, height: testCase.height})
verify(control)
compare(control.interactive, data.interactive)
@@ -133,7 +140,7 @@ TestCase {
mouseRelease(control)
verify(!ma.pressed)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
touch.press(0, control).commit()
compare(ma.pressed, !data.interactive)
diff --git a/tests/auto/quickcontrols/controls/data/tst_pane.qml b/tests/auto/quickcontrols/controls/data/tst_pane.qml
index f823031c79..ab042edec2 100644
--- a/tests/auto/quickcontrols/controls/data/tst_pane.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_pane.qml
@@ -1,9 +1,10 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
import QtQuick.Controls
+import QtQuick.Layouts
TestCase {
id: testCase
@@ -18,57 +19,22 @@ TestCase {
Pane { }
}
- Component {
- id: oneChildPane
- Pane {
- Item {
- implicitWidth: 100
- implicitHeight: 30
- }
- }
- }
-
- Component {
- id: twoChildrenPane
- Pane {
- Item {
- implicitWidth: 100
- implicitHeight: 30
- }
- Item {
- implicitWidth: 200
- implicitHeight: 60
- }
- }
+ function init() {
+ failOnWarning(/.?/)
}
- Component {
- id: contentPane
- Pane {
- contentItem: Item {
- implicitWidth: 100
- implicitHeight: 30
- }
- }
- }
+ function test_implicitContentItem() {
+ let control = createTemporaryObject(pane, testCase, {width: 100, height: 100})
+ verify(control)
- Component {
- id: pressPane
- MouseArea {
- width: 200
- height: 200
- property int pressCount
- onPressed: ++pressCount
- Pane {
- anchors.fill: parent
- }
- }
+ compare(control.width, 100)
+ compare(control.height, 100)
+ compare(control.contentItem.width, control.availableWidth)
+ compare(control.contentItem.height, control.availableHeight)
}
function test_empty() {
- failOnWarning(/.?/)
-
- var control = createTemporaryObject(pane, testCase)
+ let control = createTemporaryObject(pane, testCase)
verify(control)
verify(control.contentItem)
@@ -78,8 +44,18 @@ TestCase {
compare(control.implicitContentHeight, 0)
}
+ Component {
+ id: oneChildPane
+ Pane {
+ Item {
+ implicitWidth: 100
+ implicitHeight: 30
+ }
+ }
+ }
+
function test_oneChild() {
- var control = createTemporaryObject(oneChildPane, testCase)
+ let control = createTemporaryObject(oneChildPane, testCase)
verify(control)
compare(control.contentWidth, 100)
@@ -101,8 +77,22 @@ TestCase {
verify(control.implicitHeight > 40)
}
+ Component {
+ id: twoChildrenPane
+ Pane {
+ Item {
+ implicitWidth: 100
+ implicitHeight: 30
+ }
+ Item {
+ implicitWidth: 200
+ implicitHeight: 60
+ }
+ }
+ }
+
function test_twoChildren() {
- var control = createTemporaryObject(twoChildrenPane, testCase)
+ let control = createTemporaryObject(twoChildrenPane, testCase)
verify(control)
compare(control.contentWidth, 0)
@@ -113,8 +103,18 @@ TestCase {
verify(control.implicitHeight > 0)
}
+ Component {
+ id: contentPane
+ Pane {
+ contentItem: Item {
+ implicitWidth: 100
+ implicitHeight: 30
+ }
+ }
+ }
+
function test_contentItem() {
- var control = createTemporaryObject(contentPane, testCase)
+ let control = createTemporaryObject(contentPane, testCase)
verify(control)
compare(control.contentWidth, 100)
@@ -125,18 +125,47 @@ TestCase {
verify(control.implicitHeight > 30)
}
- function test_implicitContentItem() {
- var control = createTemporaryObject(pane, testCase, {width: 100, height: 100})
+ Component {
+ id: contentItemPane
+ Pane {
+ property string description: ""
+ contentItem: ColumnLayout {
+ Label {
+ Layout.maximumWidth: 100
+ text: description
+ elide: Label.ElideRight
+ }
+ }
+ Component.onCompleted: {
+ description = "Binding loop issue ".repeat(100)
+ }
+ }
+ }
+
+ function test_paneBindingLoop() {
+ let control = createTemporaryObject(contentItemPane, testCase)
verify(control)
+ // Wait for content item to be polished
+ waitForPolish(control.contentItem)
- compare(control.width, 100)
- compare(control.height, 100)
- compare(control.contentItem.width, control.availableWidth)
- compare(control.contentItem.height, control.availableHeight)
+ compare(control.contentWidth, 100)
+ }
+
+ Component {
+ id: pressPane
+ MouseArea {
+ width: 200
+ height: 200
+ property int pressCount
+ onPressed: ++pressCount
+ Pane {
+ anchors.fill: parent
+ }
+ }
}
function test_press() {
- var control = createTemporaryObject(pressPane, testCase)
+ let control = createTemporaryObject(pressPane, testCase)
verify(control)
compare(control.pressCount, 0)
diff --git a/tests/auto/quickcontrols/controls/data/tst_popup.qml b/tests/auto/quickcontrols/controls/data/tst_popup.qml
index 23879d817a..2428192961 100644
--- a/tests/auto/quickcontrols/controls/data/tst_popup.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_popup.qml
@@ -1,9 +1,10 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
import QtQuick.Controls
+import QtQuick.Layouts
import QtQuick.Templates as T
import QtQuick.NativeStyle as NativeStyle
import Qt.test.controls
@@ -42,37 +43,39 @@ TestCase {
SignalSpy { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(popupControl, testCase)
verify(control)
}
function test_padding() {
- var control = createTemporaryObject(popupTemplate, testCase)
+ let control = createTemporaryObject(popupTemplate, testCase)
verify(control)
- var paddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "paddingChanged"})
+ let paddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "paddingChanged"})
verify(paddingSpy.valid)
- var topPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topPaddingChanged"})
+ let topPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topPaddingChanged"})
verify(topPaddingSpy.valid)
- var leftPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftPaddingChanged"})
+ let leftPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftPaddingChanged"})
verify(leftPaddingSpy.valid)
- var rightPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightPaddingChanged"})
+ let rightPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightPaddingChanged"})
verify(rightPaddingSpy.valid)
- var bottomPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomPaddingChanged"})
+ let bottomPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomPaddingChanged"})
verify(bottomPaddingSpy.valid)
- var paddingChanges = 0
- var topPaddingChanges = 0
- var leftPaddingChanges = 0
- var rightPaddingChanges = 0
- var bottomPaddingChanges = 0
+ let paddingChanges = 0
+ let topPaddingChanges = 0
+ let leftPaddingChanges = 0
+ let rightPaddingChanges = 0
+ let bottomPaddingChanges = 0
compare(control.padding, 0)
compare(control.topPadding, 0)
@@ -159,17 +162,17 @@ TestCase {
}
function test_availableSize() {
- var control = createTemporaryObject(popupTemplate, testCase)
+ let control = createTemporaryObject(popupTemplate, testCase)
verify(control)
- var availableWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "availableWidthChanged"})
+ let availableWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "availableWidthChanged"})
verify(availableWidthSpy.valid)
- var availableHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "availableHeightChanged"})
+ let availableHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "availableHeightChanged"})
verify(availableHeightSpy.valid)
- var availableWidthChanges = 0
- var availableHeightChanges = 0
+ let availableWidthChanges = 0
+ let availableHeightChanges = 0
control.width = 100
compare(control.availableWidth, 100)
@@ -229,14 +232,14 @@ TestCase {
}
function test_position() {
- var control = createTemporaryObject(popupControl, testCase, {visible: true, leftMargin: 10, topMargin: 20, width: 100, height: 100})
+ let control = createTemporaryObject(popupControl, testCase, {visible: true, leftMargin: 10, topMargin: 20, width: 100, height: 100})
verify(control)
verify(control.visible)
- var xSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "xChanged"})
+ let xSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "xChanged"})
verify(xSpy.valid)
- var ySpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "yChanged"})
+ let ySpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "yChanged"})
verify(ySpy.valid)
// moving outside margins does not trigger change notifiers
@@ -285,7 +288,7 @@ TestCase {
}
function test_resetSize() {
- var control = createTemporaryObject(popupControl, testCase, {visible: true, margins: 0})
+ let control = createTemporaryObject(popupControl, testCase, {visible: true, margins: 0})
verify(control)
control.scale = 1.0
@@ -302,7 +305,7 @@ TestCase {
}
function test_negativeMargins() {
- var control = createTemporaryObject(popupControl, testCase, {implicitWidth: testCase.width, implicitHeight: testCase.height})
+ let control = createTemporaryObject(popupControl, testCase, {implicitWidth: testCase.width, implicitHeight: testCase.height})
verify(control)
control.open()
@@ -319,12 +322,12 @@ TestCase {
control.x = -10
control.y = -10
- compare(control.x, 0)
- compare(control.y, 0)
+ compare(control.x, -10)
+ compare(control.y, -10)
}
function test_margins() {
- var control = createTemporaryObject(popupTemplate, testCase, {width: 100, height: 100})
+ let control = createTemporaryObject(popupTemplate, testCase, {width: 100, height: 100})
verify(control)
control.open()
@@ -410,7 +413,7 @@ TestCase {
}
function test_background() {
- var control = createTemporaryObject(popupTemplate, testCase)
+ let control = createTemporaryObject(popupTemplate, testCase)
verify(control)
control.background = rect.createObject(testCase)
@@ -455,8 +458,8 @@ TestCase {
}
function getChild(control, objname, idx) {
- var index = idx
- for (var i = index+1; i < control.children.length; i++)
+ let index = idx
+ for (let i = index+1; i < control.children.length; i++)
{
if (control.children[i].objectName === objname) {
index = i
@@ -525,15 +528,15 @@ TestCase {
}
function test_font() { // QTBUG_50984, QTBUG-51696
- var window = createTemporaryObject(component, testCase)
+ let window = createTemporaryObject(component, testCase)
verify(window)
compare(window.font.pixelSize, 40)
compare(window.pane.font.pixelSize, 30)
compare(window.pane.button.font.pixelSize, 20)
compare(window.popup.font.pixelSize, 40)
- var idx1 = getChild(window.popup.listview.contentItem, "delegate", -1)
- var idx2 = getChild(window.popup.listview.contentItem, "delegate", idx1)
+ let idx1 = getChild(window.popup.listview.contentItem, "delegate", -1)
+ let idx2 = getChild(window.popup.listview.contentItem, "delegate", idx1)
window.popup.listview.contentItem.children[idx1].fontspy.clear()
window.popup.listview.contentItem.children[idx2].fontspy.clear()
window.popup.button.fontspy.clear()
@@ -649,7 +652,7 @@ TestCase {
function test_locale() { // QTBUG_50984
// test looking up natural locale from ancestors
- var control = createTemporaryObject(localeComponent, applicationWindow.contentItem)
+ let control = createTemporaryObject(localeComponent, applicationWindow.contentItem)
verify(control)
compare(control.locale.name, "en_US")
@@ -732,10 +735,10 @@ TestCase {
function test_locale_changes() { // QTBUG_50984
// test default locale and locale inheritance
- var control = createTemporaryObject(localeChangeComponent, applicationWindow.contentItem)
+ let control = createTemporaryObject(localeChangeComponent, applicationWindow.contentItem)
verify(control)
- var defaultLocale = Qt.locale()
+ let defaultLocale = Qt.locale()
compare(control.ApplicationWindow.window.locale.name, defaultLocale.name)
compare(control.locale.name, defaultLocale.name)
compare(control.button.locale.name, defaultLocale.name)
@@ -901,10 +904,10 @@ TestCase {
}
function test_size() {
- var control = createTemporaryObject(popupControl, testCase)
+ let control = createTemporaryObject(popupControl, testCase)
verify(control)
- var openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"})
+ let openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"})
verify(openedSpy.valid)
control.open()
@@ -962,7 +965,7 @@ TestCase {
}
function test_visible() {
- var control = createTemporaryObject(popupTemplate, testCase, {visible: true})
+ let control = createTemporaryObject(popupTemplate, testCase, {visible: true})
verify(control)
// QTBUG-51989
@@ -1020,7 +1023,7 @@ TestCase {
}
function indexOf(array, item) {
- for (var idx = 0; idx < array.length; ++idx) {
+ for (let idx = 0; idx < array.length; ++idx) {
if (item === array[idx])
return idx;
}
@@ -1028,13 +1031,13 @@ TestCase {
}
function findOverlay(window, popup) {
- var item = popup.contentItem.parent
- var idx = indexOf(window.Overlay.overlay.children, item)
+ let item = popup.contentItem.parent
+ let idx = indexOf(window.Overlay.overlay.children, item)
return window.Overlay.overlay.children[idx - 1]
}
function test_overlay() {
- var window = createTemporaryObject(overlayTest, testCase)
+ let window = createTemporaryObject(overlayTest, testCase)
verify(window)
window.requestActivate()
@@ -1042,7 +1045,7 @@ TestCase {
compare(window.Overlay.overlay.children.length, 0)
- var firstOverlay = findOverlay(window, window.firstDrawer)
+ let firstOverlay = findOverlay(window, window.firstDrawer)
verify(!firstOverlay)
window.firstDrawer.open()
compare(window.Overlay.overlay.children.length, 2) // 1 drawer + 1 overlay
@@ -1053,7 +1056,7 @@ TestCase {
indexOf(window.Overlay.overlay.children, window.firstDrawer.contentItem.parent) - 1)
tryCompare(firstOverlay, "opacity", 1.0)
- var secondOverlay = findOverlay(window, window.secondDrawer)
+ let secondOverlay = findOverlay(window, window.secondDrawer)
verify(!secondOverlay)
window.secondDrawer.open()
compare(window.Overlay.overlay.children.length, 4) // 2 drawers + 2 overlays
@@ -1076,7 +1079,7 @@ TestCase {
verify(!secondOverlay)
compare(window.Overlay.overlay.children.length, 0)
- var modalOverlay = findOverlay(window, window.modalPopup)
+ let modalOverlay = findOverlay(window, window.modalPopup)
verify(!modalOverlay)
window.modalPopup.open()
modalOverlay = findOverlay(window, window.modalPopup)
@@ -1086,7 +1089,7 @@ TestCase {
tryCompare(modalOverlay, "opacity", 1.0)
compare(window.Overlay.overlay.children.length, 2) // 1 popup + 1 overlay
- var modelessOverlay = findOverlay(window, window.modelessPopup)
+ let modelessOverlay = findOverlay(window, window.modelessPopup)
verify(!modelessOverlay)
window.modelessPopup.open()
modelessOverlay = findOverlay(window, window.modelessPopup)
@@ -1135,10 +1138,10 @@ TestCase {
}
function test_attached_applicationwindow() {
- var control = createTemporaryObject(popupControl, applicationWindow.contentItem)
+ let control = createTemporaryObject(popupControl, applicationWindow.contentItem)
verify(control)
- var child = rect.createObject(control.contentItem)
+ let child = rect.createObject(control.contentItem)
compare(control.ApplicationWindow.window, applicationWindow)
compare(control.contentItem.ApplicationWindow.window, applicationWindow)
@@ -1159,14 +1162,14 @@ TestCase {
}
function test_openedClosed() {
- var control = createTemporaryObject(pausePopup, testCase)
+ let control = createTemporaryObject(pausePopup, testCase)
verify(control)
- var openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"})
+ let openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"})
verify(openedSpy.valid)
- var closedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "closed"})
+ let closedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "closed"})
verify(closedSpy.valid)
- var openedChangeSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "openedChanged"})
+ let openedChangeSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "openedChanged"})
verify(openedChangeSpy.valid)
control.open()
@@ -1214,15 +1217,15 @@ TestCase {
}
function test_xyBindingLoop() {
- var window = createTemporaryObject(xyBindingLoop, testCase)
- var control = window.popup
+ let window = createTemporaryObject(xyBindingLoop, testCase)
+ let control = window.popup
waitForRendering(control.contentItem)
compare(control.x, (control.parent.width - control.width) / 2)
compare(control.y, (control.parent.height - control.height) / 2)
}
function test_windowParent() {
- var control = createTemporaryObject(popupControl, applicationWindow, {width: 100, height: 100})
+ let control = createTemporaryObject(popupControl, applicationWindow, {width: 100, height: 100})
verify(control)
control.open()
@@ -1230,7 +1233,7 @@ TestCase {
}
function test_deferredBackgroundSize() {
- var control = createTemporaryObject(popupControl, testCase, {width: 200, height: 100})
+ let control = createTemporaryObject(popupControl, testCase, {width: 200, height: 100})
verify(control)
compare(control.background.width, 200 + (control.background.leftInset || 0) + (control.background.rightInset || 0))
@@ -1238,8 +1241,12 @@ TestCase {
}
function test_anchors() {
- var control = createTemporaryObject(popupControl, applicationWindow.contentItem.Overlay.overlay,
+ let control = createTemporaryObject(popupControl, applicationWindow.contentItem.Overlay.overlay,
{ visible: true, width: 100, height: 100 })
+
+ applicationWindow.visible = true
+ verify(waitForRendering(applicationWindow.contentItem))
+
verify(control)
verify(control.visible)
// If there is a transition then make sure it is finished
@@ -1249,14 +1256,12 @@ TestCase {
compare(control.x, 0)
compare(control.y, 0)
- var overlay = control.Overlay.overlay
+ let overlay = control.Overlay.overlay
verify(overlay)
- var centerInSpy = createTemporaryObject(signalSpy, testCase, { target: control.anchors, signalName: "centerInChanged" })
+ let centerInSpy = createTemporaryObject(signalSpy, testCase, { target: control.anchors, signalName: "centerInChanged" })
verify(centerInSpy.valid)
- applicationWindow.visible = true
- verify(waitForRendering(applicationWindow.contentItem))
verify(overlay.width > 0)
verify(overlay.height > 0)
@@ -1267,7 +1272,7 @@ TestCase {
compare(control.y, (overlay.height - (control.width * control.scale)) / 2)
// Ensure that it warns when trying to set it to an item that's not its parent.
- var anotherItem = createTemporaryObject(rect, applicationWindow.contentItem, { x: 100, y: 100, width: 50, height: 50 })
+ let anotherItem = createTemporaryObject(rect, applicationWindow.contentItem, { x: 100, y: 100, width: 50, height: 50 })
verify(anotherItem)
ignoreWarning(new RegExp(".*QML Popup: Popup can only be centered within its immediate parent or Overlay.overlay"))
@@ -1338,13 +1343,13 @@ TestCase {
function test_shortcut() {
// Tests that a Shortcut with Qt.WindowShortcut context
// that is declared within a Popup is activated.
- var window = createTemporaryObject(shortcutWindowComponent, testCase)
- var control = window.popup
+ let window = createTemporaryObject(shortcutWindowComponent, testCase)
+ let control = window.popup
window.requestActivate()
tryCompare(window, "active", true)
- var shortcutActivatedSpy = createTemporaryObject(signalSpy, testCase,
+ let shortcutActivatedSpy = createTemporaryObject(signalSpy, testCase,
{ target: window.shortcut, signalName: "activated"} )
verify(shortcutActivatedSpy.valid)
@@ -1430,6 +1435,8 @@ TestCase {
let popup = window.popup
popup.open()
+ tryCompare(popup, "opened", true)
+ waitForRendering(popup.contentItem)
// mouse clicks into the popup must not propagate to the parent
mouseClick(window)
@@ -1449,6 +1456,18 @@ TestCase {
mouseRelease(title, pressPoint.x, pressPoint.y)
compare(title.pressedPosition, Qt.point(0, 0))
+
+ // Set modal as true and check for the same operation
+ popup.modal = true
+ oldPos = Qt.point(popup.x, popup.y)
+ mousePress(title, pressPoint.x, pressPoint.y)
+ fuzzyCompare(title.pressedPosition.x, pressPoint.x, 1)
+ fuzzyCompare(title.pressedPosition.y, pressPoint.y, 1)
+ mouseMove(title, pressPoint.x + 5, pressPoint.y + 5)
+ fuzzyCompare(popup.x, oldPos.x + 5, 1)
+ fuzzyCompare(popup.y, oldPos.y + 5, 1)
+ mouseRelease(title, pressPoint.x, pressPoint.y)
+ compare(title.pressedPosition, Qt.point(0, 0))
}
Component {
@@ -1470,4 +1489,73 @@ TestCase {
let rect = findChild(control.Overlay.overlay, "rect")
verify(rect)
}
+
+ Component {
+ id: popupOverlay
+
+ Popup {
+ id: popupCenterIn
+ property alias text: toastText.text
+ anchors.centerIn: Overlay.overlay
+ dim: true
+ modal: true
+ contentItem: ColumnLayout {
+ Text {
+ id: toastText
+ Layout.fillWidth: true
+ wrapMode: Text.Wrap
+ }
+ }
+ }
+ }
+
+ function test_popupOverlayCenterIn() {
+ let control = createTemporaryObject(popupOverlay, testCase)
+ verify(control)
+
+ // Modify text in the popup content item
+ control.text = "this is a long text causing a line break to show the binding loop "
+ + "(height) again after the first initialization of the text";
+
+ // Open popup item and wait for it to be rendered
+ control.open()
+ waitForRendering(testCase)
+ tryCompare(control, "opened", true)
+
+ // Verify popup position
+ compare(control.x, 0)
+ compare(control.y, control.parent.height / 2 - control.height / 2)
+ control.close()
+ }
+
+ Component {
+ id: popupWithOverlayInLoader
+
+ Loader {
+ id: loader
+ active: false
+ sourceComponent: Item {
+ anchors.fill: parent
+ Popup {
+ modal: true
+ visible: true
+ Overlay.modal: Rectangle { color: 'grey' }
+ }
+ }
+ }
+ }
+
+ function test_popupWithOverlayInLoader() { // QTBUG-122915
+ let loader = createTemporaryObject(popupWithOverlayInLoader, testCase)
+ verify(loader)
+
+ let overlay = loader.Overlay.overlay
+ verify(overlay)
+
+ loader.active = true
+ tryCompare(overlay, "visible", true)
+
+ loader.active = false
+ tryCompare(overlay, "visible", false)
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_progressbar.qml b/tests/auto/quickcontrols/controls/data/tst_progressbar.qml
index 6484df815a..043863043d 100644
--- a/tests/auto/quickcontrols/controls/data/tst_progressbar.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_progressbar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -18,15 +18,17 @@ TestCase {
ProgressBar { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(progressBar, testCase)
verify(control)
}
function test_value() {
- var control = createTemporaryObject(progressBar, testCase)
+ let control = createTemporaryObject(progressBar, testCase)
verify(control)
compare(control.value, 0.0)
@@ -41,7 +43,7 @@ TestCase {
}
function test_range() {
- var control = createTemporaryObject(progressBar, testCase, {from: 0, to: 100, value: 50})
+ let control = createTemporaryObject(progressBar, testCase, {from: 0, to: 100, value: 50})
verify(control)
compare(control.from, 0)
@@ -73,7 +75,7 @@ TestCase {
}
function test_inverted() {
- var control = createTemporaryObject(progressBar, testCase, {from: 1.0, to: -1.0})
+ let control = createTemporaryObject(progressBar, testCase, {from: 1.0, to: -1.0})
verify(control)
compare(control.from, 1.0)
@@ -95,7 +97,7 @@ TestCase {
}
function test_position() {
- var control = createTemporaryObject(progressBar, testCase)
+ let control = createTemporaryObject(progressBar, testCase)
verify(control)
compare(control.value, 0)
@@ -111,7 +113,7 @@ TestCase {
}
function test_visualPosition() {
- var control = createTemporaryObject(progressBar, testCase)
+ let control = createTemporaryObject(progressBar, testCase)
verify(control)
compare(control.value, 0)
@@ -143,7 +145,7 @@ TestCase {
}
function test_indeterminate() {
- var control = createTemporaryObject(progressBar, testCase)
+ let control = createTemporaryObject(progressBar, testCase)
verify(control)
compare(control.indeterminate, false)
diff --git a/tests/auto/quickcontrols/controls/data/tst_radiobutton.qml b/tests/auto/quickcontrols/controls/data/tst_radiobutton.qml
index 08caac977d..a4d0a08d7d 100644
--- a/tests/auto/quickcontrols/controls/data/tst_radiobutton.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_radiobutton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -25,15 +25,17 @@ TestCase {
}
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(radioButton, testCase)
verify(control)
}
function test_text() {
- var control = createTemporaryObject(radioButton, testCase)
+ let control = createTemporaryObject(radioButton, testCase)
verify(control)
compare(control.text, "")
@@ -44,10 +46,10 @@ TestCase {
}
function test_checked() {
- var control = createTemporaryObject(radioButton, testCase)
+ let control = createTemporaryObject(radioButton, testCase)
verify(control)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
sequenceSpy.expectedSequence = [] // No change expected
compare(control.checked, false)
@@ -65,10 +67,10 @@ TestCase {
}
function test_mouse() {
- var control = createTemporaryObject(radioButton, testCase)
+ let control = createTemporaryObject(radioButton, testCase)
verify(control)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
// check
sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }],
@@ -127,12 +129,12 @@ TestCase {
}
function test_touch() {
- var control = createTemporaryObject(radioButton, testCase)
+ let control = createTemporaryObject(radioButton, testCase)
verify(control)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
// check
sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }],
@@ -184,10 +186,10 @@ TestCase {
}
function test_keys() {
- var control = createTemporaryObject(radioButton, testCase)
+ let control = createTemporaryObject(radioButton, testCase)
verify(control)
- var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+ let sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
sequenceSpy.expectedSequence = []
control.forceActiveFocus()
@@ -220,8 +222,8 @@ TestCase {
sequenceSpy.expectedSequence = []
// Not testing Key_Enter and Key_Return because QGnomeTheme uses them for
// pressing buttons and the CI uses the QGnomeTheme platform theme.
- var keys = [Qt.Key_Escape, Qt.Key_Tab]
- for (var i = 0; i < keys.length; ++i) {
+ let keys = [Qt.Key_Escape, Qt.Key_Tab]
+ for (let i = 0; i < keys.length; ++i) {
sequenceSpy.reset()
keyClick(keys[i])
compare(control.checked, true)
@@ -238,7 +240,7 @@ TestCase {
}
function test_binding() {
- var container = createTemporaryObject(twoRadioButtons, testCase)
+ let container = createTemporaryObject(twoRadioButtons, testCase)
verify(container)
compare(container.rb1.checked, false)
@@ -277,65 +279,65 @@ TestCase {
}
function test_autoExclusive() {
- var container = createTemporaryObject(radioButtonGroup, testCase)
+ let container = createTemporaryObject(radioButtonGroup, testCase)
compare(container.children.length, 8)
- var checkStates = [false, false, false, false, false, false, false, false]
- for (var i = 0; i < 8; ++i)
+ let checkStates = [false, false, false, false, false, false, false, false]
+ for (let i = 0; i < 8; ++i)
compare(container.children[i].checked, checkStates[i])
container.children[0].checked = true
checkStates[0] = true
- for (i = 0; i < 8; ++i)
+ for (let i = 0; i < 8; ++i)
compare(container.children[i].checked, checkStates[i])
container.children[1].checked = true
checkStates[0] = false
checkStates[1] = true
- for (i = 0; i < 8; ++i)
+ for (let i = 0; i < 8; ++i)
compare(container.children[i].checked, checkStates[i])
container.children[2].checked = true
checkStates[2] = true
- for (i = 0; i < 8; ++i)
+ for (let i = 0; i < 8; ++i)
compare(container.children[i].checked, checkStates[i])
container.children[3].checked = true
checkStates[2] = false
checkStates[3] = true
- for (i = 0; i < 8; ++i)
+ for (let i = 0; i < 8; ++i)
compare(container.children[i].checked, checkStates[i])
container.children[4].checked = true
checkStates[4] = true
- for (i = 0; i < 8; ++i)
+ for (let i = 0; i < 8; ++i)
compare(container.children[i].checked, checkStates[i])
container.children[5].checked = true
checkStates[4] = false
checkStates[5] = true
- for (i = 0; i < 8; ++i)
+ for (let i = 0; i < 8; ++i)
compare(container.children[i].checked, checkStates[i])
container.children[6].checked = true
checkStates[6] = true
- for (i = 0; i < 8; ++i)
+ for (let i = 0; i < 8; ++i)
compare(container.children[i].checked, checkStates[i])
container.children[7].checked = true
checkStates[7] = true
- for (i = 0; i < 8; ++i)
+ for (let i = 0; i < 8; ++i)
compare(container.children[i].checked, checkStates[i])
container.children[0].checked = true
checkStates[0] = true
checkStates[1] = false
- for (i = 0; i < 8; ++i)
+ for (let i = 0; i < 8; ++i)
compare(container.children[i].checked, checkStates[i])
}
function test_baseline() {
- var control = createTemporaryObject(radioButton, testCase)
+ let control = createTemporaryObject(radioButton, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_radiodelegate.qml b/tests/auto/quickcontrols/controls/data/tst_radiodelegate.qml
index fe89838bda..fc6d93886f 100644
--- a/tests/auto/quickcontrols/controls/data/tst_radiodelegate.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_radiodelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -20,16 +20,18 @@ TestCase {
// TODO: data-fy tst_radiobutton (rename to tst_radio?) so we don't duplicate its tests here?
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(radioDelegate, testCase);
+ function test_defaults() {
+ let control = createTemporaryObject(radioDelegate, testCase);
verify(control);
verify(!control.checked);
}
function test_checked() {
- var control = createTemporaryObject(radioDelegate, testCase);
+ let control = createTemporaryObject(radioDelegate, testCase);
verify(control);
mouseClick(control);
@@ -40,17 +42,17 @@ TestCase {
}
function test_baseline() {
- var control = createTemporaryObject(radioDelegate, testCase);
+ let control = createTemporaryObject(radioDelegate, testCase);
verify(control);
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset);
}
function test_spacing() {
- var control = createTemporaryObject(radioDelegate, testCase, { text: "Some long, long, long text" })
+ let control = createTemporaryObject(radioDelegate, testCase, { text: "Some long, long, long text" })
verify(control)
verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth)
- var textLabel = findChild(control.contentItem, "label")
+ let textLabel = findChild(control.contentItem, "label")
verify(textLabel)
// The implicitWidth of the IconLabel that all buttons use as their contentItem should be
@@ -77,7 +79,7 @@ TestCase {
}
function test_display(data) {
- var control = createTemporaryObject(radioDelegate, testCase, {
+ let control = createTemporaryObject(radioDelegate, testCase, {
text: "RadioDelegate",
display: data.display,
width: 400,
@@ -87,11 +89,11 @@ TestCase {
verify(control)
compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png")
- var iconImage = findChild(control.contentItem, "image")
- var textLabel = findChild(control.contentItem, "label")
+ let iconImage = findChild(control.contentItem, "image")
+ let textLabel = findChild(control.contentItem, "label")
- var availableWidth = control.availableWidth - control.indicator.width - control.spacing
- var indicatorOffset = control.mirrored ? control.indicator.width + control.spacing : 0
+ let availableWidth = control.availableWidth - control.indicator.width - control.spacing
+ let indicatorOffset = control.mirrored ? control.indicator.width + control.spacing : 0
switch (control.display) {
case RadioDelegate.IconOnly:
diff --git a/tests/auto/quickcontrols/controls/data/tst_rangeslider.qml b/tests/auto/quickcontrols/controls/data/tst_rangeslider.qml
index 91e366c819..a574566bfb 100644
--- a/tests/auto/quickcontrols/controls/data/tst_rangeslider.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_rangeslider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -42,10 +42,12 @@ TestCase {
}
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(sliderComponent, testCase)
+ function test_defaults() {
+ let control = createTemporaryObject(sliderComponent, testCase)
verify(control)
compare(control.stepSize, 0)
@@ -56,7 +58,7 @@ TestCase {
}
function test_values() {
- var control = createTemporaryObject(sliderComponent, testCase)
+ let control = createTemporaryObject(sliderComponent, testCase)
verify(control)
compare(control.first.value, 0.0)
@@ -81,7 +83,7 @@ TestCase {
}
function test_range() {
- var control = createTemporaryObject(sliderComponent, testCase, { from: 0, to: 100, "first.value": 50, "second.value": 100 })
+ let control = createTemporaryObject(sliderComponent, testCase, { from: 0, to: 100, "first.value": 50, "second.value": 100 })
verify(control)
compare(control.from, 0)
@@ -115,16 +117,16 @@ TestCase {
}
function test_setToFromUpdatesHandles() {
- var control = createTemporaryObject(sliderComponent, testCase, { from: 0, to: 100, "first.value": 50, "second.value": 75 })
+ let control = createTemporaryObject(sliderComponent, testCase, { from: 0, to: 100, "first.value": 50, "second.value": 75 })
verify(control)
let firstPos = control.first.position
let secondPos = control.second.position
- var firstPosChangesSpy = signalSpy.createObject(control, {target: control.first, signalName: "positionChanged"})
+ let firstPosChangesSpy = signalSpy.createObject(control, {target: control.first, signalName: "positionChanged"})
verify(firstPosChangesSpy.valid)
- var secondPosChangesSpy = signalSpy.createObject(control, {target: control.second, signalName: "positionChanged"})
+ let secondPosChangesSpy = signalSpy.createObject(control, {target: control.second, signalName: "positionChanged"})
verify(secondPosChangesSpy.valid)
// Increasing the 'to' value, so the positions of the handles should be
@@ -152,7 +154,7 @@ TestCase {
}
function test_setValues() {
- var control = createTemporaryObject(sliderComponent, testCase)
+ let control = createTemporaryObject(sliderComponent, testCase)
verify(control)
compare(control.from, 0)
@@ -177,7 +179,7 @@ TestCase {
}
function test_inverted() {
- var control = createTemporaryObject(sliderComponent, testCase, { from: 1.0, to: -1.0 })
+ let control = createTemporaryObject(sliderComponent, testCase, { from: 1.0, to: -1.0 })
verify(control)
compare(control.from, 1.0)
@@ -207,7 +209,7 @@ TestCase {
}
function test_visualPosition() {
- var control = createTemporaryObject(sliderComponent, testCase)
+ let control = createTemporaryObject(sliderComponent, testCase)
verify(control)
compare(control.first.value, 0.0)
@@ -252,7 +254,7 @@ TestCase {
}
function test_orientation() {
- var control = createTemporaryObject(sliderComponent, testCase)
+ let control = createTemporaryObject(sliderComponent, testCase)
verify(control)
compare(control.orientation, Qt.Horizontal)
@@ -277,19 +279,19 @@ TestCase {
}
function test_mouse(data) {
- var control = createTemporaryObject(sliderComponent, testCase, { orientation: data.orientation, live: data.live })
+ let control = createTemporaryObject(sliderComponent, testCase, { orientation: data.orientation, live: data.live })
verify(control)
- var firstPressedSpy = signalSpy.createObject(control, {target: control.first, signalName: "pressedChanged"})
+ let firstPressedSpy = signalSpy.createObject(control, {target: control.first, signalName: "pressedChanged"})
verify(firstPressedSpy.valid)
- var firstMovedSpy = signalSpy.createObject(control, {target: control.first, signalName: "moved"})
+ let firstMovedSpy = signalSpy.createObject(control, {target: control.first, signalName: "moved"})
verify(firstMovedSpy.valid)
- var secondPressedSpy = signalSpy.createObject(control, {target: control.second, signalName: "pressedChanged"})
+ let secondPressedSpy = signalSpy.createObject(control, {target: control.second, signalName: "pressedChanged"})
verify(secondPressedSpy.valid)
- var secondMovedSpy = signalSpy.createObject(control, {target: control.second, signalName: "moved"})
+ let secondMovedSpy = signalSpy.createObject(control, {target: control.second, signalName: "moved"})
verify(secondMovedSpy.valid)
// Press and release the first handle without moving it.
@@ -380,9 +382,9 @@ TestCase {
compare(control.second.value, 1.0)
compare(control.second.position, 1.0)
- var horizontal = control.orientation === Qt.Horizontal
- var toX = horizontal ? control.width * 0.5 : control.first.handle.x
- var toY = horizontal ? control.first.handle.y : control.height * 0.5
+ let horizontal = control.orientation === Qt.Horizontal
+ let toX = horizontal ? control.width * 0.5 : control.first.handle.x
+ let toY = horizontal ? control.first.handle.y : control.height * 0.5
mouseMove(control, toX, toY)
compare(firstPressedSpy.count, 5)
compare(firstMovedSpy.count, 1)
@@ -422,24 +424,25 @@ TestCase {
}
function test_touch(data) {
- var control = createTemporaryObject(sliderComponent, testCase, { orientation: data.orientation, live: data.live })
+ let control = createTemporaryObject(sliderComponent, testCase, { orientation: data.orientation, live: data.live })
verify(control)
- var firstPressedSpy = signalSpy.createObject(control, {target: control.first, signalName: "pressedChanged"})
+ let firstPressedSpy = signalSpy.createObject(control, {target: control.first, signalName: "pressedChanged"})
verify(firstPressedSpy.valid)
- var firstMovedSpy = signalSpy.createObject(control, {target: control.first, signalName: "moved"})
+ let firstMovedSpy = signalSpy.createObject(control, {target: control.first, signalName: "moved"})
verify(firstMovedSpy.valid)
- var secondPressedSpy = signalSpy.createObject(control, {target: control.second, signalName: "pressedChanged"})
+ let secondPressedSpy = signalSpy.createObject(control, {target: control.second, signalName: "pressedChanged"})
verify(secondPressedSpy.valid)
- var secondMovedSpy = signalSpy.createObject(control, {target: control.second, signalName: "moved"})
+ let secondMovedSpy = signalSpy.createObject(control, {target: control.second, signalName: "moved"})
verify(secondMovedSpy.valid)
// Press and release the first handle without moving it.
- var touch = touchEvent(control)
- touch.press(0, control, control.width * 0.25, control.height * 0.75).commit()
+ let touch = touchEvent(control)
+ control.setValues(0, 1);
+ touch.press(0, control, control.leftPadding, control.height - control.bottomPadding - 1).commit()
compare(firstPressedSpy.count, 1)
compare(firstMovedSpy.count, 0)
compare(secondPressedSpy.count, 0)
@@ -451,7 +454,7 @@ TestCase {
compare(control.second.value, 1.0)
compare(control.second.position, 1.0)
- touch.release(0, control, control.width * 0.25, control.height * 0.75).commit()
+ touch.release(0, control, control.leftPadding, control.height - control.bottomPadding - 1).commit()
compare(firstPressedSpy.count, 2)
compare(firstMovedSpy.count, 0)
compare(secondPressedSpy.count, 0)
@@ -464,7 +467,7 @@ TestCase {
compare(control.second.position, 1.0)
// Press and release the second handle without moving it.
- touch.press(0, control, control.width * 0.75, control.height * 0.25).commit()
+ touch.press(0, control, control.width - control.rightPadding - 1, control.topPadding).commit()
compare(firstPressedSpy.count, 2)
compare(secondPressedSpy.count, 1)
compare(control.first.pressed, false)
@@ -474,7 +477,7 @@ TestCase {
compare(control.second.value, 1.0)
compare(control.second.position, 1.0)
- touch.release(0, control, control.width * 0.75, control.height * 0.25).commit()
+ touch.release(0, control, control.width - control.rightPadding - 1, control.topPadding).commit()
compare(firstPressedSpy.count, 2)
compare(secondPressedSpy.count, 2)
compare(control.first.pressed, false)
@@ -516,9 +519,9 @@ TestCase {
compare(control.second.position, 1.0)
// Drag the first handle.
- var horizontal = control.orientation === Qt.Horizontal
- var toX = horizontal ? control.width * 0.5 : control.first.handle.x
- var toY = horizontal ? control.first.handle.y : control.height * 0.5
+ let horizontal = control.orientation === Qt.Horizontal
+ let toX = horizontal ? control.width * 0.5 : control.first.handle.x
+ let toY = horizontal ? control.first.handle.y : control.height * 0.5
touch.move(0, control, toX, toY).commit()
compare(firstPressedSpy.count, 5)
compare(secondPressedSpy.count, 2)
@@ -545,11 +548,11 @@ TestCase {
}
function test_multiTouch() {
- var control1 = createTemporaryObject(sliderComponent, testCase)
+ let control1 = createTemporaryObject(sliderComponent, testCase)
verify(control1)
// press and move the first handle of the first slider
- var touch = touchEvent(control1)
+ let touch = touchEvent(control1)
touch.press(0, control1, 0, 0).commit().move(0, control1, control1.width / 2, control1.height / 2).commit()
compare(control1.first.pressed, true)
compare(control1.first.position, 0.5)
@@ -564,7 +567,7 @@ TestCase {
compare(control1.second.pressed, true)
compare(control1.second.position, 0.5)
- var control2 = createTemporaryObject(sliderComponent, testCase, {y: control1.height})
+ let control2 = createTemporaryObject(sliderComponent, testCase, {y: control1.height})
verify(control2)
// press and move the first handle of the second slider
@@ -604,7 +607,7 @@ TestCase {
}
function test_overlappingHandles() {
- var control = createTemporaryObject(sliderComponent, testCase)
+ let control = createTemporaryObject(sliderComponent, testCase)
verify(control)
// By default, we force the second handle to be after the first in
@@ -669,12 +672,12 @@ TestCase {
}
function test_keys(data) {
- var control = createTemporaryObject(sliderComponent, testCase, { orientation: data.orientation })
+ let control = createTemporaryObject(sliderComponent, testCase, { orientation: data.orientation })
verify(control)
- var pressedCount = 0
+ let pressedCount = 0
- var firstPressedSpy = signalSpy.createObject(control, {target: control.first, signalName: "pressedChanged"})
+ let firstPressedSpy = signalSpy.createObject(control, {target: control.first, signalName: "pressedChanged"})
verify(firstPressedSpy.valid)
control.first.handle.forceActiveFocus()
@@ -682,7 +685,7 @@ TestCase {
control.first.value = 0.5
- for (var d1 = 1; d1 <= 10; ++d1) {
+ for (let d1 = 1; d1 <= 10; ++d1) {
keyPress(data.decrease)
compare(control.first.pressed, true)
compare(firstPressedSpy.count, ++pressedCount)
@@ -695,7 +698,7 @@ TestCase {
compare(firstPressedSpy.count, ++pressedCount)
}
- for (var i1 = 1; i1 <= 20; ++i1) {
+ for (let i1 = 1; i1 <= 20; ++i1) {
keyPress(data.increase)
compare(control.first.pressed, true)
compare(firstPressedSpy.count, ++pressedCount)
@@ -712,13 +715,13 @@ TestCase {
control.stepSize = 0.25
pressedCount = 0;
- var secondPressedSpy = signalSpy.createObject(control, {target: control.second, signalName: "pressedChanged"})
+ let secondPressedSpy = signalSpy.createObject(control, {target: control.second, signalName: "pressedChanged"})
verify(secondPressedSpy.valid)
control.second.handle.forceActiveFocus()
verify(control.second.handle.activeFocus)
- for (var d2 = 1; d2 <= 10; ++d2) {
+ for (let d2 = 1; d2 <= 10; ++d2) {
keyPress(data.decrease)
compare(control.second.pressed, true)
compare(secondPressedSpy.count, ++pressedCount)
@@ -731,7 +734,7 @@ TestCase {
compare(secondPressedSpy.count, ++pressedCount)
}
- for (var i2 = 1; i2 <= 10; ++i2) {
+ for (let i2 = 1; i2 <= 10; ++i2) {
keyPress(data.increase)
compare(control.second.pressed, true)
compare(secondPressedSpy.count, ++pressedCount)
@@ -749,10 +752,10 @@ TestCase {
// test with "unbalanced" paddings (left padding != right padding) to ensure
// that the slider position calculation is done taking padding into account
// ==> the position is _not_ 0.5 in the middle of the control
- var control = createTemporaryObject(sliderComponent, testCase, { leftPadding: 10, rightPadding: 20, live: false })
+ let control = createTemporaryObject(sliderComponent, testCase, { leftPadding: 10, rightPadding: 20, live: false })
verify(control)
- var firstPressedSpy = signalSpy.createObject(control, {target: control.first, signalName: "pressedChanged"})
+ let firstPressedSpy = signalSpy.createObject(control, {target: control.first, signalName: "pressedChanged"})
verify(firstPressedSpy.valid)
mousePress(control, control.first.handle.x, control.first.handle.y, Qt.LeftButton)
@@ -835,13 +838,13 @@ TestCase {
}
function test_snapMode_mouse(data) {
- var control = createTemporaryObject(sliderComponent, testCase, {snapMode: data.snapMode, from: data.from, to: data.to, stepSize: 0.2, live: false, width: testCase.width})
+ let control = createTemporaryObject(sliderComponent, testCase, {snapMode: data.snapMode, from: data.from, to: data.to, stepSize: 0.2, live: false, width: testCase.width})
verify(control)
control.first.value = 0
control.second.value = data.to
- var fuzz = 0.05
+ let fuzz = 0.05
mousePress(control, control.leftPadding)
compare(control.first.pressed, true)
@@ -864,15 +867,15 @@ TestCase {
}
function test_snapMode_touch(data) {
- var control = createTemporaryObject(sliderComponent, testCase, {snapMode: data.snapMode, from: data.from, to: data.to, stepSize: 0.2, live: false, width: testCase.width})
+ let control = createTemporaryObject(sliderComponent, testCase, {snapMode: data.snapMode, from: data.from, to: data.to, stepSize: 0.2, live: false, width: testCase.width})
verify(control)
control.first.value = 0
control.second.value = data.to
- var fuzz = 0.05
+ let fuzz = 0.05
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
touch.press(0, control, control.first.handle.x, control.first.handle.y).commit()
compare(control.first.pressed, true)
compare(control.first.value, data.values[0])
@@ -890,7 +893,7 @@ TestCase {
}
function test_focus() {
- var control = createTemporaryObject(sliderComponent, testCase)
+ let control = createTemporaryObject(sliderComponent, testCase)
verify(control)
compare(control.activeFocus, false)
@@ -930,10 +933,10 @@ TestCase {
}
function test_hover(data) {
- var control = createTemporaryObject(sliderComponent, testCase, {hoverEnabled: data.hoverEnabled})
+ let control = createTemporaryObject(sliderComponent, testCase, {hoverEnabled: data.hoverEnabled})
verify(control)
- var node = control[data.node]
+ let node = control[data.node]
compare(control.hovered, false)
compare(node.hovered, false)
@@ -946,7 +949,7 @@ TestCase {
}
function test_nullHandles() {
- var control = createTemporaryObject(sliderComponent, testCase, {"second.value": 1})
+ let control = createTemporaryObject(sliderComponent, testCase, {"second.value": 1})
verify(control)
verify(control.first.handle)
@@ -973,7 +976,7 @@ TestCase {
}
function test_touchDragThreshold_data() {
- var d1 = 3; var d2 = 7;
+ let d1 = 3; let d2 = 7;
return [
{ tag: "horizontal", orientation: Qt.Horizontal, dx1: d1, dy1: 0, dx2: d2, dy2: 0 },
{ tag: "vertical", orientation: Qt.Vertical, dx1: 0, dy1: -d1, dx2: 0, dy2: -d2 },
@@ -983,19 +986,19 @@ TestCase {
}
function test_touchDragThreshold(data) {
- var control = createTemporaryObject(sliderComponent, testCase, {touchDragThreshold: 10, live: true, orientation: data.orientation, "first.value": 0, "second.value": 1})
+ let control = createTemporaryObject(sliderComponent, testCase, {touchDragThreshold: 10, live: true, orientation: data.orientation, "first.value": 0, "second.value": 1})
verify(control)
compare(control.touchDragThreshold, 10)
- var valueChangedCount = 0
- var valueChangedSpy = signalSpy.createObject(control, {target: control, signalName: "touchDragThresholdChanged"})
+ let valueChangedCount = 0
+ let valueChangedSpy = signalSpy.createObject(control, {target: control, signalName: "touchDragThresholdChanged"})
verify(valueChangedSpy.valid)
control.touchDragThreshold = undefined
compare(control.touchDragThreshold, -1) // reset to -1
compare(valueChangedSpy.count, ++valueChangedCount)
- var t = 5
+ let t = 5
control.touchDragThreshold = t
compare(control.touchDragThreshold, t)
compare(valueChangedSpy.count, ++valueChangedCount)
@@ -1004,26 +1007,26 @@ TestCase {
compare(control.touchDragThreshold, t)
compare(valueChangedSpy.count, valueChangedCount)
- var pressedCount = 0
- var pressedCount2 = 0
- var visualPositionCount = 0
- var visualPositionCount2 = 0
+ let pressedCount = 0
+ let pressedCount2 = 0
+ let visualPositionCount = 0
+ let visualPositionCount2 = 0
- var pressedSpy = signalSpy.createObject(control, {target: control.first, signalName: "pressedChanged"})
+ let pressedSpy = signalSpy.createObject(control, {target: control.first, signalName: "pressedChanged"})
verify(pressedSpy.valid)
- var pressedSpy2 = signalSpy.createObject(control, {target: control.second, signalName: "pressedChanged"})
+ let pressedSpy2 = signalSpy.createObject(control, {target: control.second, signalName: "pressedChanged"})
verify(pressedSpy2.valid)
- var visualPositionSpy = signalSpy.createObject(control, {target: control.first, signalName: "visualPositionChanged"})
+ let visualPositionSpy = signalSpy.createObject(control, {target: control.first, signalName: "visualPositionChanged"})
verify(visualPositionSpy.valid)
- var visualPositionSpy2 = signalSpy.createObject(control, {target: control.second, signalName: "visualPositionChanged"})
+ let visualPositionSpy2 = signalSpy.createObject(control, {target: control.second, signalName: "visualPositionChanged"})
verify(visualPositionSpy2.valid)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
control.first.value = 0.4
control.second.value = 1
- var x0 = control.first.handle.x + control.first.handle.width * 0.5
- var y0 = control.first.handle.y + control.first.handle.height * 0.5
+ let x0 = control.first.handle.x + control.first.handle.width * 0.5
+ let y0 = control.first.handle.y + control.first.handle.height * 0.5
touch.press(0, control, x0, y0).commit()
compare(pressedSpy.count, ++pressedCount)
compare(control.first.pressed, true)
@@ -1073,7 +1076,7 @@ TestCase {
}
function test_valueAt(data) {
- var control = createTemporaryObject(sliderComponent, testCase, data.properties)
+ let control = createTemporaryObject(sliderComponent, testCase, data.properties)
verify(control)
compare(control.valueAt(0.0), data.values[0])
@@ -1081,4 +1084,173 @@ TestCase {
compare(control.valueAt(0.5), data.values[2])
compare(control.valueAt(1.0), data.values[3])
}
+
+ function test_updatePositionOnPress() {
+ let control = createTemporaryObject(sliderComponent, testCase)
+ verify(control)
+
+ let firstPressedSpy = signalSpy.createObject(control, {target: control.first, signalName: "pressedChanged"})
+ verify(firstPressedSpy.valid)
+
+ let firstMovedSpy = signalSpy.createObject(control, {target: control.first, signalName: "moved"})
+ verify(firstMovedSpy.valid)
+
+ let secondPressedSpy = signalSpy.createObject(control, {target: control.second, signalName: "pressedChanged"})
+ verify(secondPressedSpy.valid)
+
+ let secondMovedSpy = signalSpy.createObject(control, {target: control.second, signalName: "moved"})
+ verify(secondMovedSpy.valid)
+
+ // Touch press and release on the left corner
+ control.setValues(0.2, 0.8)
+ compare(control.first.value, 0.2)
+ compare(control.second.value, 0.8)
+ let touch = touchEvent(control)
+ touch.press(0, control, 0, control.height * 0.75).commit()
+ compare(firstPressedSpy.count, 1)
+ compare(firstMovedSpy.count, 0)
+ compare(secondPressedSpy.count, 0)
+ compare(secondMovedSpy.count, 0)
+ compare(control.first.pressed, true)
+ compare(control.first.value, 0.2)
+ compare(control.first.position, 0.2)
+ compare(control.second.pressed, false)
+ compare(control.second.value, 0.8)
+ compare(control.second.position, 0.8)
+
+ touch.release(0, control, 0, control.height * 0.75).commit()
+ compare(firstPressedSpy.count, 2)
+ compare(firstMovedSpy.count, 1)
+ compare(secondPressedSpy.count, 0)
+ compare(secondMovedSpy.count, 0)
+ compare(control.first.pressed, false)
+ compare(control.first.value, 0.0)
+ compare(control.first.position, 0.0)
+ compare(control.second.pressed, false)
+ compare(control.second.value, 0.8)
+ compare(control.second.position, 0.8)
+
+ firstPressedSpy.clear()
+ firstMovedSpy.clear()
+ secondPressedSpy.clear()
+ secondMovedSpy.clear()
+
+ // Touch press and release on the right corner
+ // On touch, the handle position is updated on release
+ control.setValues(0.2, 0.8)
+ compare(control.first.value, 0.2)
+ compare(control.second.value, 0.8)
+ touch = touchEvent(control)
+ touch.press(0, control, control.width - control.rightPadding - 1, control.height * 0.75).commit()
+ compare(secondPressedSpy.count, 1)
+ compare(secondMovedSpy.count, 0)
+ compare(firstPressedSpy.count, 0)
+ compare(firstMovedSpy.count, 0)
+ compare(control.second.pressed, true)
+ compare(control.second.value, 0.8)
+ compare(control.second.position, 0.8)
+ compare(control.first.pressed, false)
+ compare(control.first.value, 0.2)
+ compare(control.first.position, 0.2)
+
+ touch.release(0, control, control.width - control.rightPadding - 1, control.height * 0.75).commit()
+ compare(secondPressedSpy.count, 2)
+ compare(secondMovedSpy.count, 1)
+ compare(firstPressedSpy.count, 0)
+ compare(firstMovedSpy.count, 0)
+ compare(control.second.pressed, false)
+ compare(control.second.value, 1.0)
+ compare(control.second.position, 1.0)
+ compare(control.first.pressed, false)
+ compare(control.first.value, 0.2)
+ compare(control.first.position, 0.2)
+
+ firstPressedSpy.clear()
+ firstMovedSpy.clear()
+ secondPressedSpy.clear()
+ secondMovedSpy.clear()
+
+ // Mouse press and release on the left corner
+ // On mouse, the position is immediately updated on press
+ control.setValues(0.2, 0.8)
+ compare(control.first.value, 0.2)
+ compare(control.second.value, 0.8)
+ mousePress(control, 0, control.height * 0.75, Qt.LeftButton)
+ compare(firstPressedSpy.count, 1)
+ compare(firstMovedSpy.count, 1)
+ compare(secondPressedSpy.count, 0)
+ compare(secondMovedSpy.count, 0)
+ compare(control.first.pressed, true)
+ compare(control.first.value, 0.0)
+ compare(control.first.position, 0.0)
+ compare(control.second.pressed, false)
+ compare(control.second.value, 0.8)
+ compare(control.second.position, 0.8)
+
+ mouseRelease(control, 0, control.height * 0.75, Qt.LeftButton)
+ compare(firstPressedSpy.count, 2)
+ compare(firstMovedSpy.count, 1)
+ compare(secondPressedSpy.count, 0)
+ compare(secondMovedSpy.count, 0)
+ compare(control.first.pressed, false)
+ compare(control.first.value, 0.0)
+ compare(control.first.position, 0.0)
+ compare(control.second.pressed, false)
+ compare(control.second.value, 0.8)
+ compare(control.second.position, 0.8)
+
+ firstPressedSpy.clear()
+ firstMovedSpy.clear()
+ secondPressedSpy.clear()
+ secondMovedSpy.clear()
+
+ // Mouse press and release on the right corner
+ control.setValues(0.2, 0.8)
+ compare(control.first.value, 0.2)
+ compare(control.second.value, 0.8)
+ mousePress(control, control.width - control.rightPadding - 1, control.height * 0.75, Qt.LeftButton)
+ compare(secondPressedSpy.count, 1)
+ compare(secondMovedSpy.count, 1)
+ compare(firstPressedSpy.count, 0)
+ compare(firstMovedSpy.count, 0)
+ compare(control.second.pressed, true)
+ compare(control.second.value, 1.0)
+ compare(control.second.position, 1.0)
+ compare(control.first.pressed, false)
+ compare(control.first.value, 0.2)
+ compare(control.first.position, 0.2)
+
+ mouseRelease(control, control.width - control.rightPadding - 1, control.height * 0.75, Qt.LeftButton)
+ compare(secondPressedSpy.count, 2)
+ compare(secondMovedSpy.count, 1)
+ compare(firstPressedSpy.count, 0)
+ compare(firstMovedSpy.count, 0)
+ compare(control.second.pressed, false)
+ compare(control.second.value, 1.0)
+ compare(control.second.position, 1.0)
+ compare(control.first.pressed, false)
+ compare(control.first.value, 0.2)
+ compare(control.first.position, 0.2)
+ }
+
+ function test_clickFocus() {
+ let control = createTemporaryObject(sliderComponent, testCase)
+ verify(control)
+
+ // Click on the second handle - it should get focus on press.
+ mousePress(control, control.second.handle.x, control.second.handle.y, Qt.LeftButton)
+ if (Qt.platform.os === "osx")
+ verify(!control.activeFocus)
+ else
+ verify(control.activeFocus)
+ mouseRelease(control, control.second.handle.x, control.second.handle.y, Qt.LeftButton)
+
+ // Click on the first handle - it should get focus on press.
+ mousePress(control, control.first.handle.x, control.first.handle.y, Qt.LeftButton)
+ if (Qt.platform.os === "osx")
+ verify(!control.activeFocus)
+ else
+ verify(control.activeFocus)
+ mouseRelease(control, control.first.handle.x, control.first.handle.y, Qt.LeftButton)
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_roundbutton.qml b/tests/auto/quickcontrols/controls/data/tst_roundbutton.qml
index dfdd62086d..553d99a2d8 100644
--- a/tests/auto/quickcontrols/controls/data/tst_roundbutton.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_roundbutton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -18,18 +18,20 @@ TestCase {
RoundButton { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(roundButton, testCase)
verify(control)
}
function test_radius() {
- var control = createTemporaryObject(roundButton, testCase);
+ let control = createTemporaryObject(roundButton, testCase);
verify(control);
- var implicitRadius = control.radius;
+ let implicitRadius = control.radius;
compare(implicitRadius, Math.min(control.width, control.height) / 2);
control.radius = 10;
@@ -46,11 +48,11 @@ TestCase {
}
function test_spacing() {
- var control = createTemporaryObject(roundButton, testCase, { text: "Some long, long, long text" })
+ let control = createTemporaryObject(roundButton, testCase, { text: "Some long, long, long text" })
verify(control)
verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth)
- var textLabel = findChild(control.contentItem, "label")
+ let textLabel = findChild(control.contentItem, "label")
verify(textLabel)
// The implicitWidth of the IconLabel that all buttons use as their contentItem
@@ -79,7 +81,7 @@ TestCase {
}
function test_display(data) {
- var control = createTemporaryObject(roundButton, testCase, {
+ let control = createTemporaryObject(roundButton, testCase, {
text: "RoundButton",
display: data.display,
"icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png",
@@ -88,8 +90,8 @@ TestCase {
verify(control)
compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png")
- var iconImage = findChild(control.contentItem, "image")
- var textLabel = findChild(control.contentItem, "label")
+ let iconImage = findChild(control.contentItem, "image")
+ let textLabel = findChild(control.contentItem, "label")
switch (control.display) {
case RoundButton.IconOnly:
diff --git a/tests/auto/quickcontrols/controls/data/tst_scrollbar.qml b/tests/auto/quickcontrols/controls/data/tst_scrollbar.qml
index f26d8f5cb0..2031019157 100644
--- a/tests/auto/quickcontrols/controls/data/tst_scrollbar.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_scrollbar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -28,6 +28,7 @@ TestCase {
Component {
id: scrollBar
ScrollBar {
+ objectName: "scrollBar"
padding: 0
minimumSize: 0
}
@@ -43,6 +44,7 @@ TestCase {
Component {
id: flickable
Flickable {
+ objectName: "flickable"
width: 100
height: 100
contentWidth: 200
@@ -52,19 +54,21 @@ TestCase {
}
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(defaultScrollBar, testCase)
verify(control)
}
function test_attach() {
- var container = createTemporaryObject(flickable, testCase)
+ let container = createTemporaryObject(flickable, testCase)
verify(container)
waitForRendering(container)
- var vertical = scrollBar.createObject()
+ let vertical = scrollBar.createObject(null, { objectName: "verticalScrollBar" })
verify(!vertical.parent)
compare(vertical.size, 0.0)
compare(vertical.position, 0.0)
@@ -94,7 +98,7 @@ TestCase {
container.width += 10
compare(vertical.x, 123)
- var horizontal = createTemporaryObject(scrollBar, null)
+ let horizontal = createTemporaryObject(scrollBar, null, { objectName: "horizontalScrollBar" })
verify(!horizontal.parent)
compare(horizontal.size, 0.0)
compare(horizontal.position, 0.0)
@@ -124,7 +128,7 @@ TestCase {
container.height += 10
compare(horizontal.y, 123)
- var velocity = container.maximumFlickVelocity
+ let velocity = container.maximumFlickVelocity
compare(container.flicking, false)
container.flick(-velocity, -velocity)
@@ -146,16 +150,16 @@ TestCase {
compare(horizontal.size, container.visibleArea.widthRatio)
compare(horizontal.position, container.visibleArea.xPosition)
- var oldY = vertical.y
- var oldHeight = vertical.height
+ let oldY = vertical.y
+ let oldHeight = vertical.height
vertical.parent = testCase
vertical.y -= 10
container.height += 10
compare(vertical.y, oldY - 10)
compare(vertical.height, oldHeight)
- var oldX = horizontal.x
- var oldWidth = horizontal.width
+ let oldX = horizontal.x
+ let oldWidth = horizontal.width
horizontal.parent = testCase
horizontal.x -= 10
container.width += 10
@@ -216,12 +220,12 @@ TestCase {
}
function test_mouse(data) {
- var control = createTemporaryObject(scrollBarWithDefaultPadding, testCase, data.properties)
+ let control = createTemporaryObject(scrollBarWithDefaultPadding, testCase, data.properties)
verify(control)
- var grooveRange = getGrooveRange(control)
+ let grooveRange = getGrooveRange(control)
- var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
+ let pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
verify(pressedSpy.valid)
mousePress(control, grooveRange.start.x, grooveRange.start.y, Qt.LeftButton)
@@ -268,7 +272,7 @@ TestCase {
fuzzyCompare(control.position, 0.25, 0.01)
if (control.__decreaseVisual.indicator !== null) {
- var p = control.__decreaseVisual.indicator.mapToItem(control, Qt.point(0, 0))
+ let p = control.__decreaseVisual.indicator.mapToItem(control, Qt.point(0, 0))
mousePress(control, p.x, p.y, Qt.LeftButton)
compare(pressedSpy.count, 4)
compare(control.pressed, false)
@@ -296,18 +300,18 @@ TestCase {
}
function test_touch(data) {
- var control = createTemporaryObject(scrollBar, testCase, data.properties)
+ let control = createTemporaryObject(scrollBar, testCase, data.properties)
verify(control)
- var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
+ let pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
verify(pressedSpy.valid)
control.width += (control.leftPadding + control.rightPadding)
control.height += (control.topPadding + control.bottomPadding)
- var availableSlideWidth = 0
- var availableSlideHeight = 0
+ let availableSlideWidth = 0
+ let availableSlideHeight = 0
- var p0 = {}
+ let p0 = {}
if (control.orientation === Qt.Horizontal) {
availableSlideWidth = control.width - control.rightPadding - control.leftPadding
p0 = { x = control.leftPadding, y = control.height/2 }
@@ -316,7 +320,7 @@ TestCase {
p0 = { x = control.width/2, y = control.topPadding}
}
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
touch.press(0, control, p0.x, p0.y).commit()
compare(pressedSpy.count, 1)
@@ -360,23 +364,23 @@ TestCase {
}
function test_multiTouch() {
- var control1 = createTemporaryObject(scrollBar, testCase)
+ let control1 = createTemporaryObject(scrollBar, testCase)
verify(control1)
control1.height = 200 + (control1.topPadding + control1.bottomPadding)
- var grooveRange = getGrooveRange(control1)
+ let grooveRange = getGrooveRange(control1)
- var pressedCount1 = 0
- var movedCount1 = 0
+ let pressedCount1 = 0
+ let movedCount1 = 0
- var pressedSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "pressedChanged"})
+ let pressedSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "pressedChanged"})
verify(pressedSpy1.valid)
- var positionSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "positionChanged"})
+ let positionSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "positionChanged"})
verify(positionSpy1.valid)
- var touch = touchEvent(control1)
+ let touch = touchEvent(control1)
touch.press(0, control1, grooveRange.start.x, grooveRange.start.y).commit().move(0, control1, grooveRange.end.x+1, grooveRange.end.y+1).commit()
compare(pressedSpy1.count, ++pressedCount1)
@@ -394,17 +398,17 @@ TestCase {
compare(control1.pressed, true)
compare(control1.position, 1.0)
- var control2 = createTemporaryObject(scrollBar, testCase, {y: control1.height})
+ let control2 = createTemporaryObject(scrollBar, testCase, {y: control1.height})
verify(control2)
control2.height = 200 + (control2.topPadding + control2.bottomPadding)
- var pressedCount2 = 0
- var movedCount2 = 0
+ let pressedCount2 = 0
+ let movedCount2 = 0
- var pressedSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "pressedChanged"})
+ let pressedSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "pressedChanged"})
verify(pressedSpy2.valid)
- var positionSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "positionChanged"})
+ let positionSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "positionChanged"})
verify(positionSpy2.valid)
// press the second scrollbar
@@ -457,7 +461,7 @@ TestCase {
}
function test_increase_decrease(data) {
- var control = createTemporaryObject(scrollBar, testCase, {position: 0.5, active: data.active})
+ let control = createTemporaryObject(scrollBar, testCase, {position: 0.5, active: data.active})
verify(control)
if (data.increase) {
@@ -479,18 +483,18 @@ TestCase {
}
function test_stepSize(data) {
- var control = createTemporaryObject(scrollBar, testCase, {stepSize: data.stepSize})
+ let control = createTemporaryObject(scrollBar, testCase, {stepSize: data.stepSize})
verify(control)
compare(control.stepSize, data.stepSize)
compare(control.position, 0.0)
- var count = 10
+ let count = 10
if (data.stepSize !== 0.0)
count = 1.0 / data.stepSize
// increase until 1.0
- for (var i = 1; i <= count; ++i) {
+ for (let i = 1; i <= count; ++i) {
control.increase()
compare(control.position, i / count)
}
@@ -498,7 +502,7 @@ TestCase {
compare(control.position, 1.0)
// decrease until 0.0
- for (var d = count - 1; d >= 0; --d) {
+ for (let d = count - 1; d >= 0; --d) {
control.decrease()
compare(control.position, d / count)
}
@@ -514,7 +518,7 @@ TestCase {
}
function test_padding(data) {
- var control = createTemporaryObject(scrollBar, testCase, data.properties)
+ let control = createTemporaryObject(scrollBar, testCase, data.properties)
mousePress(control, control.leftPadding + control.availableWidth * 0.5, control.topPadding + control.availableHeight * 0.5, Qt.LeftButton)
mouseRelease(control, control.leftPadding + control.availableWidth * 0.5, control.topPadding + control.availableHeight * 0.5, Qt.LeftButton)
@@ -528,7 +532,7 @@ TestCase {
}
function test_mirrored() {
- var container = createTemporaryObject(flickable, testCase)
+ let container = createTemporaryObject(flickable, testCase)
verify(container)
waitForRendering(container)
@@ -547,7 +551,7 @@ TestCase {
}
function test_hover(data) {
- var control = createTemporaryObject(scrollBar, testCase, {hoverEnabled: data.hoverEnabled, interactive: data.interactive})
+ let control = createTemporaryObject(scrollBar, testCase, {hoverEnabled: data.hoverEnabled, interactive: data.interactive})
verify(control)
compare(control.hovered, false)
@@ -579,14 +583,14 @@ TestCase {
}
function test_snapMode_mouse(data) {
- var control = createTemporaryObject(scrollBar, testCase, {snapMode: data.snapMode, orientation: Qt.Horizontal, stepSize: data.stepSize, size: data.size, width: data.width})
+ let control = createTemporaryObject(scrollBar, testCase, {snapMode: data.snapMode, orientation: Qt.Horizontal, stepSize: data.stepSize, size: data.size, width: data.width})
verify(control)
// In case the slider is surrounded with decrease/increase buttons
// Adjust slider width so that slider area is a whole number (to avoid rounding errors)
control.width += control.leftPadding + control.rightPadding
function snappedPosition(pos) {
- var effectiveStep = control.stepSize * (1.0 - control.size)
+ let effectiveStep = control.stepSize * (1.0 - control.size)
return Math.round(pos / effectiveStep) * effectiveStep
}
@@ -594,14 +598,14 @@ TestCase {
return Math.max(0, Math.min(pos, 1.0 - control.size))
}
- var minHandlePos = control.leftPadding
- var maxHandlePos = control.width - control.rightPadding
- var availableSlideWidth = maxHandlePos - minHandlePos
+ let minHandlePos = control.leftPadding
+ let maxHandlePos = control.width - control.rightPadding
+ let availableSlideWidth = maxHandlePos - minHandlePos
mousePress(control, minHandlePos, 0)
compare(control.position, 0)
mouseMove(control, minHandlePos + availableSlideWidth * 0.3, 0)
- var expectedMovePos = 0.3
+ let expectedMovePos = 0.3
if (control.snapMode === ScrollBar.SnapAlways) {
expectedMovePos = snappedPosition(expectedMovePos)
verify(expectedMovePos !== 0.3)
@@ -609,7 +613,7 @@ TestCase {
compare(control.position, expectedMovePos)
mouseRelease(control, minHandlePos + availableSlideWidth * 0.75, 0)
- var expectedReleasePos = 0.75
+ let expectedReleasePos = 0.75
if (control.snapMode !== ScrollBar.NoSnap) {
expectedReleasePos = snappedPosition(expectedReleasePos)
verify(expectedReleasePos !== 0.75)
@@ -619,10 +623,10 @@ TestCase {
control.position = 0
mousePress(control, minHandlePos, 0)
- var steps = 0
- var prevPos = 0
+ let steps = 0
+ let prevPos = 0
- for (var x = minHandlePos; x < maxHandlePos; ++x) {
+ for (let x = minHandlePos; x < maxHandlePos; ++x) {
mouseMove(control, x, 0)
expectedMovePos = boundPosition((x - minHandlePos) / availableSlideWidth)
if (control.snapMode === ScrollBar.SnapAlways)
@@ -643,14 +647,14 @@ TestCase {
}
function test_snapMode_touch(data) {
- var control = createTemporaryObject(scrollBar, testCase, {snapMode: data.snapMode, orientation: Qt.Horizontal, stepSize: data.stepSize, size: data.size, width: data.width})
+ let control = createTemporaryObject(scrollBar, testCase, {snapMode: data.snapMode, orientation: Qt.Horizontal, stepSize: data.stepSize, size: data.size, width: data.width})
verify(control)
// In case the slider is surrounded with decrease/increase buttons
// Adjust slider width so that slider area is a whole number (to avoid rounding errors)
control.width += control.leftPadding + control.rightPadding
function snappedPosition(pos) {
- var effectiveStep = control.stepSize * (1.0 - control.size)
+ let effectiveStep = control.stepSize * (1.0 - control.size)
return Math.round(pos / effectiveStep) * effectiveStep
}
@@ -658,16 +662,16 @@ TestCase {
return Math.max(0, Math.min(pos, 1.0 - control.size))
}
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
- var minHandlePos = control.leftPadding
- var maxHandlePos = control.width - control.rightPadding
- var availableSlideWidth = maxHandlePos - minHandlePos
+ let minHandlePos = control.leftPadding
+ let maxHandlePos = control.width - control.rightPadding
+ let availableSlideWidth = maxHandlePos - minHandlePos
touch.press(0, control, minHandlePos, 0).commit()
compare(control.position, 0)
touch.move(0, control, minHandlePos + availableSlideWidth*0.3, 0).commit()
- var expectedMovePos = 0.3
+ let expectedMovePos = 0.3
if (control.snapMode === ScrollBar.SnapAlways) {
expectedMovePos = snappedPosition(expectedMovePos)
verify(expectedMovePos !== 0.3)
@@ -675,7 +679,7 @@ TestCase {
compare(control.position, expectedMovePos)
touch.release(0, control, minHandlePos + availableSlideWidth*0.75, 0).commit()
- var expectedReleasePos = 0.75
+ let expectedReleasePos = 0.75
if (control.snapMode !== ScrollBar.NoSnap) {
expectedReleasePos = snappedPosition(expectedReleasePos)
verify(expectedReleasePos !== 0.75)
@@ -685,10 +689,10 @@ TestCase {
control.position = 0
touch.press(0, control, minHandlePos, 0).commit()
- var steps = 0
- var prevPos = 0
+ let steps = 0
+ let prevPos = 0
- for (var x = minHandlePos; x < maxHandlePos; ++x) {
+ for (let x = minHandlePos; x < maxHandlePos; ++x) {
touch.move(0, control, x, 0).commit()
expectedMovePos = boundPosition((x - minHandlePos) / availableSlideWidth)
if (control.snapMode === ScrollBar.SnapAlways)
@@ -712,7 +716,7 @@ TestCase {
}
function test_interactive(data) {
- var control = createTemporaryObject(scrollBar, testCase, {interactive: data.interactive})
+ let control = createTemporaryObject(scrollBar, testCase, {interactive: data.interactive})
verify(control)
compare(control.interactive, data.interactive)
@@ -759,7 +763,7 @@ TestCase {
}
function test_policy() {
- var control = createTemporaryObject(scrollBar, testCase, {active: true})
+ let control = createTemporaryObject(scrollBar, testCase, {active: true})
verify(control)
compare(ScrollBar.AsNeeded, Qt.ScrollBarAsNeeded)
@@ -769,8 +773,8 @@ TestCase {
compare(control.visible, true)
compare(control.policy, ScrollBar.AsNeeded)
- var windowsStyle = false
- var macOSStyle = false
+ let windowsStyle = false
+ let macOSStyle = false
if (control.background instanceof NativeStyle.StyleItem) {
windowsStyle = Qt.platform.pluginName === "windows"
macOSStyle = Qt.platform.pluginName === "cocoa"
@@ -794,14 +798,14 @@ TestCase {
}
function test_overshoot() {
- var container = createTemporaryObject(flickable, testCase)
+ let container = createTemporaryObject(flickable, testCase)
verify(container)
waitForRendering(container)
- var vertical = scrollBar.createObject(container, {size: 0.5})
+ let vertical = scrollBar.createObject(container, {size: 0.5})
container.ScrollBar.vertical = vertical
- var horizontal = scrollBar.createObject(container, {size: 0.5})
+ let horizontal = scrollBar.createObject(container, {size: 0.5})
container.ScrollBar.horizontal = horizontal
// negative vertical overshoot (pos < 0)
@@ -826,7 +830,7 @@ TestCase {
}
function test_orientation() {
- var control = createTemporaryObject(scrollBar, testCase)
+ let control = createTemporaryObject(scrollBar, testCase)
verify(control)
compare(control.orientation, Qt.Vertical)
@@ -840,10 +844,10 @@ TestCase {
}
function test_flashing() {
- var control = createTemporaryObject(scrollBar, testCase, {size: 0.2})
+ let control = createTemporaryObject(scrollBar, testCase, {size: 0.2})
verify(control)
- var activeSpy = signalSpy.createObject(control, {target: control, signalName: "activeChanged"})
+ let activeSpy = signalSpy.createObject(control, {target: control, signalName: "activeChanged"})
verify(activeSpy.valid)
compare(control.active, false)
@@ -884,11 +888,11 @@ TestCase {
}
function test_minimumSize() {
- var container = createTemporaryObject(flickable, testCase)
+ let container = createTemporaryObject(flickable, testCase)
verify(container)
waitForRendering(container)
- var vertical = scrollBar.createObject(container, {minimumSize: 0.1})
+ let vertical = scrollBar.createObject(container, {minimumSize: 0.1})
container.ScrollBar.vertical = vertical
compare(container.visibleArea.heightRatio, 0.5)
@@ -932,7 +936,7 @@ TestCase {
}
function test_resize() {
- var vertical = createTemporaryObject(scrollBar, testCase, { height:200, orientation: Qt.Vertical, size: 0.5, position: 0.5 })
+ let vertical = createTemporaryObject(scrollBar, testCase, { height:200, orientation: Qt.Vertical, size: 0.5, position: 0.5 })
verify(vertical)
vertical.size = 0.8
@@ -943,7 +947,7 @@ TestCase {
compare(vertical.visualPosition, 0.2)
- var horizontal = createTemporaryObject(scrollBar, testCase, { width:200, orientation: Qt.Horizontal, size: 0.5, position: 0.5 })
+ let horizontal = createTemporaryObject(scrollBar, testCase, { width:200, orientation: Qt.Horizontal, size: 0.5, position: 0.5 })
verify(horizontal)
horizontal.size = 0.8
@@ -955,7 +959,7 @@ TestCase {
}
function test_setting_invalid_property_values() {
- var control = createTemporaryObject(scrollBar, testCase, {size: 2.0, minimumSize: -1.0})
+ let control = createTemporaryObject(scrollBar, testCase, {size: 2.0, minimumSize: -1.0})
verify(control)
// check that the values are within the expected range
@@ -987,4 +991,19 @@ TestCase {
compare(oldPosition, control.position)
compare(oldStepSize, control.stepSize)
}
+
+ function test_visualSizeChanged_is_emitted_by_setSize() {
+ const control = createTemporaryObject(scrollBar, testCase, {size: 0.2})
+ verify(control)
+
+ const spy = signalSpy.createObject(control, {target: control, signalName: "visualSizeChanged"})
+ verify(spy.valid)
+
+ compare(control.visualSize, 0.2)
+
+ control.size = 0.5
+
+ compare(spy.count, 1)
+ compare(control.visualSize, 0.5)
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_scrollindicator.qml b/tests/auto/quickcontrols/controls/data/tst_scrollindicator.qml
index d87e29f980..74713f930c 100644
--- a/tests/auto/quickcontrols/controls/data/tst_scrollindicator.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_scrollindicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -35,19 +35,21 @@ TestCase {
}
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(scrollIndicator, testCase)
verify(control)
}
function test_attach() {
- var container = createTemporaryObject(flickable, testCase)
+ let container = createTemporaryObject(flickable, testCase)
verify(container)
waitForRendering(container)
- var vertical = createTemporaryObject(scrollIndicator, null)
+ let vertical = createTemporaryObject(scrollIndicator, null)
verify(!vertical.parent)
compare(vertical.size, 0.0)
compare(vertical.position, 0.0)
@@ -77,7 +79,7 @@ TestCase {
container.width += 10
compare(vertical.x, 123)
- var horizontal = createTemporaryObject(scrollIndicator, null)
+ let horizontal = createTemporaryObject(scrollIndicator, null)
verify(!horizontal.parent)
compare(horizontal.size, 0.0)
compare(horizontal.position, 0.0)
@@ -107,7 +109,7 @@ TestCase {
container.height += 10
compare(horizontal.y, 123)
- var velocity = container.maximumFlickVelocity
+ let velocity = container.maximumFlickVelocity
compare(container.flicking, false)
container.flick(-velocity, -velocity)
@@ -129,16 +131,16 @@ TestCase {
compare(horizontal.size, container.visibleArea.widthRatio)
compare(horizontal.position, container.visibleArea.xPosition)
- var oldY = vertical.y
- var oldHeight = vertical.height
+ let oldY = vertical.y
+ let oldHeight = vertical.height
vertical.parent = testCase
vertical.y -= 10
container.height += 10
compare(vertical.y, oldY - 10)
compare(vertical.height, oldHeight)
- var oldX = horizontal.x
- var oldWidth = horizontal.width
+ let oldX = horizontal.x
+ let oldWidth = horizontal.width
horizontal.parent = testCase
horizontal.x -= 10
container.width += 10
@@ -152,14 +154,14 @@ TestCase {
}
function test_overshoot() {
- var container = createTemporaryObject(flickable, testCase)
+ let container = createTemporaryObject(flickable, testCase)
verify(container)
waitForRendering(container)
- var vertical = scrollIndicator.createObject(container, {size: 0.5})
+ let vertical = scrollIndicator.createObject(container, {size: 0.5})
container.ScrollIndicator.vertical = vertical
- var horizontal = scrollIndicator.createObject(container, {size: 0.5})
+ let horizontal = scrollIndicator.createObject(container, {size: 0.5})
container.ScrollIndicator.horizontal = horizontal
// negative vertical overshoot (pos < 0)
@@ -184,7 +186,7 @@ TestCase {
}
function test_orientation() {
- var control = createTemporaryObject(scrollIndicator, testCase)
+ let control = createTemporaryObject(scrollIndicator, testCase)
verify(control)
compare(control.orientation, Qt.Vertical)
@@ -199,10 +201,10 @@ TestCase {
// QTBUG-61785
function test_mouseArea() {
- var ma = createTemporaryObject(mouseArea, testCase, {width: testCase.width, height: testCase.height})
+ let ma = createTemporaryObject(mouseArea, testCase, {width: testCase.width, height: testCase.height})
verify(ma)
- var control = scrollIndicator.createObject(ma, {active: true, size: 0.9, width: testCase.width, height: testCase.height})
+ let control = scrollIndicator.createObject(ma, {active: true, size: 0.9, width: testCase.width, height: testCase.height})
verify(control)
mousePress(control)
@@ -211,7 +213,7 @@ TestCase {
mouseRelease(control)
verify(!ma.pressed)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
touch.press(0, control).commit()
verify(ma.pressed)
@@ -220,11 +222,11 @@ TestCase {
}
function test_minimumSize() {
- var container = createTemporaryObject(flickable, testCase)
+ let container = createTemporaryObject(flickable, testCase)
verify(container)
waitForRendering(container)
- var vertical = scrollIndicator.createObject(container, {minimumSize: 0.1})
+ let vertical = scrollIndicator.createObject(container, {minimumSize: 0.1})
container.ScrollIndicator.vertical = vertical
compare(container.visibleArea.heightRatio, 0.5)
@@ -268,7 +270,7 @@ TestCase {
}
function test_resize() {
- var vertical = createTemporaryObject(scrollIndicator, testCase, { height:200, orientation: Qt.Vertical, size: 0.5, position: 0.5 })
+ let vertical = createTemporaryObject(scrollIndicator, testCase, { height:200, orientation: Qt.Vertical, size: 0.5, position: 0.5 })
verify(vertical)
vertical.size = 0.8
@@ -279,7 +281,7 @@ TestCase {
compare(vertical.visualPosition, 0.2)
- var horizontal = createTemporaryObject(scrollIndicator, testCase, { width:200, orientation: Qt.Horizontal, size: 0.5, position: 0.5 })
+ let horizontal = createTemporaryObject(scrollIndicator, testCase, { width:200, orientation: Qt.Horizontal, size: 0.5, position: 0.5 })
verify(horizontal)
horizontal.size = 0.8
diff --git a/tests/auto/quickcontrols/controls/data/tst_scrollview.qml b/tests/auto/quickcontrols/controls/data/tst_scrollview.qml
index e5600830a8..622f341f78 100644
--- a/tests/auto/quickcontrols/controls/data/tst_scrollview.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_scrollview.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -146,6 +146,7 @@ TestCase {
}
}
}
+
Component {
id: scrollableTextAreaWithSibling
ScrollView {
@@ -156,21 +157,23 @@ TestCase {
}
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(scrollView, testCase)
verify(control)
}
function test_scrollBars() {
- var control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200})
+ let control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200})
verify(control)
- var vertical = control.ScrollBar.vertical
+ let vertical = control.ScrollBar.vertical
verify(vertical)
- var horizontal = control.ScrollBar.horizontal
+ let horizontal = control.ScrollBar.horizontal
verify(horizontal)
control.contentHeight = 400
@@ -188,6 +191,18 @@ TestCase {
horizontal.increase()
verify(horizontal.position > 0)
compare(control.contentItem.visibleArea.xPosition, horizontal.position)
+
+ vertical.policy = ScrollBar.AlwaysOn
+ horizontal.policy = ScrollBar.AlwaysOn
+
+ verify(control.effectiveScrollBarWidth > 0)
+ verify(control.effectiveScrollBarHeight > 0)
+
+ vertical.policy = ScrollBar.AlwaysOff
+ horizontal.policy = ScrollBar.AlwaysOff
+
+ compare(control.effectiveScrollBarWidth, 0)
+ compare(control.effectiveScrollBarHeight, 0)
}
function test_oneChild_data() {
@@ -198,14 +213,14 @@ TestCase {
}
function test_oneChild(data) {
- var control = createTemporaryObject(data.component, testCase)
+ let control = createTemporaryObject(data.component, testCase)
verify(control)
- var flickable = control.contentItem
+ let flickable = control.contentItem
verify(flickable.hasOwnProperty("contentX"))
verify(flickable.hasOwnProperty("contentY"))
- var label = flickable.contentItem.children[0]
+ let label = flickable.contentItem.children[0]
compare(label.text, "ABC")
compare(control.implicitWidth, label.implicitWidth)
@@ -229,34 +244,34 @@ TestCase {
}
function test_multipleChildren() {
- var control = createTemporaryObject(scrollableLabels, testCase)
+ let control = createTemporaryObject(scrollableLabels, testCase)
verify(control)
- var flickable = control.contentItem
+ let flickable = control.contentItem
verify(flickable.hasOwnProperty("contentX"))
verify(flickable.hasOwnProperty("contentY"))
compare(control.contentChildren, flickable.contentItem.children)
- var label1 = control.contentChildren[0]
+ let label1 = control.contentChildren[0]
compare(label1.text, "First")
- var label2 = control.contentChildren[1]
+ let label2 = control.contentChildren[1]
compare(label2.text, "Second")
- var label3 = control.contentChildren[2]
+ let label3 = control.contentChildren[2]
compare(label3.text, "Third")
- var expectedContentHeight = label1.implicitHeight + label2.implicitHeight + label3.implicitHeight
+ let expectedContentHeight = label1.implicitHeight + label2.implicitHeight + label3.implicitHeight
compare(control.contentHeight, expectedContentHeight)
compare(flickable.contentHeight, expectedContentHeight)
}
function test_listView() {
- var control = createTemporaryObject(scrollableListView, testCase)
+ let control = createTemporaryObject(scrollableListView, testCase)
verify(control)
- var listview = control.contentItem
+ let listview = control.contentItem
verify(listview.hasOwnProperty("contentX"))
verify(listview.hasOwnProperty("contentY"))
verify(listview.hasOwnProperty("model"))
@@ -272,10 +287,10 @@ TestCase {
// children, even if the flickable has an empty or negative content
// size. Some flickables (e.g ListView) sets a negative
// contentWidth on purpose, which should be respected.
- var scrollview = createTemporaryObject(scrollableFlickable, testCase)
+ let scrollview = createTemporaryObject(scrollableFlickable, testCase)
verify(scrollview)
- var flickable = scrollview.contentItem
+ let flickable = scrollview.contentItem
verify(flickable.hasOwnProperty("contentX"))
verify(flickable.hasOwnProperty("contentY"))
@@ -290,10 +305,10 @@ TestCase {
// not the flickable, then those values will be forwarded and used
// by the flickable (rather than trying to calculate the content size
// based on the flickables children).
- var scrollview = createTemporaryObject(scrollableWithContentSize, testCase)
+ let scrollview = createTemporaryObject(scrollableWithContentSize, testCase)
verify(scrollview)
- var flickable = scrollview.contentItem
+ let flickable = scrollview.contentItem
verify(flickable.hasOwnProperty("contentX"))
verify(flickable.hasOwnProperty("contentY"))
@@ -307,10 +322,10 @@ TestCase {
// Check that if both the scrollview and the flickable has
// contentWidth/Height set (which is an inconsistency/fault
// by the app), the content size of the scrollview wins.
- var scrollview = createTemporaryObject(scrollableAndFlicableWithContentSize, testCase)
+ let scrollview = createTemporaryObject(scrollableAndFlicableWithContentSize, testCase)
verify(scrollview)
- var flickable = scrollview.contentItem
+ let flickable = scrollview.contentItem
verify(flickable.hasOwnProperty("contentX"))
verify(flickable.hasOwnProperty("contentY"))
@@ -321,14 +336,14 @@ TestCase {
}
function test_flickableWithExplicitContentSize() {
- var control = createTemporaryObject(emptyFlickable, testCase)
+ let control = createTemporaryObject(emptyFlickable, testCase)
verify(control)
- var flickable = control.contentItem
+ let flickable = control.contentItem
verify(flickable.hasOwnProperty("contentX"))
verify(flickable.hasOwnProperty("contentY"))
- var flickableContentSize = 1000;
+ let flickableContentSize = 1000;
flickable.contentWidth = flickableContentSize;
flickable.contentHeight = flickableContentSize;
@@ -354,13 +369,13 @@ TestCase {
}
function test_mouse() {
- var control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentHeight: 400})
+ let control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentHeight: 400})
verify(control)
mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton)
compare(control.contentItem.contentY, 0)
- for (var y = control.height / 2; y >= 0; --y) {
+ for (let y = control.height / 2; y >= 0; --y) {
mouseMove(control, control.width / 2, y, 10)
compare(control.contentItem.contentY, 0)
}
@@ -370,10 +385,10 @@ TestCase {
}
function test_hover() {
- var control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentHeight: 400})
+ let control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentHeight: 400})
verify(control)
- var vertical = control.ScrollBar.vertical
+ let vertical = control.ScrollBar.vertical
verify(vertical)
vertical.hoverEnabled = true
@@ -385,10 +400,10 @@ TestCase {
}
function test_wheel() {
- var control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentHeight: 400})
+ let control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentHeight: 400})
verify(control)
- var vertical = control.ScrollBar.vertical
+ let vertical = control.ScrollBar.vertical
verify(vertical)
mouseWheel(control, control.width / 2, control.height / 2, 0, -120)
@@ -398,21 +413,21 @@ TestCase {
}
function test_touch() {
- var control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentHeight: 400})
+ let control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentHeight: 400})
verify(control)
- var vertical = control.ScrollBar.vertical
+ let vertical = control.ScrollBar.vertical
verify(vertical)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
touch.press(0, control, control.width / 2, control.height / 2).commit()
compare(control.contentItem.contentY, 0)
compare(vertical.active, false)
compare(vertical.interactive, false)
- var maxContentY = 0
- for (var y = control.height / 2; y >= 0; --y) {
+ let maxContentY = 0
+ for (let y = control.height / 2; y >= 0; --y) {
touch.move(0, control, control.width / 2, y).commit()
maxContentY = Math.max(maxContentY, control.contentItem.contentY)
}
@@ -425,7 +440,7 @@ TestCase {
}
function test_keys() {
- var control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentWidth: 400, contentHeight: 400})
+ let control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentWidth: 400, contentHeight: 400})
verify(control)
// If the viewport is smaller than the size of the ScrollView
// (like windows style does due to its opaque scrollbars),
@@ -436,31 +451,31 @@ TestCase {
control.forceActiveFocus()
verify(control.activeFocus)
- var vertical = control.ScrollBar.vertical
+ let vertical = control.ScrollBar.vertical
verify(vertical)
compare(vertical.position, 0.0)
- for (var i = 1; i <= 10; ++i) {
+ for (let i = 1; i <= 10; ++i) {
keyClick(Qt.Key_Down)
compare(vertical.position, Math.min(0.5, i * 0.1))
}
compare(vertical.position, 0.5)
- for (i = 1; i <= 10; ++i) {
+ for (let i = 1; i <= 10; ++i) {
keyClick(Qt.Key_Up)
compare(vertical.position, Math.max(0.0, 0.5 - i * 0.1))
}
compare(vertical.position, 0.0)
- var horizontal = control.ScrollBar.horizontal
+ let horizontal = control.ScrollBar.horizontal
verify(horizontal)
compare(horizontal.position, 0.0)
- for (i = 1; i <= 10; ++i) {
+ for (let i = 1; i <= 10; ++i) {
keyClick(Qt.Key_Right)
compare(horizontal.position, Math.min(0.5, i * 0.1))
}
compare(horizontal.position, 0.5)
- for (i = 1; i <= 10; ++i) {
+ for (let i = 1; i <= 10; ++i) {
keyClick(Qt.Key_Left)
compare(horizontal.position, Math.max(0.0, 0.5 - i * 0.1))
}
@@ -469,22 +484,49 @@ TestCase {
function test_textArea() {
// TODO: verify no binding loop warnings (QTBUG-62325)
- var control = createTemporaryObject(scrollableTextArea, testCase)
+ let control = createTemporaryObject(scrollableTextArea, testCase)
verify(control)
- var flickable = control.contentItem
+ let flickable = control.contentItem
verify(flickable && flickable.hasOwnProperty("contentX"))
- var textArea = flickable.contentItem.children[0]
+ let textArea = flickable.contentItem.children[0]
verify(textArea && textArea.hasOwnProperty("text"))
compare(control.contentWidth, flickable.contentWidth)
compare(control.contentHeight, flickable.contentHeight)
}
+ Component {
+ id: scrollableTextAreaWithPadding
+
+ ScrollView {
+ TextArea {
+ text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas id dignissim ipsum. Nam molestie nisl turpis."
+ wrapMode: TextArea.WordWrap
+ leftPadding: 1
+ topPadding: 1
+ }
+ }
+ }
+
+ function test_textAreaWithPadding() {
+ let control = createTemporaryObject(scrollableTextAreaWithPadding, testCase)
+ verify(control)
+
+ let flickable = control.contentItem
+ verify(flickable)
+
+ let textArea = flickable.contentItem.children[0]
+ verify(textArea)
+
+ compare(control.contentWidth, flickable.contentWidth)
+ compare(control.contentHeight, flickable.contentHeight)
+ }
+
function test_textAreaWithSibling() {
// Checks that it does not crash when the ScrollView is deleted
- var control = createTemporaryObject(scrollableTextAreaWithSibling, testCase)
+ let control = createTemporaryObject(scrollableTextAreaWithSibling, testCase)
verify(control)
}
@@ -590,6 +632,7 @@ TestCase {
id: bindingToContentItemAndStandaloneFlickable
Item {
+ objectName: "container"
width: 200
height: 200
@@ -628,7 +671,7 @@ TestCase {
verify(verticalScrollBar.visible)
verify(horizontalScrollBar.visible)
- mouseDrag(verticalScrollBar, verticalScrollBar.width / 2, verticalScrollBar.height / 2, 0, 50)
+ mouseWheel(control, control.width / 2, control.height / 2, 0, -120)
verify(verticalScrollBar.active)
verify(horizontalScrollBar.active)
}
@@ -637,6 +680,7 @@ TestCase {
id: contentItemAssignedImperatively
Item {
+ objectName: "container"
width: 100
height: 100
@@ -644,6 +688,7 @@ TestCase {
ListView {
id: listView
+ objectName: "customListView"
model: 20
delegate: Text {
text: modelData
@@ -662,11 +707,59 @@ TestCase {
}
// Tests that a ListView declared before the ScrollView (as the QObject destruction order
- // is relevant for the bug) and assigned imperatively to ScrollView does not cause a crash
- // on exit.
+ // is relevant for the bug) and assigned imperatively to ScrollView does not cause:
+ // - a crash on exit
+ // - scroll bars that should be hidden to be visible
function test_contentItemAssignedImperatively() {
let root = createTemporaryObject(contentItemAssignedImperatively, testCase)
verify(root)
+
+ let control = root.scrollView
+ let flickable = control.contentItem
+ compare(flickable.parent, control)
+
+ let horizontalScrollBar = control.ScrollBar.horizontal
+ let verticalScrollBar = control.ScrollBar.vertical
+ // The horizontal ScrollBar's policy is set to AlwaysOff, so it shouldn't ever be visible.
+ verify(!horizontalScrollBar.visible)
+ // The vertical ScrollBar should be visible...
+ verify(verticalScrollBar.visible)
+
+ // ... and it should become active when the ScrollView is scrolled.
+ mouseWheel(control, control.width / 2, control.height / 2, 0, -120)
+ verify(verticalScrollBar.active)
+
// Shouldn't crash.
}
+
+ Component {
+ id: scrollViewContentItemComp
+
+ ScrollView {
+ id: scrollView
+ anchors.fill: parent
+ Column {
+ width: parent.width
+ Repeater {
+ model: 20
+ Rectangle {
+ width: scrollView.width
+ height: 60
+ color: (index % 2 == 0) ? "red" : "green"
+ }
+ }
+ }
+ }
+ }
+
+ function test_scrollViewContentItemSize() {
+ let scrollview = createTemporaryObject(scrollViewContentItemComp, testCase)
+ verify(scrollview)
+ let contentItem = scrollview.contentItem
+ waitForRendering(contentItem)
+ compare(contentItem.contentWidth, 400)
+ compare(contentItem.contentHeight, 1200)
+ compare(scrollview.contentWidth, 400)
+ compare(scrollview.contentHeight, 1200)
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml b/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml
index dd4f984aa2..79a51bd4c3 100644
--- a/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -73,6 +73,22 @@ TestCase {
}
Component {
+ id: delegateWithTapHandlerComp
+ Rectangle {
+ implicitWidth: 100
+ implicitHeight: 50
+ color: selected ? "lightblue" : "transparent"
+ border.width: 1
+ required property bool selected
+
+ TapHandler {
+ // This tap handler will block the tap handler in
+ // QQuickTableView from being called.
+ }
+ }
+ }
+
+ Component {
id: tableviewComp
TableView {
id: tableView
@@ -129,13 +145,55 @@ TestCase {
}
Component {
+ id: headerviewComp
+ HorizontalHeaderView {
+ id: headerView
+ clip: true
+ anchors.fill: parent
+
+ model: TableModel {
+ TableModelColumn { display: "c1" }
+ TableModelColumn { display: "c2" }
+ TableModelColumn { display: "c3" }
+ TableModelColumn { display: "c4" }
+ TableModelColumn { display: "c5" }
+ TableModelColumn { display: "c6" }
+ TableModelColumn { display: "c7" }
+ TableModelColumn { display: "c8" }
+ rows: [
+ { "c1": "v1", "c2":"v2", "c3":"v3", "c4": "v4", "c5": "v5", "c6":"v6", "c7":"v7", "c8": "v8" }
+ ]
+ }
+
+ delegate: Rectangle {
+ required property bool selected
+ implicitWidth: cellWidth
+ implicitHeight: cellHeight
+ color: selected ? "lightblue" : "gray"
+ Text { text: row + "," + column }
+ }
+
+ selectionModel: ItemSelectionModel { }
+
+ property alias selectionRectangle: selectionRectangle
+ SelectionRectangle {
+ id: selectionRectangle
+ target: headerView
+ }
+ }
+
+ }
+
+ Component {
id: signalSpy
SignalSpy { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(defaultSelectionRectangle, testCase)
verify(control)
}
@@ -195,13 +253,15 @@ TestCase {
function test_drag_data() {
return [
- { tag: "resize enabled", resizeEnabled: true },
- { tag: "resize disabled", resizeEnabled: false },
+ { tag: "resize enabled (tableview)", resizeEnabled: true, viewComp: tableviewComp },
+ { tag: "resize disabled (tableview)", resizeEnabled: false, viewComp: tableviewComp },
+ { tag: "resize enabled (headerview)", resizeEnabled: true, viewComp: headerviewComp },
+ { tag: "resize disabled (headerview)", resizeEnabled: false, viewComp: headerviewComp },
]
}
function test_drag(data) {
- let tableView = createTemporaryObject(tableviewComp, testCase)
+ let tableView = createTemporaryObject(data.viewComp, testCase)
verify(tableView)
let selectionRectangle = tableView.selectionRectangle
verify(selectionRectangle)
@@ -222,8 +282,8 @@ TestCase {
mouseDrag(tableView, 1, 1, (cellWidth * 2) - 2, 1, Qt.LeftButton)
verify(tableView.selectionModel.hasSelection)
compare(tableView.selectionModel.selectedIndexes.length, 2)
- verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
- verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1)))
+ verify(tableView.selectionModel.isSelected(tableView.selectionModel.model.index(0, 0)))
+ verify(tableView.selectionModel.isSelected(tableView.selectionModel.model.index(0, 1)))
compare(activeSpy.count, 1)
compare(draggingSpy.count, 2)
@@ -236,8 +296,218 @@ TestCase {
// Ensure that a press and hold doesn't start a selection
mousePress(tableView, 1, 1, Qt.LeftButton)
- mousePress(tableView, 1, 1, Qt.LeftButton, Qt.NoModifier, 1000)
+ mouseRelease(tableView, 1, 1, Qt.LeftButton, Qt.NoModifier, 1000)
+ verify(!tableView.selectionModel.hasSelection)
+ }
+
+ function test_tableView_singleSelection_data() {
+ return [
+ { viewComp: tableviewComp },
+ { viewComp: headerviewComp },
+ ]
+ }
+
+ function test_tableView_singleSelection(data) {
+ let tableView = createTemporaryObject(data.viewComp, testCase)
+ verify(tableView)
+ let selectionRectangle = tableView.selectionRectangle
+ verify(selectionRectangle)
+
+ selectionRectangle.selectionMode = SelectionRectangle.Drag
+ tableView.selectionMode = TableView.SingleSelection
+
+ // Try to select two cells by dragging. Only one cell should be selected.
verify(!tableView.selectionModel.hasSelection)
+ mouseDrag(tableView, 1, 1, (cellWidth * 2) - 2, 1, Qt.LeftButton)
+ verify(tableView.selectionModel.hasSelection)
+ compare(tableView.selectionModel.selectedIndexes.length, 1)
+ verify(tableView.selectionModel.isSelected(tableView.selectionModel.model.index(0, 0)))
+
+ // A control click should clear the current selection and select a new cell
+ mouseClick(tableView, (cellWidth * 2) - 1, 1, Qt.LeftButton, Qt.ControlModifier)
+ compare(tableView.selectionModel.selectedIndexes.length, 1)
+ verify(tableView.selectionModel.isSelected(tableView.selectionModel.model.index(0, 1)))
+
+ // A shift click is a no-op, and doesn't change the current selection
+ mouseClick(tableView, 1, 1, Qt.LeftButton, Qt.ShiftModifier)
+ compare(tableView.selectionModel.selectedIndexes.length, 1)
+ verify(tableView.selectionModel.isSelected(tableView.selectionModel.model.index(0, 1)))
+ }
+
+ function test_tableView_contiguousSelection_data() {
+ return [
+ { startFromCurrentIndex: false },
+ { startFromCurrentIndex: true },
+ ]
+ }
+
+ function test_tableView_contiguousSelection(data) {
+ let tableView = createTemporaryObject(tableviewComp, testCase)
+ verify(tableView)
+ let selectionRectangle = tableView.selectionRectangle
+ verify(selectionRectangle)
+
+ selectionRectangle.selectionMode = SelectionRectangle.Drag
+ tableView.selectionMode = TableView.ContiguousSelection
+
+ if (data.startFromCurrentIndex) {
+ // Click on a cell to set current index, but set no selection.
+ // A later shift-click should then start a new selection from the
+ // current cell.
+ mouseClick(tableView, 1, 1, Qt.LeftButton, Qt.NoModifier)
+ verify(!tableView.selectionModel.hasSelection)
+ compare(tableView.selectionModel.currentIndex, tableView.index(0, 0))
+ } else {
+ // Start a new selection by dragging on two cells
+ mouseDrag(tableView, 1, 1, (cellWidth * 2) - 2, 1, Qt.LeftButton)
+ verify(tableView.selectionModel.hasSelection)
+ compare(tableView.selectionModel.selectedIndexes.length, 2)
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1)))
+ }
+
+ // A shift click should extend the selection
+ mouseClick(tableView, (cellWidth * 4) - 3, 1, Qt.LeftButton, Qt.ShiftModifier)
+ compare(tableView.selectionModel.selectedIndexes.length, 4)
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 2)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 3)))
+
+ // A shift click closer to the first selected cell should shrink it again
+ mouseClick(tableView, (cellWidth * 3) - 2, 1, Qt.LeftButton, Qt.ShiftModifier)
+ compare(tableView.selectionModel.selectedIndexes.length, 3)
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 2)))
+
+ // A control click should clear the selection, and select a new cell
+ mouseClick(tableView, 1, (cellHeight * 2) - 1, Qt.LeftButton, Qt.ControlModifier)
+ compare(tableView.selectionModel.selectedIndexes.length, 1)
+ verify(tableView.selectionModel.isSelected(tableView.model.index(1, 0)))
+
+ // A control drag should clear the selection, and select new cells
+ mouseDrag(tableView, 1, 1, (cellWidth * 2) - 2, 1, Qt.LeftButton, Qt.ControlModifier)
+ verify(tableView.selectionModel.hasSelection)
+ compare(tableView.selectionModel.selectedIndexes.length, 2)
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1)))
+ }
+
+ function test_tableView_extendedSelection() {
+ let tableView = createTemporaryObject(tableviewComp, testCase)
+ verify(tableView)
+ let selectionRectangle = tableView.selectionRectangle
+ verify(selectionRectangle)
+
+ selectionRectangle.selectionMode = SelectionRectangle.Drag
+ // ExtendedSelection should be the default selection mode
+ compare(tableView.selectionMode, TableView.ExtendedSelection)
+
+ // Select two cells by dragging
+ verify(!tableView.selectionModel.hasSelection)
+ mouseDrag(tableView, 1, 1, (cellWidth * 2) - 2, 1, Qt.LeftButton)
+ verify(tableView.selectionModel.hasSelection)
+ compare(tableView.selectionModel.selectedIndexes.length, 2)
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1)))
+
+ // A shift click should extend the selection
+ mouseClick(tableView, (cellWidth * 3) - 2, 1, Qt.LeftButton, Qt.ShiftModifier)
+ compare(tableView.selectionModel.selectedIndexes.length, 3)
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 2)))
+
+ // A control click should add a new cell to the selection
+ mouseClick(tableView, 1, (cellHeight * 2) - 1, Qt.LeftButton, Qt.ControlModifier)
+ compare(tableView.selectionModel.selectedIndexes.length, 4)
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 2)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(1, 0)))
+
+ // A shift click should further extend the selection from the last cell selected
+ mouseClick(tableView, (cellWidth * 3) - 2, (cellHeight * 2) - 1, Qt.LeftButton, Qt.ShiftModifier)
+ compare(tableView.selectionModel.selectedIndexes.length, 6)
+ for (let r = 0; r < 2; ++r)
+ for (let c = 0; c < 3; ++c)
+ verify(tableView.selectionModel.isSelected(tableView.model.index(r, c)))
+
+ // Shift click the second selection so that it overlaps with the first
+ mouseClick(tableView, 1, 1, Qt.LeftButton, Qt.ShiftModifier)
+ compare(tableView.selectionModel.selectedIndexes.length, 4)
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 2)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(1, 0)))
+
+ // Shift click the selection back again. The first selection on
+ // row 0 should still be present, even if the second selection
+ // no longer overlaps it.
+ mouseClick(tableView, (cellWidth * 3) - 2, (cellHeight * 2) - 1, Qt.LeftButton, Qt.ShiftModifier)
+ compare(tableView.selectionModel.selectedIndexes.length, 6)
+ for (let r = 0; r < 2; ++r)
+ for (let c = 0; c < 3; ++c)
+ verify(tableView.selectionModel.isSelected(tableView.model.index(r, c)))
+ }
+
+ function test_unselect_click() {
+ // Check at a ctrl click on top a selected cell
+ // will cause the cell to be unselected.
+ let tableView = createTemporaryObject(tableviewComp, testCase)
+ verify(tableView)
+ let selectionRectangle = tableView.selectionRectangle
+ verify(selectionRectangle)
+
+ selectionRectangle.selectionMode = SelectionRectangle.Drag
+
+ // Select some cells
+ tableView.selectionModel.select(tableView.index(0, 0), ItemSelectionModel.Select)
+ tableView.selectionModel.select(tableView.index(0, 1), ItemSelectionModel.Select)
+ tableView.selectionModel.select(tableView.index(0, 3), ItemSelectionModel.Select)
+ tableView.selectionModel.select(tableView.index(1, 0), ItemSelectionModel.Select)
+ compare(tableView.selectionModel.selectedIndexes.length, 4)
+
+ // Do a ctrl-click on top of a selected cell. This
+ // should cause the cell to be unselected.
+ mouseClick(tableView, cellWidth / 2, cellHeight / 2, Qt.LeftButton, Qt.ControlModifier)
+ compare(tableView.selectionModel.selectedIndexes.length, 3)
+ verify(!tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 3)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(1, 0)))
+ }
+
+ function test_unselect_drag() {
+ // Check at a ctrl drag on top a selected cell
+ // will cause the dragged-over cells to be unselected.
+ let tableView = createTemporaryObject(tableviewComp, testCase)
+ verify(tableView)
+ let selectionRectangle = tableView.selectionRectangle
+ verify(selectionRectangle)
+
+ selectionRectangle.selectionMode = SelectionRectangle.Drag
+
+ // Select some cells
+ tableView.selectionModel.select(tableView.index(0, 0), ItemSelectionModel.Select)
+ tableView.selectionModel.select(tableView.index(0, 1), ItemSelectionModel.Select)
+ tableView.selectionModel.select(tableView.index(0, 3), ItemSelectionModel.Select)
+ tableView.selectionModel.select(tableView.index(1, 0), ItemSelectionModel.Select)
+ compare(tableView.selectionModel.selectedIndexes.length, 4)
+
+ // Do a ctrl-drag on top of the selected cells. This
+ // should cause all the cells to be unselected.
+ mousePress(tableView.contentItem, cellWidth / 2, cellHeight / 2, Qt.LeftButton, Qt.ControlModifier)
+ mouseMove(tableView.contentItem, cellWidth * 4, cellHeight * 2, 0, Qt.LeftButton, Qt.ControlModifier)
+ compare(tableView.selectionModel.selectedIndexes.length, 0)
+
+ // Move the mouse back to cell 2, and release the mouse. Only
+ // the top left cells will then be unselected
+ mouseMove(tableView.contentItem, (cellWidth * 2) - 1, (cellHeight * 2) - 1, 0, Qt.LeftButton, Qt.ControlModifier)
+ mouseRelease(tableView.contentItem, (cellWidth * 2) - 1, (cellHeight * 2) - 1, Qt.LeftButton, Qt.ControlModifier)
+ compare(tableView.selectionModel.selectedIndexes.length, 1)
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 3)))
}
function test_handle_position() {
@@ -320,6 +590,43 @@ TestCase {
verify(!bottomRightHandle.visible)
}
+ function test_delegateWithTapHandler() {
+ // Check that we clear the current selection if you start a new
+ // mouse drag selection on top of a delegate with a tap handler.
+ let tableView = createTemporaryObject(tableviewComp, testCase)
+ verify(tableView)
+
+ tableView.delegate = delegateWithTapHandlerComp;
+ let selectionRectangle = tableView.selectionRectangle
+ verify(selectionRectangle)
+
+ selectionRectangle.selectionMode = SelectionRectangle.Drag
+ tableView.selectionMode = TableView.ExtendedSelection
+
+ verify(waitForItemPolished(tableView))
+
+ let item0_0 = tableView.itemAtIndex(tableView.index(0, 0))
+ let item1_1 = tableView.itemAtIndex(tableView.index(1, 1))
+ verify(item0_0)
+ verify(item1_1)
+
+ tableView.selectionModel.select(tableView.index(0, 0), ItemSelectionModel.Select)
+ compare(tableView.selectionModel.selectedIndexes.length, 1)
+ compare(tableView.selectionModel.selectedIndexes[0], tableView.index(0, 0))
+
+ // A drag should clear the current selection and select a new cell
+ mouseDrag(tableView.contentItem, item1_1.x, item1_1.y, 10, 10, Qt.LeftButton)
+ compare(tableView.selectionModel.selectedIndexes.length, 1)
+ compare(tableView.selectionModel.selectedIndexes[0], tableView.index(1, 1))
+
+ // Verify that a PressAndHold works as well
+ selectionRectangle.selectionMode = SelectionRectangle.PressAndHold
+ mousePress(tableView, item0_0.x, item0_0.y, Qt.LeftButton)
+ mouseRelease(tableView, item0_0.x, item0_0.y, Qt.LeftButton, Qt.NoModifier, 2000)
+ compare(tableView.selectionModel.selectedIndexes.length, 1)
+ compare(tableView.selectionModel.selectedIndexes[0], tableView.index(0, 0))
+ }
+
// TODO: enable this test when mouseDrag sends modifiers for all mouse events
// (including mouseMove)
// function test_multi_selection() {
@@ -337,8 +644,8 @@ TestCase {
// verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
// verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1)))
-// // Hold down shift, and drag again to do a multi-selection
-// mouseDrag(tableView, 1, cellHeight + 5, (cellWidth * 2) - 2, 1, Qt.LeftButton, Qt.ShiftModifier)
+// // Hold down control, and drag again to do a multi-selection
+// mouseDrag(tableView, 1, cellHeight + 5, (cellWidth * 2) - 2, 1, Qt.LeftButton, Qt.ControlModifier)
// verify(tableView.selectionModel.hasSelection)
// compare(tableView.selectionModel.selectedIndexes.length, 4)
// verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
@@ -375,7 +682,7 @@ TestCase {
verify(!tableView.selectionModel.hasSelection)
// Do a press and hold
mousePress(tableView, 1, 1, Qt.LeftButton)
- mousePress(tableView, 1, 1, Qt.LeftButton, Qt.NoModifier, 1000)
+ mouseRelease(tableView, 1, 1, Qt.LeftButton, Qt.NoModifier, 1000)
verify(tableView.selectionModel.hasSelection)
compare(tableView.selectionModel.selectedIndexes.length, 1)
verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
@@ -384,7 +691,7 @@ TestCase {
compare(activeSpy.count, 1)
// Remove selection
- mouseClick(tableView, 1, 1, Qt.LeftButton)
+ mouseClick(tableView, 100, 100, Qt.LeftButton)
verify(!tableView.selectionModel.hasSelection)
compare(draggingSpy.count, 0)
compare(activeSpy.count, 2)
@@ -394,6 +701,31 @@ TestCase {
verify(!tableView.selectionModel.hasSelection)
}
+ function test_pressAndHoldPlussShift() {
+ let tableView = createTemporaryObject(tableviewComp, testCase)
+ verify(tableView)
+ let selectionRectangle = tableView.selectionRectangle
+ verify(selectionRectangle)
+
+ selectionRectangle.selectionMode = SelectionRectangle.Drag
+
+ verify(!tableView.selectionModel.hasSelection)
+ verify(!tableView.selectionModel.currentIndex.isValid)
+
+ // select cell 0,0
+ mouseClick(tableView, 1, 1, Qt.LeftButton)
+ compare(tableView.selectionModel.currentIndex, tableView.index(0, 0))
+
+ // do a long press on cell 1,0 while holding down Shift. This will
+ // select both cells.
+ mousePress(tableView, cellWidth + 1, 1, Qt.LeftButton, Qt.ShiftModifier)
+ mouseRelease(tableView, cellWidth + 1, 1, Qt.LeftButton, Qt.ShiftModifier, 2000)
+ verify(tableView.selectionModel.hasSelection)
+ compare(tableView.selectionModel.selectedIndexes.length, 2)
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
+ verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1)))
+ }
+
function test_pressAndHold_on_top_of_handle() {
let tableView = createTemporaryObject(tableviewComp, testCase)
verify(tableView)
@@ -439,8 +771,8 @@ TestCase {
// Select four cells in the middle
mouseDrag(tableView, cellWidth + 1, cellHeight + 1, (cellWidth * 2) - 2, (cellHeight * 2) - 2, Qt.LeftButton)
compare(tableView.selectionModel.selectedIndexes.length, 4)
- for (var x = 1; x < 3; ++x) {
- for (var y = 1; y < 3; ++y) {
+ for (let x = 1; x < 3; ++x) {
+ for (let y = 1; y < 3; ++y) {
verify(tableView.selectionModel.isSelected(tableView.model.index(x, y)))
}
}
@@ -448,8 +780,8 @@ TestCase {
// Drag on the top left handle, so that the selection extends to cell 0, 0
mouseDrag(tableView, cellWidth, cellHeight, -cellWidth / 2, -cellHeight / 2, Qt.LeftButton)
compare(tableView.selectionModel.selectedIndexes.length, 9)
- for (x = 0; x < 3; ++x) {
- for (y = 0; y < 3; ++y) {
+ for (let x = 0; x < 3; ++x) {
+ for (let y = 0; y < 3; ++y) {
verify(tableView.selectionModel.isSelected(tableView.model.index(x, y)))
}
}
@@ -467,8 +799,8 @@ TestCase {
// Select four cells in the middle
mouseDrag(tableView, cellWidth + 1, cellHeight + 1, (cellWidth * 2) - 2, (cellHeight * 2) - 2, Qt.LeftButton)
compare(tableView.selectionModel.selectedIndexes.length, 4)
- for (var x = 1; x < 3; ++x) {
- for (var y = 1; y < 3; ++y) {
+ for (let x = 1; x < 3; ++x) {
+ for (let y = 1; y < 3; ++y) {
verify(tableView.selectionModel.isSelected(tableView.model.index(x, y)))
}
}
@@ -491,8 +823,8 @@ TestCase {
// Select four cells in the middle
mouseDrag(tableView, cellWidth + 1, cellHeight + 1, (cellWidth * 2) - 2, (cellHeight * 2) - 2, Qt.LeftButton)
compare(tableView.selectionModel.selectedIndexes.length, 4)
- for (var x = 1; x < 3; ++x) {
- for (var y = 1; y < 3; ++y) {
+ for (let x = 1; x < 3; ++x) {
+ for (let y = 1; y < 3; ++y) {
verify(tableView.selectionModel.isSelected(tableView.model.index(x, y)))
}
}
@@ -500,11 +832,59 @@ TestCase {
// Drag on the bottom right handle, so that the selection expands to cell 9 cells
mouseDrag(tableView, cellWidth * 3, cellHeight * 3, 10, 10, Qt.LeftButton)
compare(tableView.selectionModel.selectedIndexes.length, 9)
- for (x = 1; x < 4; ++x) {
- for (y = 1; y < 4; ++y) {
+ for (let x = 1; x < 4; ++x) {
+ for (let y = 1; y < 4; ++y) {
verify(tableView.selectionModel.isSelected(tableView.model.index(x, y)))
}
}
}
+ function test_programmatic_unselect() {
+ // Check that the SelectionRectangle will be deactivated if the
+ // selection is changed programatically.
+ let tableView = createTemporaryObject(tableviewComp, testCase)
+ verify(tableView)
+ let selectionRectangle = tableView.selectionRectangle
+ verify(selectionRectangle)
+
+ selectionRectangle.selectionMode = SelectionRectangle.Drag
+
+ verify(!tableView.selectionModel.hasSelection)
+ mouseDrag(tableView, 1, 1, (cellWidth * 2) - 2, 1, Qt.LeftButton)
+ compare(tableView.selectionModel.selectedIndexes.length, 2)
+ verify(selectionRectangle.active)
+
+ tableView.selectionModel.clearSelection()
+ verify(!selectionRectangle.active)
+ }
+
+ function test_extend_using_keyboard() {
+ // Check that the bottom-right selection handle will move if an
+ // acitve selection is extended with the keyboard
+ let tableView = createTemporaryObject(tableviewComp, testCase)
+ verify(tableView)
+ let selectionRectangle = tableView.selectionRectangle
+ verify(selectionRectangle)
+
+ selectionRectangle.bottomRightHandle = bottomRightHandleComp
+ selectionRectangle.selectionMode = SelectionRectangle.Drag
+
+ tableView.forceActiveFocus()
+ verify(!tableView.selectionModel.hasSelection)
+ mouseDrag(tableView, 1, 1, (cellWidth * 2) - 2, 1, Qt.LeftButton)
+ compare(tableView.selectionModel.selectedIndexes.length, 2)
+ verify(selectionRectangle.active)
+ verify(bottomRightHandle)
+ compare(bottomRightHandle.x, (cellWidth * 2) - (bottomRightHandle.width / 2))
+ compare(bottomRightHandle.y, cellHeight - (bottomRightHandle.height / 2))
+
+ keyPress(Qt.Key_Down, Qt.ShiftModifier)
+ keyRelease(Qt.Key_Down, Qt.ShiftModifier)
+ keyPress(Qt.Key_Right, Qt.ShiftModifier)
+ keyRelease(Qt.Key_Right, Qt.ShiftModifier)
+ verify(selectionRectangle.active)
+ compare(tableView.selectionModel.selectedIndexes.length, 6)
+ compare(bottomRightHandle.x, (cellWidth * 3) - (bottomRightHandle.width / 2))
+ compare(bottomRightHandle.y, (cellHeight * 2) - (bottomRightHandle.height / 2))
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_slider.qml b/tests/auto/quickcontrols/controls/data/tst_slider.qml
index df3eb71ae2..991d513122 100644
--- a/tests/auto/quickcontrols/controls/data/tst_slider.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_slider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -23,10 +23,12 @@ TestCase {
Slider { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(slider, testCase)
+ function test_defaults() {
+ let control = createTemporaryObject(slider, testCase)
verify(control)
compare(control.stepSize, 0)
@@ -37,7 +39,7 @@ TestCase {
}
function test_value() {
- var control = createTemporaryObject(slider, testCase)
+ let control = createTemporaryObject(slider, testCase)
verify(control)
compare(control.value, 0.0)
@@ -52,7 +54,7 @@ TestCase {
}
function test_range() {
- var control = createTemporaryObject(slider, testCase, {from: 0, to: 100, value: 50})
+ let control = createTemporaryObject(slider, testCase, {from: 0, to: 100, value: 50})
verify(control)
compare(control.from, 0)
@@ -84,7 +86,7 @@ TestCase {
}
function test_inverted() {
- var control = createTemporaryObject(slider, testCase, {from: 1.0, to: -1.0})
+ let control = createTemporaryObject(slider, testCase, {from: 1.0, to: -1.0})
verify(control)
compare(control.from, 1.0)
@@ -106,7 +108,7 @@ TestCase {
}
function test_position() {
- var control = createTemporaryObject(slider, testCase)
+ let control = createTemporaryObject(slider, testCase)
verify(control)
compare(control.value, 0.0)
@@ -122,7 +124,7 @@ TestCase {
}
function test_visualPosition() {
- var control = createTemporaryObject(slider, testCase)
+ let control = createTemporaryObject(slider, testCase)
verify(control)
compare(control.value, 0.0)
@@ -154,7 +156,7 @@ TestCase {
}
function test_orientation() {
- var control = createTemporaryObject(slider, testCase)
+ let control = createTemporaryObject(slider, testCase)
verify(control)
compare(control.orientation, Qt.Horizontal)
@@ -179,16 +181,16 @@ TestCase {
}
function test_mouse(data) {
- var control = createTemporaryObject(slider, testCase, {orientation: data.orientation, live: data.live})
+ let control = createTemporaryObject(slider, testCase, {orientation: data.orientation, live: data.live})
verify(control)
- var pressedCount = 0
- var movedCount = 0
+ let pressedCount = 0
+ let movedCount = 0
- var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
+ let pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
verify(pressedSpy.valid)
- var movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"})
+ let movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"})
verify(movedSpy.valid)
mousePress(control, 0, control.height - 1, Qt.LeftButton)
@@ -268,19 +270,19 @@ TestCase {
}
function test_touch(data) {
- var control = createTemporaryObject(slider, testCase, {orientation: data.orientation, live: data.live})
+ let control = createTemporaryObject(slider, testCase, {orientation: data.orientation, live: data.live})
verify(control)
- var pressedCount = 0
- var movedCount = 0
+ let pressedCount = 0
+ let movedCount = 0
- var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
+ let pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
verify(pressedSpy.valid)
- var movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"})
+ let movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"})
verify(movedSpy.valid)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
touch.press(0, control, 0, 0).commit()
compare(pressedSpy.count, ++pressedCount)
compare(movedSpy.count, movedCount)
@@ -349,19 +351,19 @@ TestCase {
}
function test_multiTouch() {
- var control1 = createTemporaryObject(slider, testCase, {live: false})
+ let control1 = createTemporaryObject(slider, testCase, {live: false})
verify(control1)
- var pressedCount1 = 0
- var movedCount1 = 0
+ let pressedCount1 = 0
+ let movedCount1 = 0
- var pressedSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "pressedChanged"})
+ let pressedSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "pressedChanged"})
verify(pressedSpy1.valid)
- var movedSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "moved"})
+ let movedSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "moved"})
verify(movedSpy1.valid)
- var touch = touchEvent(control1)
+ let touch = touchEvent(control1)
touch.press(0, control1, 0, 0).commit().move(0, control1, control1.width, control1.height).commit()
compare(pressedSpy1.count, ++pressedCount1)
@@ -379,16 +381,16 @@ TestCase {
compare(control1.pressed, true)
compare(control1.position, 1.0)
- var control2 = createTemporaryObject(slider, testCase, {y: control1.height, live: false})
+ let control2 = createTemporaryObject(slider, testCase, {y: control1.height, live: false})
verify(control2)
- var pressedCount2 = 0
- var movedCount2 = 0
+ let pressedCount2 = 0
+ let movedCount2 = 0
- var pressedSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "pressedChanged"})
+ let pressedSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "pressedChanged"})
verify(pressedSpy2.valid)
- var movedSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "moved"})
+ let movedSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "moved"})
verify(movedSpy2.valid)
// press the second slider
@@ -443,25 +445,25 @@ TestCase {
}
function test_keys(data) {
- var control = createTemporaryObject(slider, testCase, {orientation: data.orientation})
+ let control = createTemporaryObject(slider, testCase, {orientation: data.orientation})
verify(control)
- var pressedCount = 0
- var movedCount = 0
+ let pressedCount = 0
+ let movedCount = 0
- var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
+ let pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
verify(pressedSpy.valid)
- var movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"})
+ let movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"})
verify(movedSpy.valid)
control.forceActiveFocus()
verify(control.activeFocus)
- var oldValue = 0.0
+ let oldValue = 0.0
control.value = 0.5
- for (var d1 = 1; d1 <= 10; ++d1) {
+ for (let d1 = 1; d1 <= 10; ++d1) {
oldValue = control.value
keyPress(data.decrease)
compare(control.pressed, true)
@@ -478,7 +480,7 @@ TestCase {
compare(movedSpy.count, movedCount)
}
- for (var i1 = 1; i1 <= 20; ++i1) {
+ for (let i1 = 1; i1 <= 20; ++i1) {
oldValue = control.value
keyPress(data.increase)
compare(control.pressed, true)
@@ -497,7 +499,7 @@ TestCase {
control.stepSize = 0.25
- for (var d2 = 1; d2 <= 10; ++d2) {
+ for (let d2 = 1; d2 <= 10; ++d2) {
oldValue = control.value
keyPress(data.decrease)
compare(control.pressed, true)
@@ -514,7 +516,7 @@ TestCase {
compare(movedSpy.count, movedCount)
}
- for (var i2 = 1; i2 <= 10; ++i2) {
+ for (let i2 = 1; i2 <= 10; ++i2) {
oldValue = control.value
keyPress(data.increase)
compare(control.pressed, true)
@@ -536,10 +538,10 @@ TestCase {
// test with "unbalanced" paddings (left padding != right padding) to ensure
// that the slider position calculation is done taking padding into account
// ==> the position is _not_ 0.5 in the middle of the control
- var control = createTemporaryObject(slider, testCase, {leftPadding: 10, rightPadding: 20, live: false})
+ let control = createTemporaryObject(slider, testCase, {leftPadding: 10, rightPadding: 20, live: false})
verify(control)
- var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
+ let pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
verify(pressedSpy.valid)
mousePress(control, 0, 0, Qt.LeftButton)
@@ -620,12 +622,12 @@ TestCase {
{ tag: "SnapOnRelease (-1..1)", snapMode: Slider.SnapOnRelease, from: -1, to: 1, values: [0.0, 0.0, -0.8], positions: [immediate ? 0.0 : 0.5, 0.1, 0.1] },
{ tag: "SnapOnRelease (1..-1)", snapMode: Slider.SnapOnRelease, from: 1, to: -1, values: [0.0, 0.0, 0.8], positions: [immediate ? 0.0 : 0.5, 0.1, 0.1] },
// Live
- { tag: "SnapAlwaysLive", snapMode: Slider.SnapAlways, from: 0, to: 1, value: 0, stepSize: 1, live: true, sliderPos: 0.6, values: [0, 1, 1], positions: [0, 1, 1] },
- { tag: "SnapAlwaysLive", snapMode: Slider.SnapAlways, from: 0, to: 1, value: 0, stepSize: 1, live: true, sliderPos: 0.4, values: [0, 0, 0], positions: [0, 0, 0] },
- { tag: "NoSnapLive", snapMode: Slider.NoSnap, from: 0, to: 1, value: 0, stepSize: 1, live: true, sliderPos: 0.6, values: [0, 1, 1], positions: [0, 0.6, 0.6] },
- { tag: "NoSnapLive", snapMode: Slider.NoSnap, from: 0, to: 1, value: 0, stepSize: 1, live: true, sliderPos: 0.4, values: [0, 0, 0], positions: [0, 0.4, 0.4] },
- { tag: "SnapOnReleaseLive", snapMode: Slider.SnapOnRelease, from: 0, to: 1, value: 0, stepSize: 1, live: true, sliderPos: 0.6, values: [0, 1, 1], positions: [0, 0.6, 1] },
- { tag: "SnapOnReleaseLive", snapMode: Slider.SnapOnRelease, from: 0, to: 1, value: 0, stepSize: 1, live: true, sliderPos: 0.4, values: [0, 0, 0], positions: [0, 0.4, 0] },
+ { tag: "SnapAlwaysLive1", snapMode: Slider.SnapAlways, from: 0, to: 1, value: 0, stepSize: 1, live: true, sliderPos: 0.6, values: [0, 1, 1], positions: [0, 1, 1] },
+ { tag: "SnapAlwaysLive2", snapMode: Slider.SnapAlways, from: 0, to: 1, value: 0, stepSize: 1, live: true, sliderPos: 0.4, values: [0, 0, 0], positions: [0, 0, 0] },
+ { tag: "NoSnapLive1", snapMode: Slider.NoSnap, from: 0, to: 1, value: 0, stepSize: 1, live: true, sliderPos: 0.6, values: [0, 1, 1], positions: [0, 0.6, 0.6] },
+ { tag: "NoSnapLive2", snapMode: Slider.NoSnap, from: 0, to: 1, value: 0, stepSize: 1, live: true, sliderPos: 0.4, values: [0, 0, 0], positions: [0, 0.4, 0.4] },
+ { tag: "SnapOnReleaseLive1", snapMode: Slider.SnapOnRelease, from: 0, to: 1, value: 0, stepSize: 1, live: true, sliderPos: 0.6, values: [0, 1, 1], positions: [0, 0.6, 1] },
+ { tag: "SnapOnReleaseLive2", snapMode: Slider.SnapOnRelease, from: 0, to: 1, value: 0, stepSize: 1, live: true, sliderPos: 0.4, values: [0, 0, 0], positions: [0, 0.4, 0] },
]
}
@@ -635,7 +637,7 @@ TestCase {
let sliderPos = data.sliderPos !== undefined ? data.sliderPos : 0.1
let fuzz = 0.05
- var control = createTemporaryObject(slider, testCase, {live: live, snapMode: data.snapMode, from: data.from, to: data.to, stepSize: stepSize})
+ let control = createTemporaryObject(slider, testCase, {live: live, snapMode: data.snapMode, from: data.from, to: data.to, stepSize: stepSize})
verify(control)
// The test assumes there is no drag threshold for neither mouse or touch.
@@ -644,7 +646,7 @@ TestCase {
// on a very narrow slider, we ensure the same width of all sliders
control.width = testCase.width
- var touch = useMouse ? null : touchEvent(control)
+ let touch = useMouse ? null : touchEvent(control)
if (useMouse)
mousePress(control, calcMousePos(control, 0.0))
@@ -695,11 +697,11 @@ TestCase {
}
function test_wheel(data) {
- var control = createTemporaryObject(slider, testCase, {wheelEnabled: true, orientation: data.orientation})
+ let control = createTemporaryObject(slider, testCase, {wheelEnabled: true, orientation: data.orientation})
verify(control)
- var movedCount = 0
- var movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"})
+ let movedCount = 0
+ let movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"})
verify(movedSpy.valid)
compare(control.value, 0.0)
@@ -761,19 +763,19 @@ TestCase {
}
function test_wheelPropagation(data) {
- var mouseArea = createTemporaryObject(mouseAreaComponent, testCase, { width: parent.width, height: parent.height })
+ let mouseArea = createTemporaryObject(mouseAreaComponent, testCase, { width: parent.width, height: parent.height })
verify(mouseArea)
- var mouseAreaWheelSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "wheel" })
+ let mouseAreaWheelSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "wheel" })
verify(mouseAreaWheelSpy.valid)
- var control = createTemporaryObject(slider, mouseArea,
+ let control = createTemporaryObject(slider, mouseArea,
{ wheelEnabled: true, orientation: data.orientation, stepSize: 1 })
verify(control)
compare(control.value, 0.0)
- var movedCount = 0
- var movedSpy = signalSpy.createObject(control, { target: control, signalName: "moved" })
+ let movedCount = 0
+ let movedSpy = signalSpy.createObject(control, { target: control, signalName: "moved" })
verify(movedSpy.valid)
// Scroll the handle to the edge.
@@ -826,7 +828,7 @@ TestCase {
}
function test_nullHandle() {
- var control = createTemporaryObject(slider, testCase)
+ let control = createTemporaryObject(slider, testCase)
verify(control)
control.handle = null
@@ -839,7 +841,7 @@ TestCase {
}
function test_touchDragThreshold_data() {
- var d1 = 3; var d2 = 7;
+ let d1 = 3; let d2 = 7;
return [
{ tag: "horizontal", orientation: Qt.Horizontal, dx1: d1, dy1: 0, dx2: d2, dy2: 0 },
{ tag: "vertical", orientation: Qt.Vertical, dx1: 0, dy1: -d1, dx2: 0, dy2: -d2 },
@@ -849,19 +851,19 @@ TestCase {
}
function test_touchDragThreshold(data) {
- var control = createTemporaryObject(slider, testCase, {touchDragThreshold: 10, live: true, orientation: data.orientation, value: 0.5})
+ let control = createTemporaryObject(slider, testCase, {touchDragThreshold: 10, live: true, orientation: data.orientation, value: 0.5})
verify(control)
compare(control.touchDragThreshold, 10)
- var valueChangedCount = 0
- var valueChangedSpy = signalSpy.createObject(control, {target: control, signalName: "touchDragThresholdChanged"})
+ let valueChangedCount = 0
+ let valueChangedSpy = signalSpy.createObject(control, {target: control, signalName: "touchDragThresholdChanged"})
verify(valueChangedSpy.valid)
control.touchDragThreshold = undefined
compare(control.touchDragThreshold, -1) // reset to -1
compare(valueChangedSpy.count, ++valueChangedCount)
- var t = 5
+ let t = 5
control.touchDragThreshold = t
compare(control.touchDragThreshold, t)
compare(valueChangedSpy.count, ++valueChangedCount)
@@ -870,18 +872,18 @@ TestCase {
compare(control.touchDragThreshold, t)
compare(valueChangedSpy.count, valueChangedCount)
- var pressedCount = 0
- var movedCount = 0
+ let pressedCount = 0
+ let movedCount = 0
- var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
+ let pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
verify(pressedSpy.valid)
- var movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"})
+ let movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"})
verify(movedSpy.valid)
- var touch = touchEvent(control)
- var x0 = control.handle.x + control.handle.width * 0.5
- var y0 = control.handle.y + control.handle.height * 0.5
+ let touch = touchEvent(control)
+ let x0 = control.handle.x + control.handle.width * 0.5
+ let y0 = control.handle.y + control.handle.height * 0.5
touch.press(0, control, x0, y0).commit()
compare(pressedSpy.count, ++pressedCount)
compare(movedSpy.count, movedCount)
@@ -902,9 +904,20 @@ TestCase {
function test_nullTexture() {
failOnWarning("No QSGTexture provided from updateSampledImage(). This is wrong.")
- var control = createTemporaryObject(slider, testCase, {width: -100})
+ let control = createTemporaryObject(slider, testCase, {width: -100})
verify(control)
control.visible = true
waitForRendering(control)
}
+
+ function test_clickFocus() {
+ let control = createTemporaryObject(slider, testCase)
+ verify(control)
+
+ mouseClick(control)
+ if (Qt.platform.os === "osx")
+ verify(!control.activeFocus)
+ else
+ verify(control.activeFocus)
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_spinbox.qml b/tests/auto/quickcontrols/controls/data/tst_spinbox.qml
index df30ef4beb..ba27aeed77 100644
--- a/tests/auto/quickcontrols/controls/data/tst_spinbox.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_spinbox.qml
@@ -1,10 +1,11 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
import QtQuick.Controls
import QtQuick.Window
+import QtQuick.Layouts
TestCase {
id: testCase
@@ -29,10 +30,12 @@ TestCase {
MouseArea { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(spinBox, testCase)
+ function test_defaults() {
+ let control = createTemporaryObject(spinBox, testCase)
verify(control)
compare(control.from, 0)
@@ -47,7 +50,7 @@ TestCase {
}
function test_value() {
- var control = createTemporaryObject(spinBox, testCase)
+ let control = createTemporaryObject(spinBox, testCase)
verify(control)
compare(control.value, 0)
@@ -62,7 +65,7 @@ TestCase {
}
function test_range() {
- var control = createTemporaryObject(spinBox, testCase, {from: 0, to: 100, value: 50})
+ let control = createTemporaryObject(spinBox, testCase, {from: 0, to: 100, value: 50})
verify(control)
compare(control.from, 0)
@@ -132,7 +135,7 @@ TestCase {
}
function test_inverted() {
- var control = createTemporaryObject(spinBox, testCase, {from: 100, to: -100})
+ let control = createTemporaryObject(spinBox, testCase, {from: 100, to: -100})
verify(control)
compare(control.from, 100)
@@ -169,16 +172,16 @@ TestCase {
}
function test_mouse(data) {
- var control = createTemporaryObject(spinBox, testCase, {value: data.value})
+ let control = createTemporaryObject(spinBox, testCase, {value: data.value})
verify(control)
- var button = control[data.button]
+ let button = control[data.button]
verify(button)
- var pressedSpy = signalSpy.createObject(control, {target: button, signalName: "pressedChanged"})
+ let pressedSpy = signalSpy.createObject(control, {target: button, signalName: "pressedChanged"})
verify(pressedSpy.valid)
- var valueModifiedSpy = signalSpy.createObject(control, {target: control, signalName: "valueModified"})
+ let valueModifiedSpy = signalSpy.createObject(control, {target: control, signalName: "valueModified"})
verify(valueModifiedSpy.valid)
mousePress(button.indicator)
@@ -209,27 +212,27 @@ TestCase {
}
function test_keys(data) {
- var control = createTemporaryObject(spinBox, testCase, data.properties)
+ let control = createTemporaryObject(spinBox, testCase, data.properties)
verify(control)
- var upPressedCount = 0
- var downPressedCount = 0
- var valueModifiedCount = 0
+ let upPressedCount = 0
+ let downPressedCount = 0
+ let valueModifiedCount = 0
- var upPressedSpy = signalSpy.createObject(control, {target: control.up, signalName: "pressedChanged"})
+ let upPressedSpy = signalSpy.createObject(control, {target: control.up, signalName: "pressedChanged"})
verify(upPressedSpy.valid)
- var downPressedSpy = signalSpy.createObject(control, {target: control.down, signalName: "pressedChanged"})
+ let downPressedSpy = signalSpy.createObject(control, {target: control.down, signalName: "pressedChanged"})
verify(downPressedSpy.valid)
- var valueModifiedSpy = signalSpy.createObject(control, {target: control, signalName: "valueModified"})
+ let valueModifiedSpy = signalSpy.createObject(control, {target: control, signalName: "valueModified"})
verify(valueModifiedSpy.valid)
control.forceActiveFocus()
verify(control.activeFocus)
- for (var u = 0; u < data.upSteps.length; ++u) {
- var wasUpEnabled = control.wrap || control.value < control.to
+ for (let u = 0; u < data.upSteps.length; ++u) {
+ let wasUpEnabled = control.wrap || control.value < control.to
keyPress(Qt.Key_Up)
compare(control.up.pressed, wasUpEnabled)
compare(control.down.pressed, false)
@@ -251,8 +254,8 @@ TestCase {
compare(valueModifiedSpy.count, valueModifiedCount)
}
- for (var d = 0; d < data.downSteps.length; ++d) {
- var wasDownEnabled = control.wrap || control.value > control.from
+ for (let d = 0; d < data.downSteps.length; ++d) {
+ let wasDownEnabled = control.wrap || control.value > control.from
keyPress(Qt.Key_Down)
compare(control.down.pressed, wasDownEnabled)
compare(control.up.pressed, false)
@@ -276,26 +279,26 @@ TestCase {
}
function test_locale() {
- var control = createTemporaryObject(spinBox, testCase)
+ let control = createTemporaryObject(spinBox, testCase)
verify(control)
control.locale = Qt.locale("ar_EG") // Arabic, Egypt
- var numbers = ["Ù ", "Ù¡", "Ù¢", "Ù£", "Ù¤", "Ù¥", "Ù¦", "Ù§", "Ù¨", "Ù©"]
- for (var i = 0; i < 10; ++i) {
+ let numbers = ["Ù ", "Ù¡", "Ù¢", "Ù£", "Ù¤", "Ù¥", "Ù¦", "Ù§", "Ù¨", "Ù©"]
+ for (let i = 0; i < 10; ++i) {
control.value = i
compare(control.contentItem.text, numbers[i])
}
}
function test_baseline() {
- var control = createTemporaryObject(spinBox, testCase)
+ let control = createTemporaryObject(spinBox, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
}
function test_focus() {
- var control = createTemporaryObject(spinBox, testCase, {from: 10, to: 1000, value: 100, focus: true})
+ let control = createTemporaryObject(spinBox, testCase, {from: 10, to: 1000, value: 100, focus: true})
verify(control)
control.forceActiveFocus()
@@ -314,41 +317,465 @@ TestCase {
}
function test_initialFocus() {
- var window = testCase.Window.window
+ let window = testCase.Window.window
verify(window)
compare(window.activeFocusItem, window.contentItem)
- var control = createTemporaryObject(spinBox, testCase, { editable: true, focus: true })
+ let control = createTemporaryObject(spinBox, testCase, { editable: true, focus: true })
verify(control)
tryCompare(control.contentItem, "activeFocus", true)
}
function test_editable() {
- var control = createTemporaryObject(spinBox, testCase)
+ let control = createTemporaryObject(spinBox, testCase)
verify(control)
- var valueModifiedSpy = signalSpy.createObject(control, {target: control, signalName: "valueModified"})
+ let valueModifiedSpy = signalSpy.createObject(control, {target: control, signalName: "valueModified"})
verify(valueModifiedSpy.valid)
+ let displayTextChangedSpy = signalSpy.createObject(control, {target: control, signalName: "displayTextChanged"})
+ verify(displayTextChangedSpy.valid)
+
+
+ control.from = 0
+ control.to = 10
+ compare(control.from, 0)
+ compare(control.to, 10)
+
control.contentItem.forceActiveFocus()
compare(control.contentItem.activeFocus, true)
compare(control.editable, false)
control.contentItem.selectAll()
+ compare(control.displayText, "0")
keyClick(Qt.Key_5)
keyClick(Qt.Key_Return)
+ compare(control.displayText, "0")
compare(control.value, 0)
compare(valueModifiedSpy.count, 0)
control.editable = true
compare(control.editable, true)
control.contentItem.selectAll()
+ keyClick(Qt.Key_Backspace)
keyClick(Qt.Key_5)
+ compare(control.displayText, "5")
keyClick(Qt.Key_Return)
compare(control.value, 5)
compare(valueModifiedSpy.count, 1)
+ compare(displayTextChangedSpy.count, 2)
+
+ keyClick(Qt.Key_0)
+ compare(control.displayText, "50")
+ compare(control.value, 5)
+ compare(valueModifiedSpy.count, 1)
+ compare(displayTextChangedSpy.count, 3)
+ keyClick(Qt.Key_Return) //will set the value to maximum = 10
+ compare(control.displayText, "10")
+ compare(control.value, 10)
+ compare(valueModifiedSpy.count, 2) // 0->5->10
+ compare(displayTextChangedSpy.count, 4) //0->5->50->10
}
+
+ function test_editable_liveUpdate() {
+ let control = createTemporaryObject(spinBox, testCase)
+ verify(control)
+
+ let valueModifiedSpy = signalSpy.createObject(control, {target: control, signalName: "valueModified"})
+ verify(valueModifiedSpy.valid)
+
+ let valueChangedSpy = signalSpy.createObject(control, {target: control, signalName: "valueChanged"})
+ verify(valueChangedSpy.valid)
+
+ let displayTextChangedSpy = signalSpy.createObject(control, {target: control, signalName: "displayTextChanged"})
+ verify(displayTextChangedSpy.valid)
+
+ control.contentItem.forceActiveFocus()
+ compare(control.contentItem.activeFocus, true)
+
+ control.editable = true
+ control.live = true
+ control.from = -10
+ control.to = 10
+ compare(control.editable, true)
+ compare(control.live, true)
+ compare(control.from, -10)
+ compare(control.to, 10)
+
+ control.contentItem.selectAll()
+ keyClick(Qt.Key_5)
+ compare(control.displayText, "5")
+ compare(control.value, 5)
+ compare(valueModifiedSpy.count, 0)
+ compare(valueChangedSpy.count, 1)
+ compare(displayTextChangedSpy.count, 1)
+
+ keyClick(Qt.Key_0)
+ compare(control.displayText, "50") // do not set the value
+ compare(control.value, 5) // if it is out of bounds
+ compare(valueModifiedSpy.count, 0)
+ compare(valueChangedSpy.count, 1)
+ compare(displayTextChangedSpy.count, 2)
+
+
+ keyClick(Qt.Key_Backspace)
+ compare(control.displayText, "5")
+ compare(control.value, 5)
+ compare(valueModifiedSpy.count, 0)
+ compare(valueChangedSpy.count, 1)
+ compare(displayTextChangedSpy.count, 3)
+
+ keyClick(Qt.Key_Backspace)
+ compare(control.displayText, "0")
+ compare(control.value, 0)
+ compare(valueModifiedSpy.count, 0)
+ compare(valueChangedSpy.count, 2)
+ compare(displayTextChangedSpy.count, 4)
+
+ keyClick(Qt.Key_Backspace)
+ compare(control.displayText, "")
+ compare(control.value, 0)
+ compare(valueModifiedSpy.count, 0)
+ compare(valueChangedSpy.count, 2)
+ compare(displayTextChangedSpy.count, 5)
+ }
+
+ Component {
+ id: doubleBox
+ SpinBox {
+ id: doubleSpinBox
+ locale: Qt.locale("en_US")
+
+ property int decimals: 2
+ property double realValue: value / 10**decimals
+ validator: DoubleValidator {
+ bottom: Math.min(doubleSpinBox.from, doubleSpinBox.to)
+ top: Math.max(doubleSpinBox.from, doubleSpinBox.to)
+ decimals: doubleSpinBox.decimals
+ notation: DoubleValidator.StandardNotation
+ locale: doubleSpinBox.locale.name
+ }
+
+ textFromValue: function(value, locale) {
+ let res = Number(value / 10**doubleSpinBox.decimals).toLocaleString(locale, 'f', doubleSpinBox.decimals)
+ return res
+ }
+
+ valueFromText: function(text, locale) {
+ let res = Math.round(Number.fromLocaleString(locale, text) * 10**doubleSpinBox.decimals)
+ return res
+ }
+
+ onDisplayTextChanged: {
+ displayTextChangedWithArg(doubleSpinBox.displayText);
+ }
+
+ signal displayTextChangedWithArg(text: string)
+ }
+ }
+
+ function test_editable_doubleSpinBox() {
+ let control = createTemporaryObject(doubleBox, testCase)
+ verify(control)
+
+ control.editable = true
+ control.from = 0
+ control.to = 1000000
+ control.value = 500
+ control.stepSize = 1
+
+ compare(control.editable, true)
+ compare(control.from, 0)
+ compare(control.to, 1000000)
+ compare(control.value, 500)
+ compare(control.realValue, 5.00)
+ compare(control.displayText, "5.00")
+
+ let valueModifiedSpy = signalSpy.createObject(control, {target: control, signalName: "valueModified"})
+ verify(valueModifiedSpy.valid)
+
+ let valueChangedSpy = signalSpy.createObject(control, {target: control, signalName: "valueChanged"})
+ verify(valueChangedSpy.valid)
+
+ let displayTextChangedSpy = signalSpy.createObject(control, {target: control, signalName: "displayTextChangedWithArg"})
+ verify(displayTextChangedSpy.valid)
+
+ control.contentItem.forceActiveFocus()
+ compare(control.contentItem.activeFocus, true)
+
+ control.contentItem.selectAll()
+ compare(displayTextChangedSpy.count, 0)
+ keyClick(Qt.Key_4)
+ compare(control.value, 500)
+ compare(control.realValue, 5.00)
+ compare(control.displayText, "4")
+ compare(valueModifiedSpy.count, 0)
+ compare(valueChangedSpy.count, 0)
+ compare(displayTextChangedSpy.signalArguments[0][0], "4")
+ compare(displayTextChangedSpy.count, 1)
+
+ keyClick(Qt.Key_Enter)
+ compare(control.value, 400)
+ compare(control.realValue, 4.00)
+ compare(control.displayText, "4.00")
+ compare(valueModifiedSpy.count, 1)
+ compare(valueChangedSpy.count, 1)
+ compare(displayTextChangedSpy.signalArguments[1][0], "4.00")
+ compare(displayTextChangedSpy.count, 2)
+
+ keyClick(Qt.Key_Backspace)
+ compare(control.value, 400)
+ compare(control.realValue, 4.00)
+ compare(control.displayText, "4.0")
+ compare(valueModifiedSpy.count, 1)
+ compare(valueChangedSpy.count, 1)
+ compare(displayTextChangedSpy.signalArguments[2][0], "4.0")
+ compare(displayTextChangedSpy.count, 3)
+
+ keyClick(Qt.Key_Backspace)
+ compare(control.value, 400)
+ compare(control.realValue, 4.00)
+ compare(control.displayText, "4") //The fixup removes the trailing "."
+ compare(valueModifiedSpy.count, 1)
+ compare(valueChangedSpy.count, 1)
+ compare(displayTextChangedSpy.signalArguments[3][0], "4")
+ compare(displayTextChangedSpy.count, 4)
+
+ keyClick(Qt.Key_0)
+ compare(control.value, 400)
+ compare(control.realValue, 4.00)
+ compare(control.displayText, "40")
+ compare(valueModifiedSpy.count, 1)
+ compare(valueChangedSpy.count, 1)
+ compare(displayTextChangedSpy.signalArguments[4][0], "40")
+ compare(displayTextChangedSpy.count, 5)
+
+ keyClick(Qt.Key_0)
+ compare(control.value, 400)
+ compare(control.realValue, 4.00)
+ compare(control.displayText, "400")
+ compare(valueModifiedSpy.count, 1)
+ compare(valueChangedSpy.count, 1)
+ compare(displayTextChangedSpy.signalArguments[5][0], "400")
+ compare(displayTextChangedSpy.count, 6)
+
+ keyClick(Qt.Key_0)
+ compare(control.value, 400)
+ compare(control.realValue, 4.00)
+ compare(control.displayText, "4,000")
+ compare(valueModifiedSpy.count, 1)
+ compare(valueChangedSpy.count, 1)
+ compare(displayTextChangedSpy.signalArguments[6][0], "4,000")
+ compare(displayTextChangedSpy.count, 7)
+
+ keyClick(Qt.Key_Enter)
+ compare(control.value, 400000)
+ compare(control.realValue, 4000.00)
+ compare(control.displayText, "4,000.00")
+ compare(valueModifiedSpy.count, 2)
+ compare(valueChangedSpy.count, 2)
+ compare(displayTextChangedSpy.signalArguments[7][0], "4,000.00")
+ compare(displayTextChangedSpy.count, 8)
+
+ // Changing to and testing live mode
+ control.live = true
+ compare(control.live, true)
+
+ keyClick(Qt.Key_Backspace)
+ compare(control.value, 400000)
+ compare(control.realValue, 4000.00)
+ compare(control.displayText, "4,000.0")
+ compare(valueModifiedSpy.count, 2)
+ compare(valueChangedSpy.count, 2)
+ compare(displayTextChangedSpy.signalArguments[8][0], "4,000.0")
+ compare(displayTextChangedSpy.count, 9)
+
+ keyClick(Qt.Key_Backspace)
+ compare(control.value, 400000)
+ compare(control.realValue, 4000.00)
+ compare(control.displayText, "4,000") //The fixup removes the trailing "."
+ compare(valueModifiedSpy.count, 2)
+ compare(valueChangedSpy.count, 2)
+ compare(displayTextChangedSpy.signalArguments[9][0], "4,000")
+ compare(displayTextChangedSpy.count, 10)
+
+ keyClick(Qt.Key_Backspace)
+ compare(control.displayText, "400.00")
+ compare(control.value, 40000)
+ compare(control.realValue, 400.00)
+ compare(valueModifiedSpy.count, 2)
+ compare(valueChangedSpy.count, 3)
+ compare(displayTextChangedSpy.signalArguments[10][0], "400.00")
+ compare(displayTextChangedSpy.count, 11)
+
+ // It is a bit unfortunate that we need 3 Backspace to go from
+ // 400 to 4000 on live editing mode. Maybe think about a fix in
+ // the future to make it more user friendly
+ keyClick(Qt.Key_Backspace)
+ keyClick(Qt.Key_Backspace)
+ keyClick(Qt.Key_Backspace)
+ compare(control.displayText, "40.00")
+ compare(control.value, 4000)
+ compare(control.realValue, 40.00)
+ compare(valueModifiedSpy.count, 2)
+ compare(valueChangedSpy.count, 4)
+ compare(displayTextChangedSpy.signalArguments[11][0], "400.0")
+ compare(displayTextChangedSpy.signalArguments[12][0], "400")
+ compare(displayTextChangedSpy.signalArguments[13][0], "40.00")
+ compare(displayTextChangedSpy.count, 14)
+
+ keyClick(Qt.Key_Backspace)
+ keyClick(Qt.Key_Backspace)
+ keyClick(Qt.Key_Backspace)
+ compare(control.displayText, "4.00")
+ compare(control.value, 400)
+ compare(control.realValue, 4.00)
+ compare(valueModifiedSpy.count, 2)
+ compare(valueChangedSpy.count, 5)
+ compare(displayTextChangedSpy.signalArguments[14][0], "40.0")
+ compare(displayTextChangedSpy.signalArguments[15][0], "40")
+ compare(displayTextChangedSpy.signalArguments[16][0], "4.00")
+ compare(displayTextChangedSpy.count, 17)
+
+ keyClick(Qt.Key_Backspace)
+ keyClick(Qt.Key_Backspace)
+ keyClick(Qt.Key_1)
+ compare(control.displayText, "41.00")
+ compare(control.value, 4100)
+ compare(control.realValue, 41.00)
+ compare(valueModifiedSpy.count, 2)
+ compare(valueChangedSpy.count, 6)
+ compare(displayTextChangedSpy.signalArguments[17][0], "4.0")
+ compare(displayTextChangedSpy.signalArguments[18][0], "4")
+ compare(displayTextChangedSpy.signalArguments[19][0], "41.00")
+ compare(displayTextChangedSpy.count, 20)
+ }
+
+ function test_groupSeparatorHandling_data() {
+ return [
+ { tag: "en_EN" },
+ { tag: "de_DE" }
+ ]
+ }
+
+ function test_groupSeparatorHandling(data) {
+ let control = createTemporaryObject(spinBox, testCase)
+ verify(control)
+
+ let testLoc = Qt.locale(data.tag)
+ control.locale = testLoc
+
+ control.contentItem.forceActiveFocus()
+ compare(control.contentItem.activeFocus, true)
+
+ control.editable = true
+ control.live = true
+ control.from = 0
+ control.to = 10*1000*1000
+ compare(control.editable, true)
+ compare(control.live, true)
+ compare(control.from, 0)
+ compare(control.to, 10*1000*1000)
+
+ control.contentItem.selectAll()
+ keyClick(Qt.Key_5)
+ compare(control.displayText, "5")
+ compare(control.value, 5)
+
+ let i = 50
+ for (; i < 1e7; i*=10) {
+ keyClick(Qt.Key_0)
+ compare(control.displayText, testLoc.toString(i))
+ compare(control.value, i)
+ }
+
+ i /= 100;
+ for (; i > 10; i/=10) {
+ keyClick(Qt.Key_Backspace)
+ compare(control.displayText, testLoc.toString(i))
+ compare(control.value, i)
+ }
+ }
+
+ function test_qtbug64151() {
+ // Slightly modified example from QTBUG-64151. We use displayText
+ // instead of contentItem.text as a workaround.
+ let control = createTemporaryObject(spinBox, testCase)
+ verify(control)
+
+ control.locale = Qt.locale("en_EN")
+
+ control.from = 0
+ control.to = 2000
+ control.value = 2000
+ control.editable = true
+
+ compare(control.displayText, "2,000")
+
+ control.contentItem.forceActiveFocus()
+ compare(control.contentItem.activeFocus, true)
+ keyClick(Qt.Key_Backspace)
+ keyClick(Qt.Key_Return)
+
+ compare(control.displayText, "200")
+ compare(control.valueFromText(control.contentItem.text, control.locale), 200)
+ compare(control.value, 200)
+
+ control.contentItem.forceActiveFocus()
+ keyClick(Qt.Key_0)
+ keyClick(Qt.Key_Return)
+ compare(control.displayText, "2,000")
+ }
+
+ Component {
+ id: spinBoxAndAction
+ RowLayout {
+ id: layout
+ property alias spinbox: theSpinbox
+ property alias button: theButton
+ SpinBox {
+ id: theSpinbox
+ from: 0
+ to: 200
+ value: 200
+ editable: true
+ live: true
+ }
+
+ Button {
+ id: theButton
+ property int value: 0
+ action: Action {
+ text: "&Do something"
+ shortcut: "Return"
+ onTriggered: {
+ theButton.value = theSpinbox.value;
+ }
+ }
+ }
+ }
+ }
+
+ function test_qtbug103205() {
+
+ let control = createTemporaryObject(spinBoxAndAction, testCase)
+ verify(control)
+ verify(control.spinbox)
+
+ compare(control.spinbox.displayText, "200")
+ control.forceActiveFocus()
+ control.spinbox.forceActiveFocus()
+ control.spinbox.contentItem.forceActiveFocus()
+ compare(control.spinbox.contentItem.activeFocus, true)
+ keyClick(Qt.Key_Backspace)
+ keyClick(Qt.Key_Return)
+
+ compare(control.spinbox.displayText, "20")
+ compare(control.button.value, 20)
+ }
+
+
function test_wheel_data() {
return [
{ tag: "1", properties: { from: 1, to: 10, value: 1, stepSize: 1 }, upSteps: [2,3,4], downSteps: [3,2,1,1] },
@@ -361,24 +788,24 @@ TestCase {
}
function test_wheel(data) {
- var ma = createTemporaryObject(mouseArea, testCase, {width: 100, height: 100})
+ let ma = createTemporaryObject(mouseArea, testCase, {width: 100, height: 100})
verify(ma)
data.properties.wheelEnabled = true
- var control = spinBox.createObject(ma, data.properties)
+ let control = spinBox.createObject(ma, data.properties)
verify(control)
- var valueModifiedCount = 0
- var valueModifiedSpy = signalSpy.createObject(control, {target: control, signalName: "valueModified"})
+ let valueModifiedCount = 0
+ let valueModifiedSpy = signalSpy.createObject(control, {target: control, signalName: "valueModified"})
verify(valueModifiedSpy.valid)
- var delta = 120
+ let delta = 120
- var spy = signalSpy.createObject(ma, {target: ma, signalName: "wheel"})
+ let spy = signalSpy.createObject(ma, {target: ma, signalName: "wheel"})
verify(spy.valid)
- for (var u = 0; u < data.upSteps.length; ++u) {
- var wasUpEnabled = control.wrap || control.value < control.to
+ for (let u = 0; u < data.upSteps.length; ++u) {
+ let wasUpEnabled = control.wrap || control.value < control.to
mouseWheel(control, control.width / 2, control.height / 2, delta, delta)
if (wasUpEnabled)
++valueModifiedCount
@@ -387,8 +814,8 @@ TestCase {
compare(control.value, data.upSteps[u])
}
- for (var d = 0; d < data.downSteps.length; ++d) {
- var wasDownEnabled = control.wrap || control.value > control.from
+ for (let d = 0; d < data.downSteps.length; ++d) {
+ let wasDownEnabled = control.wrap || control.value > control.from
mouseWheel(control, control.width / 2, control.height / 2, -delta, -delta)
if (wasDownEnabled)
++valueModifiedCount
@@ -408,7 +835,7 @@ TestCase {
}
function test_initiallyDisabledIndicators(data) {
- var control = createTemporaryObject(spinBox, testCase, { from: data.from, value: data.value, to: data.to })
+ let control = createTemporaryObject(spinBox, testCase, { from: data.from, value: data.value, to: data.to })
verify(control)
compare(control.up.indicator.enabled, data.upEnabled)
@@ -427,10 +854,10 @@ TestCase {
}
function test_hover(data) {
- var control = createTemporaryObject(spinBox, testCase, {hoverEnabled: data.hoverEnabled, value: data.value})
+ let control = createTemporaryObject(spinBox, testCase, {hoverEnabled: data.hoverEnabled, value: data.value})
verify(control)
- var button = control[data.button]
+ let button = control[data.button]
compare(control.hovered, false)
compare(button.hovered, false)
@@ -451,16 +878,16 @@ TestCase {
// QTBUG-74688
function test_hoverWhilePressed(data) {
- var control = createTemporaryObject(spinBox, testCase, { hoverEnabled: true, value: 50 })
+ let control = createTemporaryObject(spinBox, testCase, { hoverEnabled: true, value: 50 })
verify(control)
- var button = control[data.tag]
+ let button = control[data.tag]
compare(control.hovered, false)
compare(button.hovered, false)
// Hover over the indicator. It should be hovered.
- var buttonXCenter = button.indicator.x + button.indicator.width / 2
- var buttonYCenter = button.indicator.y + button.indicator.height / 2
+ let buttonXCenter = button.indicator.x + button.indicator.width / 2
+ let buttonYCenter = button.indicator.y + button.indicator.height / 2
mouseMove(control, buttonXCenter, buttonYCenter)
compare(button.hovered, true)
@@ -483,13 +910,13 @@ TestCase {
}
function test_valueFromText(data) {
- var control = createTemporaryObject(spinBox, testCase, {editable: data.editable})
+ let control = createTemporaryObject(spinBox, testCase, {editable: data.editable})
verify(control)
control.forceActiveFocus()
verify(control.activeFocus)
- var valueFromTextCalls = 0
+ let valueFromTextCalls = 0
control.valueFromText = function(text, locale) {
++valueFromTextCalls
return Number.fromLocaleString(locale, text);
@@ -506,21 +933,21 @@ TestCase {
}
function test_callDefaultValueFromText() {
- var control = createTemporaryObject(spinBox, testCase)
+ let control = createTemporaryObject(spinBox, testCase)
verify(control)
compare(control.valueFromText("123", control.locale), 123)
}
function test_autoRepeat() {
- var control = createTemporaryObject(spinBox, testCase)
+ let control = createTemporaryObject(spinBox, testCase)
verify(control)
compare(control.value, 0)
- var valueSpy = signalSpy.createObject(control, {target: control, signalName: "valueChanged"})
+ let valueSpy = signalSpy.createObject(control, {target: control, signalName: "valueChanged"})
verify(valueSpy.valid)
- var countBefore = 0
+ let countBefore = 0
// repeat up
mousePress(control.up.indicator)
@@ -572,7 +999,7 @@ TestCase {
}
function test_initialValue() {
- var control = createTemporaryObject(spinBox, testCase, {from: 1000, to: 10000})
+ let control = createTemporaryObject(spinBox, testCase, {from: 1000, to: 10000})
verify(control)
compare(control.value, 1000)
}
@@ -594,7 +1021,7 @@ TestCase {
}
valueFromText: function(text) {
- for (var i = 0; i < items.length; ++i) {
+ for (let i = 0; i < items.length; ++i) {
if (items[i].toLowerCase().indexOf(text.toLowerCase()) === 0)
return i
}
@@ -611,10 +1038,10 @@ TestCase {
}
function test_textFromValue(data) {
- var control = createTemporaryObject(data.component, testCase)
+ let control = createTemporaryObject(data.component, testCase)
verify(control)
- for (var i = 0; i < data.values.length; ++i) {
+ for (let i = 0; i < data.values.length; ++i) {
control.value = data.values[i]
compare(control.value, data.values[i])
compare(control.displayText, data.displayTexts[i])
@@ -622,7 +1049,7 @@ TestCase {
}
function test_callDefaultTextFromValue() {
- var control = createTemporaryObject(spinBox, testCase)
+ let control = createTemporaryObject(spinBox, testCase)
verify(control)
compare(control.textFromValue(123, control.locale), "123")
}
@@ -638,7 +1065,7 @@ TestCase {
}
function test_indicatorOverridden() {
- var control = createTemporaryObject(overriddenSpinBox, testCase)
+ let control = createTemporaryObject(overriddenSpinBox, testCase)
verify(control)
compare(control.up.indicator.s, "this is the one");
}
@@ -659,9 +1086,8 @@ TestCase {
}
function test_indicatorOverriddenWithIds() {
- var control = createTemporaryObject(overriddenSpinBoxWithIds, testCase)
+ let control = createTemporaryObject(overriddenSpinBoxWithIds, testCase)
verify(control)
- // TODO: Use failOnWarning() here when it has been implemented
// Specifying an id will result in both the default indicator implementations
// and the custom ones being created, but it shouldn't result in any TypeErrors.
compare(control.up.indicator.s, "up");
@@ -670,7 +1096,7 @@ TestCase {
function test_valueEnterFromOutsideRange() {
// Check that changing from 2 to 99 goes to 98 then changing to 99 puts it back to 98
- var control = createTemporaryObject(spinBox, testCase, {from: 2, to: 98, value: 2, editable: true})
+ let control = createTemporaryObject(spinBox, testCase, {from: 2, to: 98, value: 2, editable: true})
verify(control)
control.forceActiveFocus()
@@ -692,4 +1118,39 @@ TestCase {
compare(control.displayText, "98")
compare(control.contentItem.text, "98")
}
+
+ function test_pressedBeforeIncrementOrDecrement(data) {
+ let control = createTemporaryObject(spinBox, testCase, {from: -8, to: 8, value: 0})
+ verify(control)
+
+ control.forceActiveFocus()
+ verify(control.activeFocus)
+
+ // up, down
+ control.stepSize = Qt.binding(() => control.up.pressed ? 2 : 1)
+ keyClick(Qt.Key_Up) // +2
+ compare(control.value, 2)
+ mouseClick(control.up.indicator) // +2
+ compare(control.value, 4)
+ keyClick(Qt.Key_Down) // -1
+ compare(control.value, 3)
+ mouseClick(control.down.indicator) // -1
+ compare(control.value, 2)
+
+ // down, up
+ control.stepSize = Qt.binding(() => control.down.pressed ? 2 : 1)
+ keyClick(Qt.Key_Down) // -2
+ compare(control.value, 0)
+ mouseClick(control.down.indicator) // -2
+ compare(control.value, -2)
+ keyClick(Qt.Key_Up) // +1
+ compare(control.value, -1)
+ mouseClick(control.up.indicator) // +1
+ compare(control.value, 0)
+ }
+
+ function test_nullValidator() {
+ let control = createTemporaryObject(spinBox, testCase, { validator: null })
+ verify(control)
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_splitview.qml b/tests/auto/quickcontrols/controls/data/tst_splitview.qml
index 4cefd834cb..aed303689a 100644
--- a/tests/auto/quickcontrols/controls/data/tst_splitview.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_splitview.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtCore
import QtQuick
@@ -24,9 +24,9 @@ TestCase {
}
function findHandles(splitView) {
- var handles = []
- for (var i = 0; i < splitView.children.length; ++i) {
- var child = splitView.children[i]
+ let handles = []
+ for (let i = 0; i < splitView.children.length; ++i) {
+ let child = splitView.children[i]
if (child.objectName.toLowerCase().indexOf("handle") !== -1)
handles.push(child)
}
@@ -42,14 +42,14 @@ TestCase {
compare(control.count, Math.floor(expectedGeometries.length / 2) + 1,
"Mismatch in actual vs expected number of split items" + context)
- var handles = findHandles(control)
+ let handles = findHandles(control)
compare(handles.length, Math.floor(expectedGeometries.length / 2),
"Mismatch in actual vs expected number of handle items" + context)
- for (var i = 0, splitItemIndex = 0, handleItemIndex = 0; i < expectedGeometries.length; ++i) {
- var item = null
- var itemType = ""
- var typeSpecificIndex = -1
+ for (let i = 0, splitItemIndex = 0, handleItemIndex = 0; i < expectedGeometries.length; ++i) {
+ let item = null
+ let itemType = ""
+ let typeSpecificIndex = -1
if (i % 2 == 0) {
item = control.itemAt(splitItemIndex)
itemType = "split item"
@@ -64,7 +64,7 @@ TestCase {
verify(item, itemType + " at index " + typeSpecificIndex + " should not be null" + context)
- var expectedGeometry = expectedGeometries[i]
+ let expectedGeometry = expectedGeometries[i]
if (expectedGeometry.hasOwnProperty("hidden")) {
// It's geometry doesn't matter because it's hidden.
verify(!item.visible, itemType + " at index " + typeSpecificIndex + " should be hidden" + context)
@@ -74,20 +74,19 @@ TestCase {
// Note that the indices mentioned here account for handles; they do not
// match the indices reported by QQuickSplitView's logging categories.
compare(item.x, expectedGeometry.x, "Mismatch in actual vs expected x value of "
- + itemType + " at index " + typeSpecificIndex + context)
+ + itemType + " " + item + " at index " + typeSpecificIndex + context)
compare(item.y, expectedGeometry.y, "Mismatch in actual vs expected y value of "
- + itemType + " at index " + typeSpecificIndex + context)
+ + itemType + " " + item + " at index " + typeSpecificIndex + context)
compare(item.width, expectedGeometry.width, "Mismatch in actual vs expected width value of "
- + itemType + " at index " + typeSpecificIndex + context)
+ + itemType + " " + item + " at index " + typeSpecificIndex + context)
compare(item.height, expectedGeometry.height, "Mismatch in actual vs expected height value of "
- + itemType + " at index " + typeSpecificIndex + context)
+ + itemType + " " + item + " at index " + typeSpecificIndex + context)
}
}
property real defaultHorizontalHandleWidth: 10
property real defaultVerticalHandleHeight: 10
-
Component {
id: signalSpyComponent
SignalSpy {}
@@ -96,14 +95,14 @@ TestCase {
Component {
id: handleComponent
Rectangle {
- objectName: "handle"
+ objectName: `handle ${x},${y} ${width}x${height} visible: ${visible}`
implicitWidth: defaultHorizontalHandleWidth
implicitHeight: defaultVerticalHandleHeight
color: "#444"
Text {
- objectName: "handleText_" + text
- text: parent.x + "," + parent.y + " " + parent.width + "x" + parent.height
+ objectName: text + "_Text"
+ text: parent.objectName
color: "white"
anchors.centerIn: parent
rotation: 90
@@ -132,18 +131,20 @@ TestCase {
Rectangle {}
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(defaultSplitView, testCase)
verify(control)
}
function test_addItemsAfterCompletion() {
- var control = createTemporaryObject(splitViewComponent, testCase)
+ let control = createTemporaryObject(splitViewComponent, testCase)
verify(control)
- var item0 = rectangleComponent.createObject(control, { implicitWidth: 25, color: "salmon" })
+ let item0 = rectangleComponent.createObject(control, { implicitWidth: 25, color: "salmon" })
verify(item0)
verify(isPolishScheduled(control))
verify(waitForItemPolished(control))
@@ -153,7 +154,7 @@ TestCase {
compare(item0.width, testCase.width)
compare(item0.height, testCase.height)
- var item1 = rectangleComponent.createObject(control, { implicitWidth: 25, color: "steelblue" })
+ let item1 = rectangleComponent.createObject(control, { implicitWidth: 25, color: "steelblue" })
verify(item1)
verify(isPolishScheduled(control))
verify(waitForItemPolished(control))
@@ -162,8 +163,8 @@ TestCase {
compare(item0.y, 0)
compare(item0.width, item0.implicitWidth)
compare(item0.height, testCase.height)
- var handles = findHandles(control)
- var handle0 = handles[0]
+ let handles = findHandles(control)
+ let handle0 = handles[0]
compare(handle0.x, item0.implicitWidth)
compare(handle0.y, 0)
compare(handle0.width, defaultHorizontalHandleWidth)
@@ -175,10 +176,10 @@ TestCase {
}
function test_addItemsWithNoSizeAfterCompletion() {
- var control = createTemporaryObject(splitViewComponent, testCase)
+ let control = createTemporaryObject(splitViewComponent, testCase)
verify(control)
- var item0 = rectangleComponent.createObject(control, { color: "salmon" })
+ let item0 = rectangleComponent.createObject(control, { color: "salmon" })
verify(item0)
verify(isPolishScheduled(control))
verify(waitForItemPolished(control))
@@ -187,7 +188,7 @@ TestCase {
compare(item0.width, testCase.width)
compare(item0.height, testCase.height)
- var item1 = rectangleComponent.createObject(control, { color: "steelblue" })
+ let item1 = rectangleComponent.createObject(control, { color: "steelblue" })
verify(item1)
verify(isPolishScheduled(control))
verify(waitForItemPolished(control))
@@ -195,8 +196,8 @@ TestCase {
compare(item0.y, 0)
compare(item0.width, 0)
compare(item0.height, testCase.height)
- var handles = findHandles(control)
- var handle0 = handles[0]
+ let handles = findHandles(control)
+ let handle0 = handles[0]
compare(handle0.x, 0)
compare(handle0.y, 0)
compare(handle0.width, defaultHorizontalHandleWidth)
@@ -230,35 +231,35 @@ TestCase {
}
function test_changeAttachedPropertiesAfterCompletion() {
- var control = createTemporaryObject(threeZeroSizedItemsComponent, testCase)
+ let control = createTemporaryObject(threeZeroSizedItemsComponent, testCase)
verify(control)
- var item0 = control.itemAt(0)
+ let item0 = control.itemAt(0)
compare(item0.x, 0)
compare(item0.y, 0)
compare(item0.width, 0)
compare(item0.height, testCase.height)
- var handles = findHandles(control)
- var handle0 = handles[0]
+ let handles = findHandles(control)
+ let handle0 = handles[0]
compare(handle0.x, 0)
compare(handle0.y, 0)
compare(handle0.width, defaultHorizontalHandleWidth)
compare(handle0.height, testCase.height)
- var item1 = control.itemAt(1)
+ let item1 = control.itemAt(1)
compare(item1.x, defaultHorizontalHandleWidth)
compare(item1.y, 0)
compare(item1.width, 0)
compare(item1.height, testCase.height)
- var handle1 = handles[1]
+ let handle1 = handles[1]
compare(handle1.x, defaultHorizontalHandleWidth)
compare(handle1.y, 0)
compare(handle1.width, defaultHorizontalHandleWidth)
compare(handle1.height, testCase.height)
- var item2 = control.itemAt(2)
+ let item2 = control.itemAt(2)
compare(item2.x, defaultHorizontalHandleWidth * 2)
compare(item2.y, 0)
compare(item2.width, testCase.width - item2.x)
@@ -396,19 +397,19 @@ TestCase {
}
function test_useAttachedPropertiesIncorrectly_data() {
- var properties = [ "fillWidth", "fillHeight", "minimumWidth", "minimumHeight",
+ let properties = [ "fillWidth", "fillHeight", "minimumWidth", "minimumHeight",
"preferredWidth", "preferredHeight", "maximumWidth", "maximumHeight" ]
- var data = []
+ let data = []
- for (var i = 0; i < properties.length; ++i) {
- var property = properties[i]
+ for (let i = 0; i < properties.length; ++i) {
+ let property = properties[i]
data.push({ tag: "Item," + property, component: itemComponent, property: property,
expectedWarning: /.*SplitView: attached properties must be accessed through a direct child of SplitView/ })
}
- for (i = 0; i < properties.length; ++i) {
- property = properties[i]
+ for (let i = 0; i < properties.length; ++i) {
+ let property = properties[i]
data.push({ tag: "QtObject," + property, component: objectComponent, property: property,
expectedWarning: /.*SplitView: attached properties can only be used on Items/ })
}
@@ -418,7 +419,7 @@ TestCase {
function test_useAttachedPropertiesIncorrectly(data) {
// The object (whatever it may be) is not managed by a SplitView.
- var object = createTemporaryObject(data.component, testCase, { objectName: data.tag })
+ let object = createTemporaryObject(data.component, testCase, { objectName: data.tag })
verify(object)
ignoreWarning(data.expectedWarning)
@@ -427,12 +428,11 @@ TestCase {
}
function test_sizes_data() {
- var splitViewWidth = testCase.width
- var splitViewHeight = testCase.height
- var data = [
+ let splitViewWidth = testCase.width
+ let splitViewHeight = testCase.height
+ let data = [
{
- // When the combined size of items is too large, the non-fill items should just exceed
- // the size of the SplitView, exactly as they would were they in a RowLayout, for example.
+ // When the combined size of items is too large, make them fit.
tag: "fillItemOnLeft",
expectedGeometries: [
// We're the fill item, but since the combined implicitWidths
@@ -445,8 +445,8 @@ TestCase {
// Second handle.
{ x: 200 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth,
height: splitViewHeight },
- // The third item also gets its implicitWidth.
- { x: 200 + defaultHorizontalHandleWidth * 2, y: 0, width: 200, height: splitViewHeight }
+ // The third item is reduced from its implicitWidth to fit into SplitView.
+ { x: 200 + defaultHorizontalHandleWidth * 2, y: 0, width: 200 - 2 * defaultHorizontalHandleWidth, height: splitViewHeight }
]
},
{
@@ -463,8 +463,8 @@ TestCase {
// Second handle.
{ x: 0, y: 200 + defaultVerticalHandleHeight, width: splitViewWidth,
height: defaultVerticalHandleHeight },
- // The third item also gets its implicitHeight.
- { x: 0, y: 200 + defaultVerticalHandleHeight * 2, width: splitViewWidth, height: 200 }
+ // The third item is reduced from its implicitWidth to fit into SplitView.
+ { x: 0, y: 200 + defaultVerticalHandleHeight * 2, width: splitViewWidth, height: 200 - 2 * defaultVerticalHandleHeight }
]
},
{
@@ -489,9 +489,9 @@ TestCase {
}
function test_sizes(data) {
- var component = Qt.createComponent("splitview/" + data.tag + ".qml")
+ let component = Qt.createComponent("splitview/" + data.tag + ".qml")
compare(component.status, Component.Ready, component.errorString());
- var control = createTemporaryObject(component, testCase, { "handle": handleComponent })
+ let control = createTemporaryObject(component, testCase, { "handle": handleComponent })
verify(control)
compareSizes(control, data.expectedGeometries)
@@ -526,9 +526,9 @@ TestCase {
}
function test_resetAttachedProperties_data() {
- var splitViewWidth = testCase.width
- var splitViewHeight = testCase.height
- var data = [
+ let splitViewWidth = testCase.width
+ let splitViewHeight = testCase.height
+ let data = [
{
tag: "resetMinimumWidth",
orientation: Qt.Horizontal,
@@ -696,11 +696,11 @@ TestCase {
}
function test_resetAttachedProperties(data) {
- var control = createTemporaryObject(threeSizedItemsComponent, testCase,
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase,
{ "orientation": data.orientation })
verify(control)
- var splitItem = control.itemAt(data.splitItemIndex)
+ let splitItem = control.itemAt(data.splitItemIndex)
splitItem.SplitView[data.propertyName] = data.propertyValue
verify(isPolishScheduled(control))
verify(waitForItemPolished(control))
@@ -713,35 +713,35 @@ TestCase {
}
function test_orientation() {
- var control = createTemporaryObject(threeSizedItemsComponent, testCase)
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase)
verify(control)
- var item0 = control.itemAt(0)
+ let item0 = control.itemAt(0)
compare(item0.x, 0)
compare(item0.y, 0)
compare(item0.width, item0.implicitWidth)
compare(item0.height, testCase.height)
- var handles = findHandles(control)
- var handle0 = handles[0]
+ let handles = findHandles(control)
+ let handle0 = handles[0]
compare(handle0.x, item0.implicitWidth)
compare(handle0.y, 0)
compare(handle0.width, defaultHorizontalHandleWidth)
compare(handle0.height, testCase.height)
- var item1 = control.itemAt(1)
+ let item1 = control.itemAt(1)
compare(item1.x, item0.width + defaultHorizontalHandleWidth)
compare(item1.y, 0)
compare(item1.width, item1.implicitWidth)
compare(item1.height, testCase.height)
- var handle1 = handles[1]
+ let handle1 = handles[1]
compare(handle1.x, item1.x + item1.width)
compare(handle1.y, 0)
compare(handle1.width, defaultHorizontalHandleWidth)
compare(handle1.height, testCase.height)
- var item2 = control.itemAt(2)
+ let item2 = control.itemAt(2)
compare(item2.x, item0.width + item1.width + defaultHorizontalHandleWidth * 2)
compare(item2.y, 0)
compare(item2.width, testCase.width - item2.x)
@@ -775,6 +775,75 @@ TestCase {
compare(item2.height, testCase.height - item2.y)
}
+ Component {
+ id: threeSizedItemsComponentWithDefaultHandle
+
+ SplitView {
+ anchors.fill: parent
+
+ Rectangle {
+ objectName: "salmon"
+ color: objectName
+ implicitWidth: 25
+ implicitHeight: 25
+ }
+ Rectangle {
+ objectName: "navajowhite"
+ color: objectName
+ implicitWidth: 100
+ implicitHeight: 100
+ }
+ Rectangle {
+ objectName: "steelblue"
+ color: objectName
+ implicitWidth: 200
+ implicitHeight: 200
+ }
+ }
+ }
+
+ function test_orientationWithDefaultHandle() {
+ const control = createTemporaryObject(threeSizedItemsComponentWithDefaultHandle, testCase)
+ verify(control)
+
+ const item0 = control.itemAt(0)
+ compare(item0.x, 0)
+ compare(item0.y, 0)
+ compare(item0.width, item0.implicitWidth)
+ compare(item0.height, testCase.height)
+
+ const item1 = control.itemAt(1)
+ let handleDefaultWidth = item1.x - item0.width // Find default handle width
+ compare(item1.x, item0.width + handleDefaultWidth)
+ compare(item1.y, 0)
+ compare(item1.width, item1.implicitWidth)
+ compare(item1.height, testCase.height)
+
+ const item2 = control.itemAt(2)
+ compare(item2.x, item0.width + item1.width + handleDefaultWidth * 2)
+ compare(item2.y, 0)
+ compare(item2.width, testCase.width - item2.x)
+ compare(item2.height, testCase.height)
+
+ control.orientation = Qt.Vertical
+ verify(isPolishScheduled(control))
+ verify(waitForItemPolished(control))
+ compare(item0.x, 0)
+ compare(item0.y, 0)
+ compare(item0.width, testCase.width)
+ compare(item0.height, item0.implicitHeight)
+
+ compare(item1.x, 0)
+ compare(item1.y, item0.height + handleDefaultWidth)
+ compare(item1.width, testCase.width)
+ compare(item1.height, item1.implicitHeight)
+
+ compare(item2.x, 0)
+ compare(item2.y, item0.height + item1.height + handleDefaultWidth * 2)
+ compare(item2.width, testCase.width)
+ compare(item2.height, testCase.height - item2.y)
+ }
+
readonly property int splitViewMargins: 50
Component {
@@ -876,9 +945,9 @@ TestCase {
}
function test_dragHandle_data() {
- var splitViewWidth = testCase.width - splitViewMargins * 2
- var splitViewHeight = testCase.height - splitViewMargins * 2
- var data = [
+ let splitViewWidth = testCase.width - splitViewMargins * 2
+ let splitViewHeight = testCase.height - splitViewMargins * 2
+ let data = [
{
tag: "fillThirdItemAndDragFirstHandlePastRightSide",
component: threeSizedItemsComponent,
@@ -1034,7 +1103,7 @@ TestCase {
{ x: 0, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight },
{ x: defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight },
{ x: 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight },
- { x: 100 + defaultHorizontalHandleWidth * 2, y: 0, width: 200, height: splitViewHeight }
+ { x: 100 + defaultHorizontalHandleWidth * 2, y: 0, width: 200 - defaultHorizontalHandleWidth * 2, height: splitViewHeight }
],
expectedGeometriesAfterDrag: [
// The fill item is to the left of the handle at index 1, so the handle belongs
@@ -1067,7 +1136,7 @@ TestCase {
{ x: 0, y: 0, width: splitViewWidth, height: defaultVerticalHandleHeight },
{ x: 0, y: defaultVerticalHandleHeight, width: splitViewWidth, height: 100 },
{ x: 0, y: 100 + defaultVerticalHandleHeight, width: splitViewWidth, height: defaultVerticalHandleHeight },
- { x: 0, y: 100 + defaultVerticalHandleHeight * 2, width: splitViewWidth, height: 200 }
+ { x: 0, y: 100 + defaultVerticalHandleHeight * 2, width: splitViewWidth, height: 200 - defaultVerticalHandleHeight * 2 }
],
expectedGeometriesAfterDrag: [
// The fill item is to the top of the handle at index 1, so the handle belongs
@@ -1099,8 +1168,8 @@ TestCase {
{ x: defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight },
{ x: 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight },
// The second item's implicitWidth is 100, and ours is 200. The available width is 300,
- // so both items get their implicit widths.
- { x: 100 + defaultHorizontalHandleWidth * 2, y: 0, width: splitViewWidth - 100, height: splitViewHeight }
+ // so this item gets size 300 - 100 - 2 * 10 = 180.
+ { x: 100 + defaultHorizontalHandleWidth * 2, y: 0, width: splitViewWidth - 100 - 2 * defaultHorizontalHandleWidth, height: splitViewHeight }
],
// Should be unchanged.
expectedGeometriesAfterDrag: [
@@ -1108,7 +1177,7 @@ TestCase {
{ x: 0, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight },
{ x: defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight },
{ x: 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight },
- { x: 100 + defaultHorizontalHandleWidth * 2, y: 0, width: splitViewWidth - 100, height: splitViewHeight }
+ { x: 100 + defaultHorizontalHandleWidth * 2, y: 0, width: splitViewWidth - 100 - 2 * defaultHorizontalHandleWidth, height: splitViewHeight }
]
},
{
@@ -1123,7 +1192,9 @@ TestCase {
{ x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight },
{ x: 25 + defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight },
{ x: 25 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight },
- { x: 25 + 100 + defaultHorizontalHandleWidth * 2, y: 0, width: splitViewWidth - 100, height: splitViewHeight }
+ // The first item is the filling one, with minimum size 25. Second item is 100.
+ // The available size is 300, so third item is 300 - 100 - 25 - 2 * 10 = 155.
+ { x: 25 + 100 + defaultHorizontalHandleWidth * 2, y: 0, width: splitViewWidth - 100 - 25 - 2 * defaultHorizontalHandleWidth, height: splitViewHeight }
],
// Should be unchanged.
expectedGeometriesAfterDrag: [
@@ -1131,7 +1202,7 @@ TestCase {
{ x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight },
{ x: 25 + defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight },
{ x: 25 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight },
- { x: 25 + 100 + defaultHorizontalHandleWidth * 2, y: 0, width: splitViewWidth - 100, height: splitViewHeight }
+ { x: 25 + 100 + defaultHorizontalHandleWidth * 2, y: 0, width: splitViewWidth - 100 - 25 - 2 * defaultHorizontalHandleWidth, height: splitViewHeight }
]
},
{
@@ -1191,7 +1262,7 @@ TestCase {
}
function test_dragHandle(data) {
- var control = createTemporaryObject(data.component, testCase)
+ let control = createTemporaryObject(data.component, testCase)
verify(control)
control.orientation = data.orientation
@@ -1199,7 +1270,7 @@ TestCase {
// Ensure that there is space to drag outside of the SplitView.
control.anchors.margins = splitViewMargins
- var fillItem = control.itemAt(data.fillIndex)
+ let fillItem = control.itemAt(data.fillIndex)
if (control.orientation === Qt.Horizontal)
fillItem.SplitView.fillWidth = true
else
@@ -1211,13 +1282,13 @@ TestCase {
compareSizes(control, data.expectedGeometriesBeforeDrag, "before drag")
// Drag the handle.
- var handles = findHandles(control)
- var targetHandle = handles[data.handleIndex]
+ let handles = findHandles(control)
+ let targetHandle = handles[data.handleIndex]
verify(targetHandle.visible)
mousePress(targetHandle)
verify(control.resizing)
// newHandlePos is in scene coordinates, so map it to coordinates local to the handle.
- var localPos = testCase.mapToItem(targetHandle, data.newHandlePos.x, data.newHandlePos.y)
+ let localPos = testCase.mapToItem(targetHandle, data.newHandlePos.x, data.newHandlePos.y)
mouseMove(targetHandle, localPos.x - targetHandle.width / 2, localPos.y - targetHandle.height / 2)
verify(control.resizing)
compareSizes(control, data.expectedGeometriesAfterDrag, "after drag move")
@@ -1229,10 +1300,10 @@ TestCase {
}
function test_splitViewGeometryChanges_data() {
- var defaultSplitViewWidth = testCase.width
- var defaultSplitViewHeight = testCase.height
+ let defaultSplitViewWidth = testCase.width
+ let defaultSplitViewHeight = testCase.height
- var data = [
+ let data = [
{
tag: "growWidth",
orientation: Qt.Horizontal,
@@ -1296,7 +1367,7 @@ TestCase {
}
function test_splitViewGeometryChanges(data) {
- var control = createTemporaryObject(threeSizedItemsComponent, testCase,
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase,
{ "handle": handleComponent, "anchors.fill": undefined, "orientation": data.orientation })
verify(control)
@@ -1316,10 +1387,10 @@ TestCase {
}
function test_splitItemImplicitSizeChanges_data() {
- var defaultSplitViewWidth = testCase.width
- var defaultSplitViewHeight = testCase.height
+ let defaultSplitViewWidth = testCase.width
+ let defaultSplitViewHeight = testCase.height
- var data = [
+ let data = [
{
tag: "growImplicitWidth",
orientation: Qt.Horizontal,
@@ -1354,11 +1425,11 @@ TestCase {
// Tests that implicitWidth/Height changes in items are noticed by SplitView.
function test_splitItemImplicitSizeChanges(data) {
- var control = createTemporaryObject(threeSizedItemsComponent, testCase,
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase,
{ "handle": handleComponent, "orientation": data.orientation })
verify(control)
- var firstItem = control.itemAt(0)
+ let firstItem = control.itemAt(0)
if (data.hasOwnProperty("splitItemImplicitWidth"))
firstItem.implicitWidth = data.splitItemImplicitWidth
@@ -1392,10 +1463,10 @@ TestCase {
}
function test_handleChanges_data() {
- var splitViewWidth = testCase.width
- var splitViewHeight = testCase.height
+ let splitViewWidth = testCase.width
+ let splitViewHeight = testCase.height
- var data = [
+ let data = [
{
tag: "growHandleWidth",
orientation: Qt.Horizontal,
@@ -1455,7 +1526,7 @@ TestCase {
}
function test_handleChanges(data) {
- var control = createTemporaryObject(threeSizedItemsComponent, testCase,
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase,
{ "orientation": data.orientation })
verify(control)
@@ -1466,10 +1537,10 @@ TestCase {
}
function test_insertRemoveItems_data() {
- var splitViewWidth = testCase.width
- var splitViewHeight = testCase.height
+ let splitViewWidth = testCase.width
+ let splitViewHeight = testCase.height
- var data = [
+ let data = [
{
tag: "insertItemAtHorizontalEnd",
orientation: Qt.Horizontal,
@@ -1552,17 +1623,17 @@ TestCase {
}
function test_insertRemoveItems(data) {
- var control = createTemporaryObject(threeSizedItemsComponent, testCase,
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase,
{ "orientation": data.orientation })
verify(control)
if (data.hasOwnProperty("removeItemAtIndex")) {
- var itemToRemove = control.itemAt(data.removeItemAtIndex)
+ let itemToRemove = control.itemAt(data.removeItemAtIndex)
verify(itemToRemove)
control.removeItem(itemToRemove)
} else if (data.hasOwnProperty("insertItemAtIndex")) {
- var itemToAdd = smallRectComponent.createObject(control)
+ let itemToAdd = smallRectComponent.createObject(control)
control.insertItem(data.insertItemAtIndex, itemToAdd)
}
@@ -1572,19 +1643,19 @@ TestCase {
}
function test_removeAllItems() {
- var control = createTemporaryObject(threeSizedItemsComponent, testCase)
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase)
verify(control)
while (control.count > 0)
- var itemToRemove = control.removeItem(control.itemAt(0))
+ control.removeItem(control.itemAt(0))
// Shouldn't crash.
}
function test_hideItems_data() {
- var splitViewWidth = testCase.width
- var splitViewHeight = testCase.height
+ let splitViewWidth = testCase.width
+ let splitViewHeight = testCase.height
- var data = [
+ let data = [
{
tag: "hideItemAtHorizontalEnd",
orientation: Qt.Horizontal,
@@ -1655,12 +1726,12 @@ TestCase {
}
function test_hideItems(data) {
- var control = createTemporaryObject(threeSizedItemsComponent, testCase,
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase,
{ "orientation": data.orientation })
verify(control)
- for (var i = 0; i < data.hideIndices.length; ++i) {
- var itemToHide = control.itemAt(data.hideIndices[i])
+ for (let i = 0; i < data.hideIndices.length; ++i) {
+ let itemToHide = control.itemAt(data.hideIndices[i])
verify(itemToHide)
itemToHide.visible = false
}
@@ -1671,10 +1742,10 @@ TestCase {
}
function test_hideAndShowItems_data() {
- var splitViewWidth = testCase.width
- var splitViewHeight = testCase.height
+ let splitViewWidth = testCase.width
+ let splitViewHeight = testCase.height
- var data = [
+ let data = [
{
tag: "hideLastTwoHorizontalItems",
orientation: Qt.Horizontal,
@@ -1704,12 +1775,12 @@ TestCase {
}
function test_hideAndShowItems(data) {
- var control = createTemporaryObject(threeSizedItemsComponent, testCase,
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase,
{ "orientation": data.orientation })
verify(control)
- for (var i = 0; i < data.hideIndices.length; ++i) {
- var itemToHide = control.itemAt(data.hideIndices[i])
+ for (let i = 0; i < data.hideIndices.length; ++i) {
+ let itemToHide = control.itemAt(data.hideIndices[i])
verify(itemToHide)
itemToHide.visible = false
}
@@ -1717,8 +1788,8 @@ TestCase {
verify(waitForItemPolished(control))
compareSizes(control, data.expectedGeometriesAfterHiding, "after hiding")
- for (i = 0; i < data.showIndices.length; ++i) {
- var itemToShow = control.itemAt(data.showIndices[i])
+ for (let i = 0; i < data.showIndices.length; ++i) {
+ let itemToShow = control.itemAt(data.showIndices[i])
verify(itemToShow)
itemToShow.visible = true
}
@@ -1728,10 +1799,10 @@ TestCase {
}
function test_moveHiddenItems_data() {
- var splitViewWidth = testCase.width
- var splitViewHeight = testCase.height
+ let splitViewWidth = testCase.width
+ let splitViewHeight = testCase.height
- var data = [
+ let data = [
{
tag: "hideSecondItemAndMoveItToFirst",
orientation: Qt.Horizontal,
@@ -1767,12 +1838,12 @@ TestCase {
}
function test_moveHiddenItems(data) {
- var control = createTemporaryObject(threeSizedItemsComponent, testCase,
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase,
{ "orientation": data.orientation })
verify(control)
- for (var i = 0; i < data.hideIndices.length; ++i) {
- var itemToHide = control.itemAt(data.hideIndices[i])
+ for (let i = 0; i < data.hideIndices.length; ++i) {
+ let itemToHide = control.itemAt(data.hideIndices[i])
verify(itemToHide)
itemToHide.visible = false
}
@@ -1782,8 +1853,8 @@ TestCase {
verify(waitForItemPolished(control))
compareSizes(control, data.expectedGeometriesAfterMoving, "after moving")
- for (i = 0; i < data.showIndices.length; ++i) {
- var itemToShow = control.itemAt(data.showIndices[i])
+ for (let i = 0; i < data.showIndices.length; ++i) {
+ let itemToShow = control.itemAt(data.showIndices[i])
verify(itemToShow)
itemToShow.visible = true
}
@@ -1802,10 +1873,10 @@ TestCase {
}
function test_draggingHandleInFlickable() {
- var flickable = createTemporaryObject(flickableComponent, testCase)
+ let flickable = createTemporaryObject(flickableComponent, testCase)
verify(flickable)
- var control = threeSizedItemsComponent.createObject(flickable.contentItem)
+ let control = threeSizedItemsComponent.createObject(flickable.contentItem)
verify(control)
control.anchors.fill = undefined
@@ -1816,19 +1887,19 @@ TestCase {
verify(isPolishScheduled(control))
verify(waitForItemPolished(control))
- var contentXSpy = signalSpyComponent.createObject(flickable,
+ let contentXSpy = signalSpyComponent.createObject(flickable,
{ target: flickable, signalName: "contentXChanged" })
verify(contentXSpy.valid)
- var contentYSpy = signalSpyComponent.createObject(flickable,
+ let contentYSpy = signalSpyComponent.createObject(flickable,
{ target: flickable, signalName: "contentYChanged" })
verify(contentYSpy.valid)
// Drag the first handle to the right;
// the flickable's contentX and contentY shouldn't change.
- var firstItem = control.itemAt(0)
- var firstItemOriginalWidth = firstItem.width
- var handles = findHandles(control)
- var firstHandle = handles[0]
+ let firstItem = control.itemAt(0)
+ let firstItemOriginalWidth = firstItem.width
+ let handles = findHandles(control)
+ let firstHandle = handles[0]
// Add some vertical movement in there as well.
mouseDrag(firstHandle, firstHandle.width / 2, firstHandle.height / 2, 100, 50)
compare(contentXSpy.count, 0)
@@ -1839,7 +1910,7 @@ TestCase {
control.orientation = Qt.Vertical
control.width = control.parent.width - 100
control.height = 400
- var firstItemOriginalHeight = firstItem.height
+ let firstItemOriginalHeight = firstItem.height
verify(isPolishScheduled(control))
verify(waitForItemPolished(control))
@@ -2284,14 +2355,14 @@ TestCase {
if ((Qt.platform.pluginName === "offscreen") || (Qt.platform.pluginName === "minimal"))
skip("Mouse hovering not functional on offscreen/minimal platforms")
- var control = createTemporaryObject(threeSizedItemsComponent, testCase)
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase)
verify(control)
control.anchors.margins = 50
- var handles = findHandles(control)
- var firstHandle = handles[0]
+ let handles = findHandles(control)
+ let firstHandle = handles[0]
- var handleCenter = control.mapFromItem(firstHandle, firstHandle.width / 2, firstHandle.height / 2)
+ let handleCenter = control.mapFromItem(firstHandle, firstHandle.width / 2, firstHandle.height / 2)
// Test fails if we don't do two moves for some reason...
mouseMove(control, handleCenter.x, handleCenter.y)
mouseMove(control, handleCenter.x, handleCenter.y)
@@ -2316,15 +2387,15 @@ TestCase {
if ((Qt.platform.pluginName === "offscreen") || (Qt.platform.pluginName === "minimal"))
skip("Mouse hovering not functional on offscreen/minimal platforms")
- var control = createTemporaryObject(threeSizedItemsComponent, testCase)
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase)
verify(control)
control.anchors.margins = 50
- var handles = findHandles(control)
- var firstHandle = handles[0]
+ let handles = findHandles(control)
+ let firstHandle = handles[0]
// First, ensure that the handle is hovered + pressed.
- var handleCenter = control.mapFromItem(firstHandle, firstHandle.width / 2, firstHandle.height / 2)
+ let handleCenter = control.mapFromItem(firstHandle, firstHandle.width / 2, firstHandle.height / 2)
// Test fails if we don't do two moves for some reason...
mouseMove(control, handleCenter.x, handleCenter.y)
mouseMove(control, handleCenter.x, handleCenter.y)
@@ -2342,8 +2413,8 @@ TestCase {
compare(handles.length, 1)
// No handles should be hovered/pressed.
- for (var i = 0; i < handles.length; ++i) {
- var handle = handles[i]
+ for (let i = 0; i < handles.length; ++i) {
+ let handle = handles[i]
verify(!handle.SplitHandle.hovered, "handle at index " + i + " should not be hovered")
verify(!handle.SplitHandle.pressed, "handle at index " + i + " should not be hovered")
}
@@ -2366,16 +2437,16 @@ TestCase {
}
function test_saveAndRestoreState(data) {
- var control = createTemporaryObject(threeSizedItemsComponent, testCase, { orientation: data.orientation })
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase, { orientation: data.orientation })
verify(control)
compare(control.orientation, data.orientation)
- var lastItem = control.itemAt(2)
+ let lastItem = control.itemAt(2)
verify(lastItem)
lastItem.SplitView[data.propertyName] = data.propertyValue
// Save the state.
- var settings = createTemporaryObject(settingsComponent, testCase)
+ let settings = createTemporaryObject(settingsComponent, testCase)
verify(settings)
settings.setValue("splitView", control.saveState())
@@ -2394,11 +2465,11 @@ TestCase {
}
function test_changePreferredSizeDuringLayout() {
- var control = createTemporaryObject(threeSizedItemsComponent, testCase)
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase)
verify(control)
- var firstItem = control.itemAt(0)
- var secondItem = control.itemAt(1)
+ let firstItem = control.itemAt(0)
+ let secondItem = control.itemAt(1)
secondItem.widthChanged.connect(function() {
if (secondItem.width < 10)
firstItem.SplitView.preferredWidth = 50
@@ -2439,28 +2510,31 @@ TestCase {
// m_ignoreNextDelayedLayoutRequest doesn't interfere with any action from
// the user that results in a delayed layout.
function test_changePreferredSizeDuringLayoutWhileDraggingHandle() {
- var control = createTemporaryObject(threeSizedItemsComponent, testCase)
+ let control = createTemporaryObject(threeSizedItemsComponent, testCase)
verify(control)
- var firstItem = control.itemAt(0)
- var secondItem = control.itemAt(1)
+ let firstItem = control.itemAt(0)
+ let secondItem = control.itemAt(1)
firstItem.widthChanged.connect(function() {
if (firstItem.width === 0)
secondItem.SplitView.preferredWidth = 50
})
// Start dragging the handle.
- var handles = findHandles(control)
- var targetHandle = handles[0]
+ let handles = findHandles(control)
+ let targetHandle = handles[0]
mousePress(targetHandle)
verify(control.resizing)
- var localPos = testCase.mapToItem(targetHandle, 15, testCase.height / 2)
+ let localPos = testCase.mapToItem(targetHandle, 15, testCase.height / 2)
// Move the handle to the very left, so that the item's width becomes zero.
mouseMove(targetHandle, -100, targetHandle.height / 2)
verify(control.resizing)
compare(firstItem.width, 0)
compare(secondItem.SplitView.preferredWidth, 50)
+ // Wait for polish so item width becomes preferredWidth
+ verify(isPolishScheduled(control))
+ verify(waitForItemPolished(control))
compare(secondItem.width, 50)
mouseRelease(targetHandle, -100, targetHandle.height / 2, Qt.LeftButton)
verify(!control.resizing)
@@ -2476,7 +2550,7 @@ TestCase {
// QTBUG-79270
function test_hideSplitViewWithOneItem() {
- var control = createTemporaryObject(oneItemComponent, testCase)
+ let control = createTemporaryObject(oneItemComponent, testCase)
verify(control)
// Shouldn't be an assertion failure.
control.visible = false
@@ -2485,7 +2559,7 @@ TestCase {
// QTBUG-79302: ensure that the Repeater's items are actually generated.
// test_dragHandle:repeater tests dragging behavior with a Repeater.
function test_repeater(data) {
- var control = createTemporaryObject(repeaterSplitViewComponent, testCase)
+ let control = createTemporaryObject(repeaterSplitViewComponent, testCase)
verify(control)
compare(control.repeater.count, 3)
compare(control.contentChildren.length, 3)
@@ -2515,15 +2589,15 @@ TestCase {
if (Qt.platform.pluginName === "offscreen" || Qt.platform.pluginName === "minimal")
skip("Mouse hovering not functional on offscreen/minimal platforms")
- var control = createTemporaryObject(hoverableChildrenSplitViewComponent, testCase)
+ let control = createTemporaryObject(hoverableChildrenSplitViewComponent, testCase)
verify(control)
verify(isPolishScheduled(control))
verify(waitForItemPolished(control))
// Move the mouse over the handle.
- var handles = findHandles(control)
- var targetHandle = handles[0]
+ let handles = findHandles(control)
+ let targetHandle = handles[0]
// Test fails if we don't do two moves for some reason... QTBUG-94968
mouseMove(targetHandle, targetHandle.width / 2, targetHandle.height / 2)
mouseMove(targetHandle, targetHandle.width / 2, targetHandle.height / 2)
@@ -2603,4 +2677,88 @@ TestCase {
verify(!firstHandle.SplitHandle.pressed)
compare(firstItem.width, 125)
}
+
+ Component {
+ id: hiddenItemComponent
+
+ SplitView {
+ anchors.fill: parent
+ handle: handleComponent
+ orientation: Qt.Horizontal
+
+ component SplitItem: Rectangle {
+ objectName: labelText
+
+ SplitView.preferredWidth: 50
+ SplitView.fillHeight: true
+
+ required property string labelText
+
+ Text {
+ anchors.fill: parent
+ wrapMode: Text.Wrap
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: `${parent.labelText} - width: ${parent.width.toFixed(2)}`
+ }
+ }
+
+ SplitItem {
+ color: "blue"
+ labelText: "View 1"
+ }
+ SplitItem {
+ color: "red"
+ labelText: "View 2 (hidden)"
+ visible: false
+ }
+ SplitItem {
+ color: "purple"
+ labelText: "View 3"
+ }
+ SplitItem {
+ color: "yellow"
+ labelText: "View 4"
+ }
+ }
+ }
+
+ function test_resizeHiddenItem() {
+ let control = createTemporaryObject(hiddenItemComponent, testCase)
+ verify(control)
+
+ const standardItemWidth = 50
+ let expectedGeometries = [
+ // First item.
+ { x: 0, y: 0, width: standardItemWidth, height: control.height },
+ // First handle.
+ { x: standardItemWidth, y: 0, width: defaultHorizontalHandleWidth, height: control.height },
+ // The second item and its handle are hidden.
+ { hidden: true },
+ { hidden: true },
+ // Third item.
+ { x: standardItemWidth + defaultHorizontalHandleWidth, y: 0, width: standardItemWidth, height: control.height },
+ // Third handle.
+ { x: (standardItemWidth * 2) + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: control.height },
+ // Fourth item.
+ { x: (standardItemWidth * 2) + (defaultHorizontalHandleWidth * 2), y: 0,
+ width: control.width - (standardItemWidth * 2) - (defaultHorizontalHandleWidth * 2), height: control.height }
+ ]
+ compareSizes(control, expectedGeometries, "before dragging handle")
+
+ // Drag the third handle to the right.
+ let handles = findHandles(control)
+ let thirdHandle = handles[2]
+ // The third (index 4 here) item should get one pixel bigger, and the fourth one pixel smaller.
+ ++expectedGeometries[4].width
+ ++expectedGeometries[5].x // handle
+ ++expectedGeometries[6].x
+ --expectedGeometries[6].width
+ // Use individual events rather than mouseDrag because that will move it past the drag threshold,
+ // which we don't want, since we only want to move by 1 pixel.
+ mousePress(thirdHandle)
+ mouseMove(thirdHandle, thirdHandle.width / 2 + 1, thirdHandle.height / 2, 16)
+ mouseRelease(thirdHandle)
+ compareSizes(control, expectedGeometries, "after dragging handle")
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_stackview.qml b/tests/auto/quickcontrols/controls/data/tst_stackview.qml
index 8584385cbf..7e373c66ff 100644
--- a/tests/auto/quickcontrols/controls/data/tst_stackview.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_stackview.qml
@@ -1,13 +1,17 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+pragma ComponentBehavior: Bound
import QtQuick
import QtTest
import QtQuick.Controls
+import QtQuick.Templates as T
import Qt.test.controls
TestCase {
id: testCase
+ objectName: name
width: 200
height: 200
visible: true
@@ -16,10 +20,10 @@ TestCase {
Item { id: item }
Component { id: textField; TextField { } }
- Component { id: component; Item { } }
+ Component { id: itemComponent; Item { } }
Component {
- id: stackView
+ id: stackViewComponent
StackView { }
}
@@ -30,60 +34,62 @@ TestCase {
Component { id: withRequired; Item { required property int i }}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
- let control = createTemporaryObject(stackView, testCase)
+ function test_defaults() {
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
}
function test_initialItem() {
- var control1 = createTemporaryObject(stackView, testCase)
+ let control1 = createTemporaryObject(stackViewComponent, testCase)
verify(control1)
compare(control1.currentItem, null)
control1.destroy()
- var control2 = createTemporaryObject(stackView, testCase, {initialItem: item})
+ let control2 = createTemporaryObject(stackViewComponent, testCase, {initialItem: item})
verify(control2)
compare(control2.currentItem, item)
control2.destroy()
- var control3 = createTemporaryObject(stackView, testCase, {initialItem: component})
+ let control3 = createTemporaryObject(stackViewComponent, testCase, {initialItem: itemComponent})
verify(control3)
verify(control3.currentItem)
control3.destroy()
}
function test_currentItem() {
- var control = createTemporaryObject(stackView, testCase, {initialItem: item})
+ let control = createTemporaryObject(stackViewComponent, testCase, {initialItem: item})
verify(control)
compare(control.currentItem, item)
- control.push(component)
+ control.push(itemComponent)
verify(control.currentItem !== item)
control.pop(StackView.Immediate)
compare(control.currentItem, item)
}
function test_busy() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
compare(control.busy, false)
- var busyCount = 0
- var busySpy = signalSpy.createObject(control, {target: control, signalName: "busyChanged"})
+ let busyCount = 0
+ let busySpy = signalSpy.createObject(control, {target: control, signalName: "busyChanged"})
verify(busySpy.valid)
- control.push(component)
+ control.push(itemComponent)
compare(control.busy, false)
compare(busySpy.count, busyCount)
- control.push(component)
+ control.push(itemComponent)
compare(control.busy, true)
compare(busySpy.count, ++busyCount)
tryCompare(control, "busy", false)
compare(busySpy.count, ++busyCount)
- control.replace(component)
+ control.replace(itemComponent)
compare(control.busy, true)
compare(busySpy.count, ++busyCount)
tryCompare(control, "busy", false)
@@ -98,14 +104,14 @@ TestCase {
control.pushEnter = null
control.pushExit = null
- control.push(component)
+ control.push(itemComponent)
compare(control.busy, false)
compare(busySpy.count, busyCount)
control.replaceEnter = null
control.replaceExit = null
- control.replace(component)
+ control.replace(itemComponent)
compare(control.busy, false)
compare(busySpy.count, busyCount)
@@ -118,15 +124,15 @@ TestCase {
}
function test_status() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
- var item1 = component.createObject(control)
+ let item1 = itemComponent.createObject(control)
compare(item1.StackView.status, StackView.Inactive)
control.push(item1)
compare(item1.StackView.status, StackView.Active)
- var item2 = component.createObject(control)
+ let item2 = itemComponent.createObject(control)
compare(item2.StackView.status, StackView.Inactive)
control.push(item2)
compare(item2.StackView.status, StackView.Activating)
@@ -142,15 +148,15 @@ TestCase {
}
function test_index() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
- var item1 = component.createObject(control)
+ let item1 = itemComponent.createObject(control)
compare(item1.StackView.index, -1)
control.push(item1, StackView.Immediate)
compare(item1.StackView.index, 0)
- var item2 = component.createObject(control)
+ let item2 = itemComponent.createObject(control)
compare(item2.StackView.index, -1)
control.push(item2, StackView.Immediate)
compare(item2.StackView.index, 1)
@@ -162,15 +168,15 @@ TestCase {
}
function test_view() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
- var item1 = component.createObject(control)
+ let item1 = itemComponent.createObject(control)
compare(item1.StackView.view, null)
control.push(item1, StackView.Immediate)
compare(item1.StackView.view, control)
- var item2 = component.createObject(control)
+ let item2 = itemComponent.createObject(control)
compare(item2.StackView.view, null)
control.push(item2, StackView.Immediate)
compare(item2.StackView.view, control)
@@ -182,13 +188,13 @@ TestCase {
}
function test_depth() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
- var depthChanges = 0
- var emptyChanges = 0
- var depthSpy = signalSpy.createObject(control, {target: control, signalName: "depthChanged"})
- var emptySpy = signalSpy.createObject(control, {target: control, signalName: "emptyChanged"})
+ let depthChanges = 0
+ let emptyChanges = 0
+ let depthSpy = signalSpy.createObject(control, {target: control, signalName: "depthChanged"})
+ let emptySpy = signalSpy.createObject(control, {target: control, signalName: "emptyChanged"})
verify(depthSpy.valid)
verify(emptySpy.valid)
compare(control.depth, 0)
@@ -206,25 +212,25 @@ TestCase {
compare(control.empty, true)
compare(emptySpy.count, ++emptyChanges)
- control.push(component, StackView.Immediate)
+ control.push(itemComponent, StackView.Immediate)
compare(control.depth, 1)
compare(depthSpy.count, ++depthChanges)
compare(control.empty, false)
compare(emptySpy.count, ++emptyChanges)
- control.push(component, StackView.Immediate)
+ control.push(itemComponent, StackView.Immediate)
compare(control.depth, 2)
compare(depthSpy.count, ++depthChanges)
compare(control.empty, false)
compare(emptySpy.count, emptyChanges)
- control.replace(component, StackView.Immediate)
+ control.replace(itemComponent, StackView.Immediate)
compare(control.depth, 2)
compare(depthSpy.count, depthChanges)
compare(control.empty, false)
compare(emptySpy.count, emptyChanges)
- control.replace([component, component], StackView.Immediate)
+ control.replace([itemComponent, itemComponent], StackView.Immediate)
compare(control.depth, 3)
compare(depthSpy.count, ++depthChanges)
compare(control.empty, false)
@@ -253,12 +259,21 @@ TestCase {
compare(depthSpy.count, depthChanges)
compare(control.empty, true)
compare(emptySpy.count, emptyChanges)
+
+ control.push(item, StackView.PushTransition)
+ compare(depthSpy.count, ++depthChanges)
+ compare(emptySpy.count, ++emptyChanges)
+ compare(control.depth, 1)
+ control.clear(StackView.PopTransition)
+ compare(depthSpy.count, ++depthChanges)
+ compare(emptySpy.count, ++emptyChanges)
+ compare(control.depth, 0)
}
function test_size() {
- var container = createTemporaryObject(component, testCase, {width: 200, height: 200})
+ let container = createTemporaryObject(itemComponent, testCase, {width: 200, height: 200})
verify(container)
- var control = stackView.createObject(container, {width: 100, height: 100})
+ let control = stackViewComponent.createObject(container, {width: 100, height: 100})
verify(control)
container.width += 10
@@ -286,7 +301,7 @@ TestCase {
compare(item.height, control.height)
}
- function test_focus_data() {
+ function test_focus_data() : var {
return [
{ tag: "true", focus: true, forceActiveFocus: false },
{ tag: "false", focus: false, forceActiveFocus: false },
@@ -294,8 +309,8 @@ TestCase {
]
}
- function test_focus(data) {
- var control = createTemporaryObject(stackView, testCase, {initialItem: item, width: 200, height: 200})
+ function test_focus(data: var) {
+ let control = createTemporaryObject(stackViewComponent, testCase, {initialItem: item, width: 200, height: 200})
verify(control)
if (data.focus)
@@ -304,7 +319,7 @@ TestCase {
control.forceActiveFocus()
compare(control.activeFocus, data.focus || data.forceActiveFocus)
- var page = control.push(textField, StackView.Immediate)
+ let page = control.push(textField, StackView.Immediate)
verify(page)
compare(control.currentItem, page)
compare(page.activeFocus, control.activeFocus)
@@ -316,12 +331,12 @@ TestCase {
}
function test_find() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
- var item1 = component.createObject(control, {objectName: "1"})
- var item2 = component.createObject(control, {objectName: "2"})
- var item3 = component.createObject(control, {objectName: "3"})
+ let item1 = itemComponent.createObject(control, {objectName: "1"})
+ let item2 = itemComponent.createObject(control, {objectName: "2"})
+ let item3 = itemComponent.createObject(control, {objectName: "3"})
control.push(item1, StackView.Immediate)
control.push(item2, StackView.Immediate)
@@ -341,10 +356,10 @@ TestCase {
}
function test_get() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
- control.push([item, component, component], StackView.Immediate)
+ control.push([item, itemComponent, itemComponent], StackView.Immediate)
verify(control.get(0, StackView.DontLoad))
compare(control.get(0, StackView.ForceLoad), item)
@@ -355,8 +370,10 @@ TestCase {
verify(control.get(2, StackView.ForceLoad))
}
+ property bool qmlProperty
+
function test_push() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
// missing arguments
@@ -372,58 +389,163 @@ TestCase {
control.push(Qt.createQmlObject('import QtQml; QtObject { }', control))
// push(item)
- var item1 = component.createObject(control, {objectName:"1"})
+ let item1 = itemComponent.createObject(control, {objectName:"1"})
compare(control.push(item1, StackView.Immediate), item1)
compare(control.depth, 1)
compare(control.currentItem, item1)
// push([item])
- var item2 = component.createObject(control, {objectName:"2"})
+ let item2 = itemComponent.createObject(control, {objectName:"2"})
compare(control.push([item2], StackView.Immediate), item2)
compare(control.depth, 2)
compare(control.currentItem, item2)
// push(item, {properties})
- var item3 = component.createObject(control)
+ let item3 = itemComponent.createObject(control)
compare(control.push(item3, {objectName:"3"}, StackView.Immediate), item3)
compare(item3.objectName, "3")
compare(control.depth, 3)
compare(control.currentItem, item3)
// push([item, {properties}])
- var item4 = component.createObject(control)
+ let item4 = itemComponent.createObject(control)
compare(control.push([item4, {objectName:"4"}], StackView.Immediate), item4)
compare(item4.objectName, "4")
compare(control.depth, 4)
compare(control.currentItem, item4)
// push(component, {properties})
- var item5 = control.push(component, {objectName:"5"}, StackView.Immediate)
+ let item5 = control.push(itemComponent, {objectName:"5"}, StackView.Immediate)
compare(item5.objectName, "5")
compare(control.depth, 5)
compare(control.currentItem, item5)
// push([component, {properties}])
- var item6 = control.push([component, {objectName:"6"}], StackView.Immediate)
+ let item6 = control.push([itemComponent, {objectName:"6"}], StackView.Immediate)
compare(item6.objectName, "6")
compare(control.depth, 6)
compare(control.currentItem, item6)
+
+ // push([component, {binding}]) - with JS variable in binding
+ let jsVariable = false
+ let item7 = control.push([itemComponent, {objectName: Qt.binding(() => {
+ return jsVariable.toString() })}], StackView.Immediate)
+ compare(item7.objectName, "false")
+ compare(control.depth, 7)
+ compare(control.currentItem, item7)
+ jsVariable = true
+ expectFailContinue("", "QTBUG-114959")
+ compare(item7.objectName, "true")
+
+ // push([component, {binding}]) - with QML property in binding
+ qmlProperty = false
+ let item8 = control.push([itemComponent, {objectName: Qt.binding(() => {
+ return testCase.qmlProperty.toString() })}], StackView.Immediate)
+ compare(item8.objectName, "false")
+ compare(control.depth, 8)
+ compare(control.currentItem, item8)
+ qmlProperty = true
+ compare(item8.objectName, "true")
+ }
+
+ function test_pushNew() {
+ let control = createTemporaryObject(stackViewComponent, testCase)
+ verify(control)
+
+ // Passing the wrong type to a strongly-typed function results in an exception.
+ let exceptionThrown = false
+ try {
+ ignoreWarning(/Could not convert argument 0 at/)
+ const stackTraceLineCount = 5
+ for (let i = 0; i < stackTraceLineCount; ++i)
+ ignoreWarning(/.*@.*qml/)
+ control.pushItem(Qt.createQmlObject('import QtQml; QtObject { }', control))
+ } catch (e) {
+ exceptionThrown = true
+ }
+ verify(exceptionThrown)
+ compare(control.depth, 0)
+
+ // pushItem(item)
+ let item1 = itemComponent.createObject(control, {objectName:"1"})
+ compare(control.pushItem(item1, {}, StackView.Immediate), item1)
+ compare(control.depth, 1)
+ compare(control.currentItem, item1)
+
+ // pushItems([item])
+ let item2 = itemComponent.createObject(control, {objectName:"2"})
+ compare(control.pushItems([item2], StackView.Immediate), item2)
+ compare(control.depth, 2)
+ compare(control.currentItem, item2)
+
+ // pushItems([item, component, url])
+ let item3 = itemComponent.createObject(control)
+ let actualCurrent = control.pushItems([item3, itemComponent, Qt.resolvedUrl("stackview/Rect.qml")], StackView.Immediate)
+ let expectedCurrent = control.get(control.depth - 1, StackView.DontLoad)
+ compare(actualCurrent, expectedCurrent)
+ compare(control.depth, 5)
+ compare(control.currentItem, expectedCurrent)
+
+ // pushItems([item, {properties}])
+ let item4 = itemComponent.createObject(control)
+ compare(control.pushItems([item4, {objectName:"4"}], StackView.Immediate), item4)
+ compare(item4.objectName, "4")
+ compare(control.depth, 6)
+ compare(control.currentItem, item4)
+
+ // pushItems([item, {properties}, component, {properties}, url, {properties}])
+ let item5 = itemComponent.createObject(control)
+ let item7 = control.pushItems([
+ item5, {objectName: "object5"},
+ itemComponent, {objectName: "object6"},
+ Qt.resolvedUrl("stackview/Rect.qml"), {objectName: "object7"}
+ ],
+ StackView.Immediate)
+ item5 = control.get(control.depth - 3, StackView.ForceLoad)
+ let item6 = control.get(control.depth - 2, StackView.ForceLoad)
+ compare(item7, control.get(control.depth - 1, StackView.ForceLoad))
+ compare(item5.objectName, "object5")
+ compare(item6.objectName, "object6")
+ compare(item7.objectName, "object7")
+ compare(control.depth, 9)
+ compare(control.currentItem, item7)
+
+ // pushItems([component, {binding}]) - with JS variable in binding
+ let jsVariable = false
+ let item8 = control.pushItems([itemComponent, {objectName: Qt.binding(() => {
+ return jsVariable.toString() })}], StackView.Immediate)
+ compare(item8.objectName, "false")
+ compare(control.depth, 10)
+ compare(control.currentItem, item8)
+ jsVariable = true
+ expectFailContinue("", "QTBUG-114959")
+ compare(item8.objectName, "true")
+
+ // pushItems([component, {binding}]) - with QML property in binding
+ qmlProperty = false
+ let item9 = control.pushItems([itemComponent, {objectName: Qt.binding(() => {
+ return testCase.qmlProperty.toString() })}], StackView.Immediate)
+ compare(item9.objectName, "false")
+ compare(control.depth, 11)
+ compare(control.currentItem, item9)
+ qmlProperty = true
+ compare(item9.objectName, "true")
}
// Escape special Regexp characters with a '\' (backslash) prefix so that \a str can be
// used as a Regexp pattern.
- function escapeRegExp(str) {
+ function escapeRegExp(str: string): string {
// "$&" is the last matched substring
return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
function test_pop() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
- var items = []
- for (var i = 0; i < 7; ++i)
- items.push(component.createObject(control, {objectName:i}))
+ let items = []
+ for (let i = 0; i < 7; ++i)
+ items.push(itemComponent.createObject(control, {objectName:i}))
control.push(items, StackView.Immediate)
@@ -451,7 +573,7 @@ TestCase {
compare(control.currentItem, items[2])
// don't pop non-existent item
- ignoreWarning(new RegExp(".*QML StackView: pop: unknown argument: " + escapeRegExp(testCase.toString())))
+ ignoreWarning(new RegExp(".*QML StackView: pop: can't find item to pop: " + escapeRegExp(testCase.toString())))
compare(control.pop(testCase, StackView.Immediate), null)
compare(control.depth, 3)
compare(control.currentItem, items[2])
@@ -462,8 +584,75 @@ TestCase {
compare(control.currentItem, items[0])
}
+ function test_popNew() {
+ let control = createTemporaryObject(stackViewComponent, testCase)
+ verify(control)
+
+ let items = []
+ for (let i = 0; i < 7; ++i)
+ items.push(itemComponent.createObject(control, {objectName:i}))
+
+ compare(control.pushItems(items, StackView.Immediate), items[6])
+ compare(control.depth, 7)
+
+ // pop the top most item
+ compare(control.popCurrentItem(StackView.Immediate), items[6])
+ compare(control.depth, 6)
+ compare(control.currentItem, items[5])
+
+ // pop down to the current item (does nothing as it's already the top-most item)
+ compare(control.popToItem(control.currentItem, StackView.Immediate), null)
+ compare(control.depth, 6)
+ compare(control.currentItem, items[5])
+
+ // pop down to (but not including) the Nth item
+ compare(control.popToItem(items[3], StackView.Immediate), items[5])
+ compare(control.depth, 4)
+ compare(control.currentItem, items[3])
+
+ // pop the top most item
+ compare(control.popCurrentItem(StackView.Immediate), items[3])
+ compare(control.depth, 3)
+ compare(control.currentItem, items[2])
+
+ // don't pop non-existent item
+ ignoreWarning(new RegExp(".*QML StackView: pop: can't find item to pop: TestCase.*"))
+ compare(control.popToItem(testCase, StackView.Immediate), null)
+ compare(control.depth, 3)
+ compare(control.currentItem, items[2])
+
+ // The new functions don't support passing null.
+ ignoreWarning(new RegExp(".*QML StackView: pop: item cannot be null"))
+ compare(control.popToItem(null, StackView.Immediate), null)
+ compare(control.depth, 3)
+ compare(control.currentItem, items[2])
+
+ // Test that popToIndex pops down to an Nth item.
+ control.clear()
+ compare(control.depth, 0)
+
+ items = []
+ for (let i = 0; i < 3; ++i)
+ items.push(itemComponent.createObject(control, { objectName: i }))
+ compare(control.pushItems(items, StackView.Immediate), items[2])
+ compare(control.depth, 3)
+
+ compare(control.popToIndex(1, StackView.Immediate), items[2])
+ compare(control.depth, 2)
+
+ compare(control.popToIndex(0, StackView.Immediate), items[1])
+ compare(control.depth, 1)
+
+ // Also check that popCurrentItem still pops when depth is 1,
+ // because pop() doesn't, and we don't want that behavior with the new function.
+ compare(control.popCurrentItem(StackView.Immediate), items[0])
+
+ ignoreWarning(new RegExp(".*QML StackView: pop: no items to pop"))
+ compare(control.popCurrentItem(StackView.Immediate), null)
+ }
+
function test_replace() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
// missing arguments
@@ -479,71 +668,116 @@ TestCase {
compare(control.replace(Qt.createQmlObject('import QtQml; QtObject { }', control)), null)
// replace(item)
- var item1 = component.createObject(control, {objectName:"1"})
+ let item1 = itemComponent.createObject(control, {objectName:"1"})
compare(control.replace(item1, StackView.Immediate), item1)
compare(control.depth, 1)
compare(control.currentItem, item1)
// replace([item])
- var item2 = component.createObject(control, {objectName:"2"})
+ let item2 = itemComponent.createObject(control, {objectName:"2"})
compare(control.replace([item2], StackView.Immediate), item2)
compare(control.depth, 1)
compare(control.currentItem, item2)
// replace(item, {properties})
- var item3 = component.createObject(control)
+ let item3 = itemComponent.createObject(control)
compare(control.replace(item3, {objectName:"3"}, StackView.Immediate), item3)
compare(item3.objectName, "3")
compare(control.depth, 1)
compare(control.currentItem, item3)
// replace([item, {properties}])
- var item4 = component.createObject(control)
+ let item4 = itemComponent.createObject(control)
compare(control.replace([item4, {objectName:"4"}], StackView.Immediate), item4)
compare(item4.objectName, "4")
compare(control.depth, 1)
compare(control.currentItem, item4)
// replace(component, {properties})
- var item5 = control.replace(component, {objectName:"5"}, StackView.Immediate)
+ let item5 = control.replace(itemComponent, {objectName:"5"}, StackView.Immediate)
compare(item5.objectName, "5")
compare(control.depth, 1)
compare(control.currentItem, item5)
// replace([component, {properties}])
- var item6 = control.replace([component, {objectName:"6"}], StackView.Immediate)
+ let item6 = control.replace([itemComponent, {objectName:"6"}], StackView.Immediate)
compare(item6.objectName, "6")
compare(control.depth, 1)
compare(control.currentItem, item6)
// replace the topmost item
- control.push(component)
+ control.push(itemComponent)
compare(control.depth, 2)
- var item7 = control.replace(control.get(1), component, StackView.Immediate)
+ let item7 = control.replace(control.get(1), itemComponent, StackView.Immediate)
compare(control.depth, 2)
compare(control.currentItem, item7)
// replace the item in the middle
- control.push(component)
- control.push(component)
- control.push(component)
+ control.push(itemComponent)
+ control.push(itemComponent)
+ control.push(itemComponent)
compare(control.depth, 5)
- var item8 = control.replace(control.get(2), component, StackView.Immediate)
+ let item8 = control.replace(control.get(2), itemComponent, StackView.Immediate)
compare(control.depth, 3)
compare(control.currentItem, item8)
}
+ function test_replaceNew() {
+ let control = createTemporaryObject(stackViewComponent, testCase)
+ verify(control)
+
+ // replace(item) - replace currentItem
+ let item1 = itemComponent.createObject(control, {objectName:"1"})
+ compare(control.replaceCurrentItem(item1, {}, StackView.Immediate), item1)
+ compare(control.depth, 1)
+ compare(control.currentItem, item1)
+
+ // replace([item]) - replace currentItem
+ let item2 = itemComponent.createObject(control, {objectName:"2"})
+ compare(control.replaceCurrentItem(item2, {}, StackView.Immediate), item2)
+ compare(control.depth, 1)
+ compare(control.currentItem, item2)
+
+ // replace(item, {properties}) - replace currentItem
+ let item3 = itemComponent.createObject(control)
+ compare(control.replaceCurrentItem(item3, {objectName:"3"}, StackView.Immediate), item3)
+ compare(item3.objectName, "3")
+ compare(control.depth, 1)
+ compare(control.currentItem, item3)
+
+ // replace([item, {properties}]) - replace currentItem
+ let item4 = itemComponent.createObject(control)
+ compare(control.replaceCurrentItem([item4, {objectName:"4"}], StackView.Immediate), item4)
+ compare(item4.objectName, "4")
+ compare(control.depth, 1)
+ compare(control.currentItem, item4)
+
+ // replace(component, {properties}) - replace currentItem
+ let item5 = control.replaceCurrentItem(itemComponent, {objectName:"5"}, StackView.Immediate)
+ compare(control.currentItem, item5)
+ compare(item5.objectName, "5")
+ compare(control.depth, 1)
+ compare(control.currentItem, item5)
+
+ // replace([component, {properties}]) - replace currentItem
+ let item6 = control.replaceCurrentItem([itemComponent, {objectName:"6"}], StackView.Immediate)
+ compare(control.currentItem, item6)
+ compare(item6.objectName, "6")
+ compare(control.depth, 1)
+ compare(control.currentItem, item6)
+ }
+
function test_clear() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
- control.push(component, StackView.Immediate)
+ control.push(itemComponent, StackView.Immediate)
control.clear()
compare(control.depth, 0)
compare(control.busy, false)
- control.push(component, StackView.Immediate)
+ control.push(itemComponent, StackView.Immediate)
control.clear(StackView.PopTransition)
compare(control.depth, 0)
@@ -551,22 +785,22 @@ TestCase {
tryCompare(control, "busy", false)
}
- function test_visibility_data() {
+ function test_visibility_data() : var {
return [
{tag:"default transitions", properties: {}},
{tag:"null transitions", properties: {pushEnter: null, pushExit: null, popEnter: null, popExit: null}}
]
}
- function test_visibility(data) {
- var control = createTemporaryObject(stackView, testCase, data.properties)
+ function test_visibility(data: var) {
+ let control = createTemporaryObject(stackViewComponent, testCase, data.properties)
verify(control)
- var item1 = component.createObject(control)
+ let item1 = itemComponent.createObject(control)
control.push(item1, StackView.Immediate)
verify(item1.visible)
- var item2 = component.createObject(control)
+ let item2 = itemComponent.createObject(control)
control.push(item2)
tryCompare(item1, "visible", false)
verify(item2.visible)
@@ -579,6 +813,7 @@ TestCase {
Component {
id: transitionView
StackView {
+ id: stackView
property int popEnterRuns
property int popExitRuns
property int pushEnterRuns
@@ -587,32 +822,32 @@ TestCase {
property int replaceExitRuns
popEnter: Transition {
PauseAnimation { duration: 1 }
- onRunningChanged: if (!running) ++popEnterRuns
+ onRunningChanged: if (!running) ++stackView.popEnterRuns
}
popExit: Transition {
PauseAnimation { duration: 1 }
- onRunningChanged: if (!running) ++popExitRuns
+ onRunningChanged: if (!running) ++stackView.popExitRuns
}
pushEnter: Transition {
PauseAnimation { duration: 1 }
- onRunningChanged: if (!running) ++pushEnterRuns
+ onRunningChanged: if (!running) ++stackView.pushEnterRuns
}
pushExit: Transition {
PauseAnimation { duration: 1 }
- onRunningChanged: if (!running) ++pushExitRuns
+ onRunningChanged: if (!running) ++stackView.pushExitRuns
}
replaceEnter: Transition {
PauseAnimation { duration: 1 }
- onRunningChanged: if (!running) ++replaceEnterRuns
+ onRunningChanged: if (!running) ++stackView.replaceEnterRuns
}
replaceExit: Transition {
PauseAnimation { duration: 1 }
- onRunningChanged: if (!running) ++replaceExitRuns
+ onRunningChanged: if (!running) ++stackView.replaceExitRuns
}
}
}
- function test_transitions_data() {
+ function test_transitions_data() : var {
return [
{ tag: "undefined", operation: undefined,
pushEnterRuns: [1,2,2,2], pushExitRuns: [0,1,1,1], replaceEnterRuns: [0,0,1,1], replaceExitRuns: [0,0,1,1], popEnterRuns: [0,0,0,1], popExitRuns: [0,0,0,1] },
@@ -627,11 +862,11 @@ TestCase {
]
}
- function test_transitions(data) {
- var control = createTemporaryObject(transitionView, testCase)
+ function test_transitions(data: var) {
+ let control = createTemporaryObject(transitionView, testCase)
verify(control)
- control.push(component, data.operation)
+ control.push(itemComponent, data.operation)
tryCompare(control, "busy", false)
compare(control.pushEnterRuns, data.pushEnterRuns[0])
compare(control.pushExitRuns, data.pushExitRuns[0])
@@ -640,7 +875,7 @@ TestCase {
compare(control.popEnterRuns, data.popEnterRuns[0])
compare(control.popExitRuns, data.popExitRuns[0])
- control.push(component, data.operation)
+ control.push(itemComponent, data.operation)
tryCompare(control, "busy", false)
compare(control.pushEnterRuns, data.pushEnterRuns[1])
compare(control.pushExitRuns, data.pushExitRuns[1])
@@ -649,7 +884,7 @@ TestCase {
compare(control.popEnterRuns, data.popEnterRuns[1])
compare(control.popExitRuns, data.popExitRuns[1])
- control.replace(component, data.operation)
+ control.replace(itemComponent, data.operation)
tryCompare(control, "busy", false)
compare(control.pushEnterRuns, data.pushEnterRuns[2])
compare(control.pushExitRuns, data.pushExitRuns[2])
@@ -677,7 +912,7 @@ TestCase {
TestItem { }
}
- function test_ownership_data() {
+ function test_ownership_data() : var {
return [
{tag:"item, transition", arg: indestructibleItem, operation: StackView.Transition, destroyed: false},
{tag:"item, immediate", arg: indestructibleItem, operation: StackView.Immediate, destroyed: false},
@@ -688,15 +923,15 @@ TestCase {
]
}
- function test_ownership(data) {
- var control = createTemporaryObject(transitionView, testCase, {initialItem: component})
+ function test_ownership(data: var) {
+ let control = createTemporaryObject(transitionView, testCase, {initialItem: itemComponent})
verify(control)
// push-pop
control.push(data.arg, StackView.Immediate)
verify(control.currentItem)
verify(control.currentItem.hasOwnProperty("destroyedCallback"))
- var destroyed = false
+ let destroyed = false
control.currentItem.destroyedCallback = function() { destroyed = true }
control.pop(data.operation)
tryCompare(control, "busy", false)
@@ -709,7 +944,7 @@ TestCase {
verify(control.currentItem.hasOwnProperty("destroyedCallback"))
destroyed = false
control.currentItem.destroyedCallback = function() { destroyed = true }
- control.replace(component, data.operation)
+ control.replace(itemComponent, data.operation)
tryCompare(control, "busy", false)
wait(0) // deferred delete
compare(destroyed, data.destroyed)
@@ -725,17 +960,17 @@ TestCase {
}
function test_destroyOnRemoved() {
- var control = createTemporaryObject(stackView, testCase, { initialItem: component })
+ let control = createTemporaryObject(stackViewComponent, testCase, { initialItem: itemComponent })
verify(control)
- var item = removeComponent.createObject(control)
+ let item = removeComponent.createObject(control)
verify(item)
- var removedSpy = signalSpy.createObject(control, { target: item.StackView, signalName: "removed" })
+ let removedSpy = signalSpy.createObject(control, { target: item.StackView, signalName: "removed" })
verify(removedSpy)
verify(removedSpy.valid)
- var destructionSpy = signalSpy.createObject(control, { target: item.Component, signalName: "destruction" })
+ let destructionSpy = signalSpy.createObject(control, { target: item.Component, signalName: "destruction" })
verify(destructionSpy)
verify(destructionSpy.valid)
@@ -760,7 +995,7 @@ TestCase {
// push-replace
control.push(item, StackView.Immediate)
compare(control.currentItem, item)
- control.replace(component, StackView.Transition)
+ control.replace(itemComponent, StackView.Transition)
item = null
tryCompare(removedSpy, "count", 2)
tryCompare(destructionSpy, "count", 2)
@@ -768,15 +1003,15 @@ TestCase {
}
function test_pushOnRemoved() {
- var control = createTemporaryObject(stackView, testCase, { initialItem: component })
+ let control = createTemporaryObject(stackViewComponent, testCase, { initialItem: itemComponent })
verify(control)
- var item = control.push(component, StackView.Immediate)
+ let item = control.push(itemComponent, StackView.Immediate)
verify(item)
item.StackView.onRemoved.connect(function() {
ignoreWarning(/.*QML StackView: cannot push while already in the process of completing a pop/)
- control.push(component, StackView.Immediate)
+ control.push(itemComponent, StackView.Immediate)
})
// don't crash (QTBUG-62153)
@@ -787,13 +1022,13 @@ TestCase {
id: attachedItem
Item {
property int index: StackView.index
- property StackView view: StackView.view
+ property T.StackView view: StackView.view
property int status: StackView.status
}
}
function test_attached() {
- var control = createTemporaryObject(stackView, testCase, {initialItem: attachedItem})
+ let control = createTemporaryObject(stackViewComponent, testCase, {initialItem: attachedItem})
compare(control.get(0).index, 0)
compare(control.get(0).view, control)
@@ -825,18 +1060,19 @@ TestCase {
}
function test_interaction() {
- var control = createTemporaryObject(stackView, testCase, {initialItem: testButton, width: testCase.width, height: testCase.height})
+ let control = createTemporaryObject(stackViewComponent, testCase,
+ {initialItem: testButton, width: testCase.width, height: testCase.height})
verify(control)
- var firstButton = control.currentItem
+ let firstButton = control.currentItem
verify(firstButton)
- var firstClicks = 0
- var secondClicks = 0
- var thirdClicks = 0
+ let firstClicks = 0
+ let secondClicks = 0
+ let thirdClicks = 0
// push - default transition
- var secondButton = control.push(testButton)
+ let secondButton = control.push(testButton)
compare(control.busy, true)
mouseClick(firstButton) // filtered while busy
mouseClick(secondButton) // filtered while busy
@@ -847,7 +1083,7 @@ TestCase {
compare(secondButton.clicks, ++secondClicks)
// replace - default transition
- var thirdButton = control.replace(testButton)
+ let thirdButton = control.replace(testButton)
compare(control.busy, true)
mouseClick(secondButton) // filtered while busy
mouseClick(thirdButton) // filtered while busy
@@ -941,10 +1177,11 @@ TestCase {
// QTBUG-50305
function test_events() {
- var control = createTemporaryObject(stackView, testCase, {initialItem: mouseArea, width: testCase.width, height: testCase.height})
+ let control = createTemporaryObject(stackViewComponent, testCase,
+ {initialItem: mouseArea, width: testCase.width, height: testCase.height})
verify(control)
- var testItem = control.currentItem
+ let testItem = control.currentItem
verify(testItem)
testItem.doubleClicked.connect(function() {
@@ -961,10 +1198,11 @@ TestCase {
}
function test_ungrab() {
- var control = createTemporaryObject(stackView, testCase, {initialItem: mouseArea, width: testCase.width, height: testCase.height})
+ let control = createTemporaryObject(stackViewComponent, testCase,
+ {initialItem: mouseArea, width: testCase.width, height: testCase.height})
verify(control)
- var testItem = control.currentItem
+ let testItem = control.currentItem
verify(testItem)
mousePress(testItem)
@@ -981,7 +1219,7 @@ TestCase {
}
function test_failures() {
- var control = createTemporaryObject(stackView, testCase, {initialItem: component})
+ let control = createTemporaryObject(stackViewComponent, testCase, {initialItem: itemComponent})
verify(control)
ignoreWarning("QQmlComponent: Component is not ready")
@@ -1010,10 +1248,10 @@ TestCase {
}
function test_properties() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
- var rect = control.push(rectangle, {color: "#ff0000"})
+ let rect = control.push(rectangle, {color: "#ff0000"})
compare(rect.color, "#ff0000")
compare(rect.initialColor, "#ff0000")
}
@@ -1030,10 +1268,10 @@ TestCase {
}
function test_signals() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
- var item1 = signalTest.createObject(control)
+ let item1 = signalTest.createObject(control)
compare(item1.StackView.status, StackView.Inactive)
control.push(item1)
compare(item1.StackView.status, StackView.Active)
@@ -1042,7 +1280,7 @@ TestCase {
compare(item1.deactivatedSpy.count, 0)
compare(item1.deactivatingSpy.count, 0)
- var item2 = signalTest.createObject(control)
+ let item2 = signalTest.createObject(control)
compare(item2.StackView.status, StackView.Inactive)
control.push(item2)
compare(item2.StackView.status, StackView.Activating)
@@ -1074,11 +1312,12 @@ TestCase {
// QTBUG-56158
function test_repeatedPop() {
- var control = createTemporaryObject(stackView, testCase, {initialItem: component, width: testCase.width, height: testCase.height})
+ let control = createTemporaryObject(stackViewComponent, testCase,
+ {initialItem: itemComponent, width: testCase.width, height: testCase.height})
verify(control)
- for (var i = 0; i < 12; ++i)
- control.push(component)
+ for (let i = 0; i < 12; ++i)
+ control.push(itemComponent)
tryCompare(control, "busy", false)
while (control.depth > 1) {
@@ -1089,7 +1328,7 @@ TestCase {
}
function test_pushSameItem() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
control.push(item, StackView.Immediate)
@@ -1103,27 +1342,27 @@ TestCase {
compare(control.depth, 1)
// Push a component so that it becomes current.
- var current = control.push(component, StackView.Immediate)
+ let current = control.push(itemComponent, StackView.Immediate)
compare(control.currentItem, current)
compare(control.depth, 2)
// Push a bunch of stuff. "item" is already in the stack, so it should be ignored.
- current = control.push(component, item, StackView.Immediate)
+ current = control.push(itemComponent, item, StackView.Immediate)
verify(current !== item)
compare(control.currentItem, current)
compare(control.depth, 3)
}
function test_visible() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
- var item1 = component.createObject(control)
+ let item1 = itemComponent.createObject(control)
control.push(item1, StackView.Immediate)
compare(item1.visible, true)
compare(item1.StackView.visible, item1.visible)
- var item2 = component.createObject(control)
+ let item2 = itemComponent.createObject(control)
control.push(item2, StackView.Immediate)
compare(item1.visible, false)
compare(item2.visible, true)
@@ -1132,7 +1371,7 @@ TestCase {
// keep explicitly visible
item2.StackView.visible = true
- control.push(component, StackView.Immediate)
+ control.push(itemComponent, StackView.Immediate)
compare(item2.visible, true)
compare(item2.StackView.visible, true)
@@ -1166,26 +1405,26 @@ TestCase {
}
function test_resolveInitialItem() {
- var control = createTemporaryObject(stackView, testCase, {initialItem: "TestItem.qml"})
+ let control = createTemporaryObject(stackViewComponent, testCase, {initialItem: "TestItem.qml"})
verify(control)
verify(control.currentItem)
}
function test_resolve() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
- var item = control.push("TestItem.qml")
+ let item = control.push("TestItem.qml")
compare(control.depth, 1)
verify(item)
}
// QTBUG-65084
function test_mouseArea() {
- var ma = createTemporaryObject(mouseArea, testCase, {width: testCase.width, height: testCase.height})
+ let ma = createTemporaryObject(mouseArea, testCase, {width: testCase.width, height: testCase.height})
verify(ma)
- var control = stackView.createObject(ma, {width: testCase.width, height: testCase.height})
+ let control = stackViewComponent.createObject(ma, {width: testCase.width, height: testCase.height})
verify(control)
mousePress(control)
@@ -1194,7 +1433,7 @@ TestCase {
mouseRelease(control)
verify(!ma.pressed)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
touch.press(0, control).commit()
verify(ma.pressed)
@@ -1204,14 +1443,14 @@ TestCase {
// Separate function to ensure that the temporary value created to hold the return value of the Qt.createComponent()
// call is out of scope when the caller calls gc().
- function stackViewFactory()
+ function stackViewFactory() : T.StackView
{
- return createTemporaryObject(stackView, testCase, {initialItem: Qt.createComponent("TestItem.qml")})
+ return createTemporaryObject(stackViewComponent, testCase, {initialItem: Qt.createComponent("TestItem.qml")})
}
function test_initalItemOwnership()
{
- var control = stackViewFactory()
+ let control = stackViewFactory()
verify(control)
gc()
verify(control.initialItem)
@@ -1237,7 +1476,7 @@ TestCase {
// We don't actually do this on destruction because destruction is delayed.
// Rather, we do it when we get un-parented.
if (parent === null)
- container.onDestructionCallback(stackView)
+ container.onDestructionCallback(stackView) // qmllint disable use-proper-function
}
}
}
@@ -1288,7 +1527,7 @@ TestCase {
let control = container.control
// Push an extra item so that we can call pop(null) and reproduce the conditions for the crash.
- control.push(component, StackView.Immediate)
+ control.push(itemComponent, StackView.Immediate)
control.push(container.clearUponDestructionComponent, StackView.Immediate)
// Pop the top item, then pop down to the first item in response.
@@ -1306,12 +1545,12 @@ TestCase {
// Replace the top item, then clear in response.
ignoreWarning(/.*cannot clear while already in the process of completing a replace/)
- control.replace(component, StackView.Immediate)
+ control.replace(itemComponent, StackView.Immediate)
}
function test_recursiveClearReplace() {
let container = createTemporaryObject(clearUponDestructionContainerComponent, testCase,
- { onDestructionCallback: function(stackView) { stackView.replace(component, StackView.Immediate) }})
+ { onDestructionCallback: function(stackView) { stackView.replace(itemComponent, StackView.Immediate) }})
verify(container)
let control = container.control
@@ -1383,7 +1622,7 @@ TestCase {
// QTBUG-84381
function test_clearAndPushAfterDepthChange() {
- var control = createTemporaryObject(stackView, testCase, {
+ let control = createTemporaryObject(stackViewComponent, testCase, {
popEnter: null, popExit: null, pushEnter: null,
pushExit: null, replaceEnter: null, replaceExit: null
})
@@ -1396,12 +1635,12 @@ TestCase {
control.clear()
// Shouldn't crash.
ignoreWarning(/.*QML StackView: cannot push while already in the process of completing a push/)
- control.push(component)
+ control.push(itemComponent)
}
})
- control.push(component)
- control.push(component)
+ control.push(itemComponent)
+ control.push(itemComponent)
}
// QTBUG-96966
@@ -1516,8 +1755,9 @@ TestCase {
}
function test_requiredProperties() {
- var control = createTemporaryObject(stackView, testCase)
+ let control = createTemporaryObject(stackViewComponent, testCase)
verify(control)
+ ignoreWarning(/QML StackView: push: Property i was marked as required but not set/)
let failedPush = control.push(withRequired)
compare(failedPush, null);
control.push(withRequired, {"i": 42})
@@ -1564,7 +1804,7 @@ TestCase {
StackView {
id: stackView
anchors.fill: parent
- initialItem: cppComponent
+ initialItem: stackView.cppComponent
property Component cppComponent: ComponentCreator.createComponent("import QtQuick; Rectangle { color: \"navajowhite\" }")
}
@@ -1601,4 +1841,42 @@ TestCase {
control.push(noProperties, { "unknownProperty.test": "crashes" })
verify(!control.empty)
}
+
+ Component {
+ id: deletePoppedItem
+
+ StackView {
+ id: stackView
+ anchors.fill: parent
+ property int visibleChangedCounter
+ property bool secondDestroyed: false
+ initialItem: Text {
+ text: "First"
+ onVisibleChanged: {
+ ++visibleChangedCounter
+ if (visible)
+ tryVerify(function() { return secondDestroyed; })
+ }
+ }
+ }
+ }
+
+ Component {
+ id: otherComp
+ Text {
+ text: "Second"
+ property var stackView
+ Component.onDestruction: stackView.secondDestroyed = true
+ }
+ }
+
+ function test_deletePoppedItem() {
+ let control = createTemporaryObject(deletePoppedItem, testCase)
+ verify(control)
+ control.push(otherComp)
+ tryCompare(control, "visibleChangedCounter", 1)
+ control.currentItem.stackView = control
+ let item = control.pop()
+ tryCompare(control, "visibleChangedCounter", 2)
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_swipedelegate.qml b/tests/auto/quickcontrols/controls/data/tst_swipedelegate.qml
index 901170bf9f..4e4022a1c5 100644
--- a/tests/auto/quickcontrols/controls/data/tst_swipedelegate.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_swipedelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -86,12 +86,12 @@ TestCase {
}
function test_horizontalAnchors(data) {
- var warningMessage = Qt.resolvedUrl("tst_swipedelegate.qml") + data.warningLocation
+ let warningMessage = Qt.resolvedUrl("tst_swipedelegate.qml") + data.warningLocation
+ ": QML QQuickItem: SwipeDelegate: cannot use horizontal anchors with " + data.itemName + "; unable to layout the item."
ignoreWarning(warningMessage);
- var control = createTemporaryObject(data.component, testCase);
+ let control = createTemporaryObject(data.component, testCase);
verify(control.contentItem);
}
@@ -144,7 +144,7 @@ TestCase {
// Sanity check.
compare(control.swipe.position, from);
- var distance = (to - from) * control.width;
+ let distance = (to - from) * control.width;
mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton);
mouseMove(control, control.width / 2 + distance, control.height / 2);
@@ -166,7 +166,7 @@ TestCase {
}
function test_settingDelegates() {
- var control = createTemporaryObject(swipeDelegateComponent, testCase);
+ let control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
ignoreWarning(/QML SwipeDelegate: cannot set both behind and left\/right properties/)
@@ -200,8 +200,8 @@ TestCase {
// First, try the left item.
swipe(control, 0.0, 1.0);
- var oldLeft = control.swipe.left;
- var oldLeftItem = control.swipe.leftItem;
+ let oldLeft = control.swipe.left;
+ let oldLeftItem = control.swipe.leftItem;
ignoreWarning(/QML SwipeDelegate: left\/right\/behind properties may only be set when swipe.position is 0/)
control.swipe.left = null;
compare(control.swipe.left, oldLeft);
@@ -210,8 +210,8 @@ TestCase {
// Try the same thing with the right item.
swipe(control, 1.0, -1.0);
- var oldRight = control.swipe.right;
- var oldRightItem = control.swipe.rightItem;
+ let oldRight = control.swipe.right;
+ let oldRightItem = control.swipe.rightItem;
ignoreWarning(/QML SwipeDelegate: left\/right\/behind properties may only be set when swipe.position is 0/)
control.swipe.right = null;
compare(control.swipe.right, oldRight);
@@ -235,18 +235,20 @@ TestCase {
swipe(control, 0.0, 1.0);
- var oldBehind = control.swipe.behind;
- var oldBehindItem = control.swipe.behindItem;
+ let oldBehind = control.swipe.behind;
+ let oldBehindItem = control.swipe.behindItem;
ignoreWarning(/QML SwipeDelegate: left\/right\/behind properties may only be set when swipe.position is 0/)
control.swipe.behind = null;
compare(control.swipe.behind, oldBehind);
compare(control.swipe.behindItem, oldBehindItem);
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(swipeDelegateComponent, testCase);
+ function test_defaults() {
+ let control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset);
@@ -261,20 +263,20 @@ TestCase {
}
function test_swipe() {
- var control = createTemporaryObject(swipeDelegateComponent, testCase);
+ let control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
- var overDragDistance = Math.round(dragDistance * 1.1);
+ let overDragDistance = Math.round(dragDistance * 1.1);
- var completedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "completed" });
+ let completedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "completed" });
verify(completedSpy);
verify(completedSpy.valid);
- var openedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "opened" });
+ let openedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "opened" });
verify(openedSpy);
verify(openedSpy.valid);
- var closedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "closed" });
+ let closedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "closed" });
verify(closedSpy);
verify(closedSpy.valid);
@@ -437,10 +439,10 @@ TestCase {
function test_swipeVelocity(data) {
skip("QTBUG-52003");
- var control = createTemporaryObject(swipeDelegateComponent, testCase);
+ let control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
- var distance = Math.round(dragDistance * 1.1);
+ let distance = Math.round(dragDistance * 1.1);
if (distance >= control.width / 2)
skip("This test requires a startDragDistance that is less than half the width of the control");
@@ -464,10 +466,10 @@ TestCase {
verify(control.swipe.position < 0.5);
verify(!control.swipe.complete);
- var expectedVisibleItem;
- var expectedVisibleObjectName;
- var expectedHiddenItem;
- var expectedContentItemX;
+ let expectedVisibleItem;
+ let expectedVisibleObjectName;
+ let expectedHiddenItem;
+ let expectedContentItemX;
if (distance > 0) {
expectedVisibleObjectName = "leftItem";
expectedVisibleItem = control.swipe.leftItem;
@@ -505,7 +507,9 @@ TestCase {
text: "SwipeDelegate"
width: 150
swipe.right: Button {
- width: parent.width
+ // make the button a bit shorter than the delegate, so
+ // that we're able to release the mouse outside of it
+ width: parent.width - 4
height: parent.height
text: "Boo!"
}
@@ -513,10 +517,10 @@ TestCase {
}
function test_eventsToLeftAndRight() {
- var control = createTemporaryObject(swipeDelegateWithButtonComponent, testCase);
+ let control = createTemporaryObject(swipeDelegateWithButtonComponent, testCase);
verify(control);
- var closedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "closed" });
+ let closedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "closed" });
verify(closedSpy);
verify(closedSpy.valid);
@@ -529,20 +533,20 @@ TestCase {
verify(control.swipe.rightItem.visible);
compare(control.swipe.rightItem.parent, control);
- var buttonPressedSpy = signalSpyComponent.createObject(control, { target: control.swipe.rightItem, signalName: "pressed" });
+ let buttonPressedSpy = signalSpyComponent.createObject(control, { target: control.swipe.rightItem, signalName: "pressed" });
verify(buttonPressedSpy);
verify(buttonPressedSpy.valid);
- var buttonReleasedSpy = signalSpyComponent.createObject(control, { target: control.swipe.rightItem, signalName: "released" });
+ let buttonReleasedSpy = signalSpyComponent.createObject(control, { target: control.swipe.rightItem, signalName: "released" });
verify(buttonReleasedSpy);
verify(buttonReleasedSpy.valid);
- var buttonClickedSpy = signalSpyComponent.createObject(control, { target: control.swipe.rightItem, signalName: "clicked" });
+ let buttonClickedSpy = signalSpyComponent.createObject(control, { target: control.swipe.rightItem, signalName: "clicked" });
verify(buttonClickedSpy);
verify(buttonClickedSpy.valid);
// Now press the button.
mousePress(control, control.width / 2, control.height / 2);
verify(!control.pressed);
- var button = control.swipe.rightItem;
+ let button = control.swipe.rightItem;
verify(button.pressed);
compare(buttonPressedSpy.count, 1);
compare(buttonReleasedSpy.count, 0);
@@ -564,10 +568,26 @@ TestCase {
verify(!button.pressed);
mouseRelease(control, control.width / 2, control.height / 2);
verify(!control.pressed);
+
+ // Try to press the button again, but drag and release outside of it.
+ // This should not click the button.
+ buttonClickedSpy.clear();
+ // Open the control, and press the button
+ mouseDrag(control, control.width / 2, control.height / 2, -control.width, 0);
+ mousePress(control);
+ verify(button.pressed);
+
+ // Drag the mouse outside the button, and release
+ mouseMove(control, control.width - 2, control.height / 2, -1, Qt.LeftButton);
+ mouseRelease(control);
+ verify(!button.pressed);
+ verify(!button.hovered);
+ // This should not be a click
+ compare(buttonClickedSpy.count, 0);
}
function test_mouseButtons() {
- var control = createTemporaryObject(swipeDelegateComponent, testCase);
+ let control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
// click
@@ -609,7 +629,7 @@ TestCase {
verify(mouseSignalSequenceSpy.success);
// press and hold
- var pressAndHoldSpy = signalSpyComponent.createObject(control, { target: control, signalName: "pressAndHold" });
+ let pressAndHoldSpy = signalSpyComponent.createObject(control, { target: control, signalName: "pressAndHold" });
verify(pressAndHoldSpy);
verify(pressAndHoldSpy.valid);
@@ -691,27 +711,45 @@ TestCase {
}
}
+ function test_removableDelegates_data() {
+ return [
+ { tag: "mouse", touch: false },
+ { tag: "touch", touch: true }
+ ]
+ }
+
function test_removableDelegates() {
- var listView = createTemporaryObject(removableDelegatesComponent, testCase);
+ let listView = createTemporaryObject(removableDelegatesComponent, testCase);
verify(listView);
compare(listView.count, 3);
+ let touch = data.touch ? touchEvent(listView) : null
+
// Expose the remove button.
- var firstItem = listView.itemAt(0, 0);
- mousePress(listView, firstItem.width / 2, firstItem.height / 2);
+ let firstItem = listView.itemAt(0, 0);
+ if (data.touch)
+ touch.press(0, listView, firstItem.width / 2, firstItem.height / 2).commit()
+ else
+ mousePress(listView, firstItem.width / 2, firstItem.height / 2);
verify(firstItem.pressed);
compare(firstItem.swipe.position, 0.0);
verify(!firstItem.swipe.complete);
verify(!firstItem.swipe.leftItem);
- mouseMove(listView, firstItem.width * 1.1, firstItem.height / 2);
+ if (data.touch)
+ touch.move(0, listView, firstItem.width * 1.1, firstItem.height / 2).commit()
+ else
+ mouseMove(listView, firstItem.width * 1.1, firstItem.height / 2);
verify(firstItem.pressed);
compare(firstItem.swipe.position, 0.6);
verify(!firstItem.swipe.complete);
verify(firstItem.swipe.leftItem);
verify(!firstItem.swipe.leftItem.SwipeDelegate.pressed);
- mouseRelease(listView, firstItem.width / 2, firstItem.height / 2);
+ if (data.touch)
+ touch.release(0, listView, firstItem.width / 2, firstItem.height / 2).commit()
+ else
+ mouseRelease(listView, firstItem.width / 2, firstItem.height / 2);
verify(!firstItem.pressed);
tryCompare(firstItem.swipe, "position", 1.0);
tryCompare(firstItem.swipe, "complete", true);
@@ -720,19 +758,32 @@ TestCase {
// Wait for it to settle down.
tryCompare(firstItem.contentItem, "x", firstItem.leftPadding + firstItem.width);
- var leftClickedSpy = signalSpyComponent.createObject(firstItem.swipe.leftItem,
+ let leftClickedSpy = signalSpyComponent.createObject(firstItem.swipe.leftItem,
{ target: firstItem.swipe.leftItem.SwipeDelegate, signalName: "clicked" });
verify(leftClickedSpy);
verify(leftClickedSpy.valid);
// Click the left item to remove the delegate from the list.
- var contentItemX = firstItem.contentItem.x;
- mousePress(listView, firstItem.width / 2, firstItem.height / 2);
+ let contentItemX = firstItem.contentItem.x;
+ // press
+ if (data.touch)
+ touch.press(0, listView, firstItem.width / 2, firstItem.height / 2).commit()
+ else
+ mousePress(listView, firstItem.width / 2, firstItem.height / 2);
verify(firstItem.swipe.leftItem.SwipeDelegate.pressed);
compare(leftClickedSpy.count, 0);
verify(firstItem.pressed);
- mouseRelease(listView, firstItem.width / 2, firstItem.height / 2);
+ // simulate inadvertent movement which can easily happen
+ if (data.touch)
+ touch.move(0, listView, firstItem.width / 2 + 1, firstItem.height / 2).commit()
+ else
+ mouseMove(listView, firstItem.width / 2 + 1, firstItem.height / 2);
+ // release
+ if (data.touch)
+ touch.release(0, listView, firstItem.width / 2, firstItem.height / 2).commit()
+ else
+ mouseRelease(listView, firstItem.width / 2, firstItem.height / 2);
verify(!firstItem.swipe.leftItem.SwipeDelegate.pressed);
compare(leftClickedSpy.count, 1);
verify(!firstItem.pressed);
@@ -806,7 +857,7 @@ TestCase {
}
function test_leadingTrailing(data) {
- var control = createTemporaryObject(data.component, testCase);
+ let control = createTemporaryObject(data.component, testCase);
verify(control);
mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton);
@@ -817,7 +868,7 @@ TestCase {
}
function test_minMaxPosition() {
- var control = createTemporaryObject(leadingTrailingXComponent, testCase);
+ let control = createTemporaryObject(leadingTrailingXComponent, testCase);
verify(control);
// Should be limited within the range -1.0 to 1.0.
@@ -853,13 +904,13 @@ TestCase {
// swipe.position should be scaled to the width of the relevant delegate,
// and it shouldn't be possible to drag past the delegate (so that content behind the control is visible).
function test_delegateWidth() {
- var control = createTemporaryObject(emptySwipeDelegateComponent, testCase);
+ let control = createTemporaryObject(emptySwipeDelegateComponent, testCase);
verify(control);
control.swipe.left = smallLeftComponent;
// Ensure that the position is scaled to the width of the currently visible delegate.
- var overDragDistance = Math.round(dragDistance * 1.1);
+ let overDragDistance = Math.round(dragDistance * 1.1);
mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton);
mouseMove(control, control.width / 2 + overDragDistance, control.height / 2);
verify(control.swipe.leftItem);
@@ -891,7 +942,7 @@ TestCase {
}
function test_positionAfterSwipeCompleted() {
- var control = createTemporaryObject(swipeDelegateComponent, testCase);
+ let control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
// Ensure that both delegates are constructed.
@@ -916,7 +967,7 @@ TestCase {
mousePress(control, control.swipe.leftItem.width - 1, control.height / 2, Qt.LeftButton);
compare(leftVisibleSpy.count, 0);
compare(rightVisibleSpy.count, 0);
- var newX = control.swipe.leftItem.width - Math.round(dragDistance * 1.1) -1;
+ let newX = control.swipe.leftItem.width - Math.round(dragDistance * 1.1) -1;
mouseMove(control, newX, control.height / 2);
compare(leftVisibleSpy.count, 0);
compare(rightVisibleSpy.count, 0);
@@ -986,7 +1037,7 @@ TestCase {
}
function test_leadingTrailingBehindItem() {
- var control = createTemporaryObject(behindSwipeDelegateComponent, testCase);
+ let control = createTemporaryObject(behindSwipeDelegateComponent, testCase);
verify(control);
swipe(control, 0.0, 1.0);
@@ -1038,10 +1089,10 @@ TestCase {
}
function test_close() {
- var control = createTemporaryObject(closeSwipeDelegateComponent, testCase);
+ let control = createTemporaryObject(closeSwipeDelegateComponent, testCase);
verify(control);
- var closedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "closed" });
+ let closedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "closed" });
verify(closedSpy);
verify(closedSpy.valid);
@@ -1173,14 +1224,14 @@ TestCase {
// Tests that it's possible to have multiple non-interactive items in one delegate
// (e.g. left/right/behind) that can each receive clicks.
function test_multipleClickableActions() {
- var control = createTemporaryObject(multiActionSwipeDelegateComponent, testCase);
+ let control = createTemporaryObject(multiActionSwipeDelegateComponent, testCase);
verify(control);
swipe(control, 0.0, -1.0);
verify(control.swipe.rightItem);
tryCompare(control.swipe, "complete", true);
- var firstClickedSpy = signalSpyComponent.createObject(control,
+ let firstClickedSpy = signalSpyComponent.createObject(control,
{ target: control.swipe.rightItem.firstAction.SwipeDelegate, signalName: "clicked" });
verify(firstClickedSpy);
verify(firstClickedSpy.valid);
@@ -1204,7 +1255,7 @@ TestCase {
compare(firstClickedSpy.count, 1);
compare(control.swipe.rightItem.firstClickCount, 1);
- var secondClickedSpy = signalSpyComponent.createObject(control,
+ let secondClickedSpy = signalSpyComponent.createObject(control,
{ target: control.swipe.rightItem.secondAction.SwipeDelegate, signalName: "clicked" });
verify(secondClickedSpy);
verify(secondClickedSpy.valid);
@@ -1280,25 +1331,25 @@ TestCase {
// rotation, for example), the positions of the contentItem and background items
// should be updated accordingly.
function test_contentItemPosOnWidthChanged() {
- var control = createTemporaryObject(swipeDelegateComponent, testCase);
+ let control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
swipe(control, 0.0, 1.0);
- var oldContentItemX = control.contentItem.x;
- var oldBackgroundX = control.background.x;
+ let oldContentItemX = control.contentItem.x;
+ let oldBackgroundX = control.background.x;
control.width += 100;
compare(control.contentItem.x, oldContentItemX + 100);
compare(control.background.x, oldBackgroundX + 100);
}
function test_contentItemHeightOnHeightChanged() {
- var control = createTemporaryObject(swipeDelegateComponent, testCase);
+ let control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
// Try when swipe.complete is false.
- var originalHeight = control.height;
- var originalContentItemHeight = control.contentItem.height;
+ let originalHeight = control.height;
+ let originalContentItemHeight = control.contentItem.height;
verify(control.height !== 10);
control.height = 10;
compare(control.contentItem.height, control.availableHeight);
@@ -1322,7 +1373,7 @@ TestCase {
}
function test_releaseOutside(data) {
- var control = createTemporaryObject(data.component, testCase);
+ let control = createTemporaryObject(data.component, testCase);
verify(control);
// Press and then release below the control.
@@ -1337,7 +1388,7 @@ TestCase {
verify(mouseSignalSequenceSpy.success);
// Press and then release to the right of the control.
- var hasDelegates = control.swipe.left || control.swipe.right || control.swipe.behind;
+ let hasDelegates = control.swipe.left || control.swipe.right || control.swipe.behind;
mouseSignalSequenceSpy.target = control;
mouseSignalSequenceSpy.expectedSequence = hasDelegates
? [["pressedChanged", { "pressed": true }], "pressed"]
@@ -1405,7 +1456,7 @@ TestCase {
}
function test_beginSwipeOverRightItem() {
- var control = createTemporaryObject(leftRightWithLabelsComponent, testCase);
+ let control = createTemporaryObject(leftRightWithLabelsComponent, testCase);
verify(control);
// Swipe to the left, exposing the right item.
@@ -1416,8 +1467,8 @@ TestCase {
// TODO: Swipe to the left, with the mouse over the Label in the right item.
// The left item should not become visible at any point.
- var rightLabel = control.swipe.rightItem.label;
- var overDragDistance = Math.round(dragDistance * 1.1);
+ let rightLabel = control.swipe.rightItem.label;
+ let overDragDistance = Math.round(dragDistance * 1.1);
mousePress(rightLabel, rightLabel.width / 2, rightLabel.height / 2, Qt.rightButton);
mouseMove(rightLabel, rightLabel.width / 2 - overDragDistance, rightLabel.height / 2);
verify(!control.swipe.leftItem);
@@ -1450,7 +1501,7 @@ TestCase {
}
function test_swipeEnabled() {
- var control = createTemporaryObject(swipeDelegateDisabledComponent, testCase);
+ let control = createTemporaryObject(swipeDelegateDisabledComponent, testCase);
mousePress(control, control.width / 2, control.height / 2);
verify(control.pressed);
@@ -1460,7 +1511,7 @@ TestCase {
verify(!control.swipe.rightItem);
// It shouldn't be possible to swipe.
- var overDragDistance = Math.round(dragDistance * 1.1);
+ let overDragDistance = Math.round(dragDistance * 1.1);
mouseMove(control, control.width / 2 - overDragDistance, control.height / 2);
verify(control.pressed);
compare(control.swipe.position, 0.0);
@@ -1527,7 +1578,7 @@ TestCase {
}
function test_open_side(data) {
- var control = createTemporaryObject(emptySwipeDelegateComponent, testCase,
+ let control = createTemporaryObject(emptySwipeDelegateComponent, testCase,
{"swipe.left": data.left, "swipe.right": data.right, "swipe.behind": data.behind});
verify(control);
@@ -1553,7 +1604,7 @@ TestCase {
}
function test_open() {
- var control = createTemporaryObject(openSwipeDelegateComponent, testCase);
+ let control = createTemporaryObject(openSwipeDelegateComponent, testCase);
verify(control);
mouseClick(control);
@@ -1599,7 +1650,7 @@ TestCase {
function test_animations() {
// Test that animations are run when releasing from a drag.
- var control = createTemporaryObject(animationSwipeDelegateComponent, testCase);
+ let control = createTemporaryObject(animationSwipeDelegateComponent, testCase);
verify(control);
mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton);
@@ -1615,11 +1666,11 @@ TestCase {
}
function test_spacing() {
- var control = createTemporaryObject(swipeDelegateComponent, testCase, { text: "Some long, long, long text" })
+ let control = createTemporaryObject(swipeDelegateComponent, testCase, { text: "Some long, long, long text" })
verify(control)
verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth)
- var textLabel = findChild(control.contentItem, "label")
+ let textLabel = findChild(control.contentItem, "label")
verify(textLabel)
// The implicitWidth of the IconLabel that all buttons use as their contentItem
@@ -1648,7 +1699,7 @@ TestCase {
}
function test_display(data) {
- var control = createTemporaryObject(swipeDelegateComponent, testCase, {
+ let control = createTemporaryObject(swipeDelegateComponent, testCase, {
text: "SwipeDelegate",
display: data.display,
width: 400,
@@ -1658,8 +1709,8 @@ TestCase {
verify(control)
compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png")
- var iconImage = findChild(control.contentItem, "image")
- var textLabel = findChild(control.contentItem, "label")
+ let iconImage = findChild(control.contentItem, "image")
+ let textLabel = findChild(control.contentItem, "label")
switch (control.display) {
case SwipeDelegate.IconOnly:
@@ -1747,4 +1798,47 @@ TestCase {
swipe(control, 0, -1.0)
compare(control.swipe.rightItem.color, Qt.color("tomato"))
}
+
+
+ Component {
+ id: swipeDelegate
+
+ SwipeDelegate {
+ anchors.centerIn: parent
+ width: 100
+ height: 50
+ contentItem: Rectangle {
+ color: "red"
+ }
+ swipe.right: Row {
+ height: parent.height
+ anchors.right: parent.right
+ property alias buttonItem: button
+ Button {
+ id: button
+ width: 50
+ height: parent.height
+ text: "Button"
+ }
+ }
+ }
+ }
+
+ function test_mouseEventOnNonVisualItem() {
+ let control = createTemporaryObject(swipeDelegate, testCase)
+ verify(control)
+
+ swipe(control, 0, -1.0)
+ verify(control.swipe.rightItem.visible)
+
+ let rightItem = control.swipe.rightItem
+ let rightClickSpy = signalSpyComponent.createObject(control,
+ { target: rightItem.buttonItem, signalName: "clicked" })
+ verify(rightClickSpy)
+ verify(rightClickSpy.valid)
+
+ mouseClick(rightItem)
+
+ compare(rightClickSpy.count, 1)
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_swipeview.qml b/tests/auto/quickcontrols/controls/data/tst_swipeview.qml
index c853f6dd55..8d59c4a09a 100644
--- a/tests/auto/quickcontrols/controls/data/tst_swipeview.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_swipeview.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -28,24 +28,26 @@ TestCase {
SignalSpy { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(swipeView, testCase)
verify(control)
}
function test_current() {
- var control = createTemporaryObject(swipeView, testCase)
+ let control = createTemporaryObject(swipeView, testCase)
- var currentItemChangedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "currentItemChanged"})
+ let currentItemChangedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "currentItemChanged"})
verify(currentItemChangedSpy.valid)
compare(control.count, 0)
compare(control.currentIndex, -1)
compare(control.currentItem, null)
- var item0 = page.createObject(control, {text: "0"})
+ let item0 = page.createObject(control, {text: "0"})
control.addItem(item0)
compare(control.count, 1)
compare(control.currentIndex, 0)
@@ -54,7 +56,7 @@ TestCase {
compare(control.contentWidth, item0.implicitWidth)
compare(control.contentHeight, item0.implicitHeight)
- var item1 = page.createObject(control, {text: "11"})
+ let item1 = page.createObject(control, {text: "11"})
control.addItem(item1)
compare(control.count, 2)
compare(control.currentIndex, 0)
@@ -63,7 +65,7 @@ TestCase {
compare(control.contentWidth, item0.implicitWidth)
compare(control.contentHeight, item0.implicitHeight)
- var item2 = page.createObject(control, {text: "222"})
+ let item2 = page.createObject(control, {text: "222"})
control.addItem(item2)
compare(control.count, 3)
compare(control.currentIndex, 0)
@@ -119,7 +121,7 @@ TestCase {
}
function test_initialCurrent() {
- var control = createTemporaryObject(initialCurrentSwipeView, testCase)
+ let control = createTemporaryObject(initialCurrentSwipeView, testCase)
compare(control.count, 2)
compare(control.currentIndex, 1)
@@ -127,7 +129,7 @@ TestCase {
}
function test_addRemove() {
- var control = createTemporaryObject(swipeView, testCase)
+ let control = createTemporaryObject(swipeView, testCase)
function verifyCurrentIndexCountDiff() {
verify(control.currentIndex < control.count)
@@ -135,7 +137,7 @@ TestCase {
control.currentIndexChanged.connect(verifyCurrentIndexCountDiff)
control.countChanged.connect(verifyCurrentIndexCountDiff)
- var currentItemChangedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "currentItemChanged"})
+ let currentItemChangedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "currentItemChanged"})
verify(currentItemChangedSpy.valid)
compare(control.count, 0)
@@ -235,12 +237,12 @@ TestCase {
}
function test_content() {
- var control = createTemporaryObject(contentView, testCase)
+ let control = createTemporaryObject(contentView, testCase)
function compareObjectNames(content, names) {
if (content.length !== names.length)
return false
- for (var i = 0; i < names.length; ++i) {
+ for (let i = 0; i < names.length; ++i) {
if (content[i].objectName !== names[i])
return false
}
@@ -280,20 +282,20 @@ TestCase {
}
function test_repeater() {
- var control = createTemporaryObject(repeated, testCase)
+ let control = createTemporaryObject(repeated, testCase)
verify(control)
- var model = control.contentModel
+ let model = control.contentModel
verify(model)
- var repeater = control.repeater
+ let repeater = control.repeater
verify(repeater)
compare(repeater.count, 5)
compare(model.count, 5)
- for (var i = 0; i < 5; ++i) {
- var item1 = control.itemAt(i)
+ for (let i = 0; i < 5; ++i) {
+ let item1 = control.itemAt(i)
verify(item1)
compare(item1.idx, i)
compare(model.get(i), item1)
@@ -304,8 +306,8 @@ TestCase {
compare(repeater.count, 3)
compare(model.count, 3)
- for (var j = 0; j < 3; ++j) {
- var item2 = control.itemAt(j)
+ for (let j = 0; j < 3; ++j) {
+ let item2 = control.itemAt(j)
verify(item2)
compare(item2.idx, j)
compare(model.get(j), item2)
@@ -334,7 +336,7 @@ TestCase {
}
function test_order() {
- var control = createTemporaryObject(ordered, testCase)
+ let control = createTemporaryObject(ordered, testCase)
verify(control)
compare(control.count, 7)
@@ -395,14 +397,14 @@ TestCase {
}
function test_move(data) {
- var control = createTemporaryObject(swipeView, testCase)
+ let control = createTemporaryObject(swipeView, testCase)
compare(control.count, 0)
- var titles = ["1", "2", "3"]
+ let titles = ["1", "2", "3"]
- var i = 0;
+ let i = 0;
for (i = 0; i < titles.length; ++i) {
- var item = pageAttached.createObject(control, {text: titles[i]})
+ let item = pageAttached.createObject(control, {text: titles[i]})
control.addItem(item)
}
@@ -427,7 +429,7 @@ TestCase {
compare(control.count, titles.length)
compare(control.currentIndex, data.currentAfter)
- var title = titles[data.from]
+ let title = titles[data.from]
titles.splice(data.from, 1)
titles.splice(data.to, 0, title)
@@ -455,13 +457,13 @@ TestCase {
}
function test_dynamic() {
- var control = createTemporaryObject(dynamicView, testCase)
+ let control = createTemporaryObject(dynamicView, testCase)
// insertItem(), addItem(), createObject() and static page {}
compare(control.count, 4)
compare(control.itemAt(0).text, "inserted")
- var tab = page.createObject(control, {text: "dying"})
+ let tab = page.createObject(control, {text: "dying"})
compare(control.count, 5)
compare(control.itemAt(4).text, "dying")
@@ -472,9 +474,9 @@ TestCase {
}
function test_attachedParent() {
- var control = createTemporaryObject(swipeView, testCase);
+ let control = createTemporaryObject(swipeView, testCase);
- var page = createTemporaryObject(pageAttached, testCase);
+ let page = createTemporaryObject(pageAttached, testCase);
compare(page.view, null);
compare(page.index, -1);
compare(page.isCurrentItem, false);
@@ -509,17 +511,17 @@ TestCase {
}
function test_orientation() {
- var control = createTemporaryObject(swipeView, testCase, {width: 200, height: 200})
+ let control = createTemporaryObject(swipeView, testCase, {width: 200, height: 200})
verify(control)
- for (var i = 0; i < 3; ++i)
+ for (let i = 0; i < 3; ++i)
control.addItem(page.createObject(control, {text: i}))
compare(control.orientation, Qt.Horizontal)
compare(control.horizontal, true)
compare(control.vertical, false)
- for (i = 0; i < control.count; ++i) {
+ for (let i = 0; i < control.count; ++i) {
control.currentIndex = i
compare(control.itemAt(i).y, 0)
}
@@ -529,7 +531,7 @@ TestCase {
compare(control.horizontal, false)
compare(control.vertical, true)
- for (i = 0; i < control.count; ++i) {
+ for (let i = 0; i < control.count; ++i) {
control.currentIndex = i
compare(control.itemAt(i).x, 0)
}
@@ -564,7 +566,7 @@ TestCase {
if (Qt.styleHints.tabFocusBehavior !== Qt.TabFocusAllControls)
skip("This platform only allows tab focus for text controls")
- var control = createTemporaryObject(focusSwipeViewComponent, testCase)
+ let control = createTemporaryObject(focusSwipeViewComponent, testCase)
verify(control)
compare(control.focus, true)
compare(control.contentItem.focus, true)
@@ -643,7 +645,7 @@ TestCase {
tryCompare(rect, "visible", true)
if (Qt.platform.pluginName === "offscreen")
skip("grabImage() is not functional on the offscreen platform (QTBUG-63185)")
- var image = grabImage(control)
+ let image = grabImage(control)
compare(image.pixel(3, 3), "#ffff00")
}
@@ -651,7 +653,10 @@ TestCase {
id: translucentPages
SwipeView {
spacing: 10
- padding: 10
+ leftPadding: 10
+ topPadding: 10
+ rightPadding: 10
+ bottomPadding: 10
Text { text: "page 0" }
Text { text: "page 1"; font.pointSize: 16 }
Text { text: "page 2"; font.pointSize: 24 }
@@ -662,18 +667,97 @@ TestCase {
function test_initialPositions() { // QTBUG-102487
const control = createTemporaryObject(translucentPages, testCase, {width: 320, height: 200})
verify(control)
+ compare(control.contentItem.width, control.width - control.leftPadding - control.rightPadding)
+ compare(control.spacing, 10)
+
compare(control.orientation, Qt.Horizontal)
- for (var i = 0; i < control.count; ++i) {
+ for (let i = 0; i < control.count; ++i) {
const page = control.itemAt(i)
- // control.contentItem.width + control.spacing == 310; except Imagine style has contentItem.width == 320
- compare(page.x, i * 310)
+ compare(page.x, i * (control.contentItem.width + control.spacing))
compare(page.y, 0)
+ compare(page.width, control.contentItem.width)
+ compare(page.height, control.contentItem.height)
}
control.orientation = Qt.Vertical
- for (var i = 0; i < control.count; ++i) {
+ for (let i = 0; i < control.count; ++i) {
const page = control.itemAt(i)
compare(page.y, i * (control.contentItem.height + control.spacing))
compare(page.x, 0)
+ compare(page.width, control.contentItem.width)
+ compare(page.height, control.contentItem.height)
+ }
+
+ // QTBUG-115468: add a page after startup and check that that works too.
+ control.orientation = Qt.Horizontal
+ let page4 = page.createObject(control, { text: "page 4", "font.pointSize": 40 })
+ control.insertItem(control.count, page4)
+ compare(page4.x, (control.count - 1) * 310)
+ compare(page4.y, 0)
+ compare(page4.width, control.contentItem.width)
+ compare(page4.height, control.contentItem.height)
+ }
+
+ Component {
+ id: doublePageWithLabels
+ SwipeView {
+ anchors.fill: parent
+ property alias item1: item1
+ property alias item2: item2
+ Item {
+ id: item1
+ property alias label: label1
+ Label { id: label1; anchors.centerIn: parent; text: "1"; }
+ }
+ Item {
+ id: item2
+ property alias label: label2
+ Label { id: label2; anchors.centerIn: parent; text: "2"; }
+ }
+ }
+ }
+
+ function test_rightClick_data() {
+ return [
+ { tag: "mouse_left", mouse: true, button: Qt.LeftButton },
+ { tag: "mouse_right", mouse: true, button: Qt.RightButton },
+ { tag: "touch", touch: true }
+ ]
+ }
+
+ function test_rightClick(data) {
+ let swipeView = createTemporaryObject(doublePageWithLabels, testCase)
+ verify(swipeView)
+ let item1 = swipeView.item1
+ verify(item1)
+ let item2 = swipeView.item2
+ verify(item2)
+ let label1 = item1.label
+ verify(label1)
+ let label2 = item2.label
+ verify(label2)
+ const swipeListView = swipeView.contentItem
+ verify(swipeListView)
+
+ swipeView.currentIndex = 0
+ compare(swipeView.currentIndex, 0)
+ compare(swipeView.currentItem, item1)
+ tryCompare(swipeListView, "contentX", 0, 1000)
+ compare(item2.x, swipeListView.width)
+
+ let touch = data.touch ? touchEvent(swipeView) : null
+
+ if (data.touch) {
+ touch.press(0, label1, label1.width / 2, label1.height / 2)
+ touch.commit()
+ touch.release(0, label1, label1.width / 2, label1.height / 2)
+ touch.commit()
+ } else if (data.mouse) {
+ mouseClick(label1, label1.width / 2, label1.height / 2, data.button)
}
+ swipeView.currentIndex = 1
+ compare(swipeView.currentIndex, 1)
+ compare(swipeView.currentItem, item2)
+ tryCompare(swipeListView, "contentX", swipeListView.width, 1000)
+ compare(item2.x, swipeListView.width)
}
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_switch.qml b/tests/auto/quickcontrols/controls/data/tst_switch.qml
index 407513b914..40fdbaff0d 100644
--- a/tests/auto/quickcontrols/controls/data/tst_switch.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_switch.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -25,15 +25,17 @@ TestCase {
}
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(swtch, testCase)
verify(control)
}
function test_text() {
- var control = createTemporaryObject(swtch, testCase)
+ let control = createTemporaryObject(swtch, testCase)
verify(control)
compare(control.text, "")
@@ -44,12 +46,12 @@ TestCase {
}
function test_checked() {
- var control = createTemporaryObject(swtch, testCase)
+ let control = createTemporaryObject(swtch, testCase)
verify(control)
compare(control.checked, false)
- var spy = signalSequenceSpy.createObject(control, {target: control})
+ let spy = signalSequenceSpy.createObject(control, {target: control})
spy.expectedSequence = [["checkedChanged", { "checked": true }]]
control.checked = true
compare(control.checked, true)
@@ -69,7 +71,7 @@ TestCase {
}
function test_pressed(data) {
- var control = createTemporaryObject(swtch, testCase, {padding: 10})
+ let control = createTemporaryObject(swtch, testCase, {padding: 10})
verify(control)
// stays pressed when dragged outside
@@ -83,11 +85,11 @@ TestCase {
}
function test_mouse() {
- var control = createTemporaryObject(swtch, testCase)
+ let control = createTemporaryObject(swtch, testCase)
verify(control)
// check
- var spy = signalSequenceSpy.createObject(control, {target: control})
+ let spy = signalSequenceSpy.createObject(control, {target: control})
spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }],
"pressed"]
mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton)
@@ -184,13 +186,13 @@ TestCase {
}
function test_touch() {
- var control = createTemporaryObject(swtch, testCase)
+ let control = createTemporaryObject(swtch, testCase)
verify(control)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
// check
- var spy = signalSequenceSpy.createObject(control, {target: control})
+ let spy = signalSequenceSpy.createObject(control, {target: control})
spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }],
"pressed"]
touch.press(0, control, control.width / 2, control.height / 2).commit()
@@ -282,10 +284,10 @@ TestCase {
}
function test_mouseDrag() {
- var control = createTemporaryObject(swtch, testCase, {leftPadding: 100, rightPadding: 100})
+ let control = createTemporaryObject(swtch, testCase, {leftPadding: 100, rightPadding: 100})
verify(control)
- var spy = signalSequenceSpy.createObject(control, {target: control})
+ let spy = signalSequenceSpy.createObject(control, {target: control})
compare(control.position, 0.0)
compare(control.checked, false)
compare(control.pressed, false)
@@ -387,12 +389,12 @@ TestCase {
}
function test_touchDrag() {
- var control = createTemporaryObject(swtch, testCase, {leftPadding: 100, rightPadding: 100})
+ let control = createTemporaryObject(swtch, testCase, {leftPadding: 100, rightPadding: 100})
verify(control)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
- var spy = signalSequenceSpy.createObject(control, {target: control})
+ let spy = signalSequenceSpy.createObject(control, {target: control})
compare(control.position, 0.0)
compare(control.checked, false)
compare(control.pressed, false)
@@ -497,14 +499,14 @@ TestCase {
}
function test_keys() {
- var control = createTemporaryObject(swtch, testCase)
+ let control = createTemporaryObject(swtch, testCase)
verify(control)
control.forceActiveFocus()
verify(control.activeFocus)
// check
- var spy = signalSequenceSpy.createObject(control, {target: control})
+ let spy = signalSequenceSpy.createObject(control, {target: control})
spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }],
"pressed",
["pressedChanged", { "pressed": false, "checked": false }],
@@ -532,8 +534,8 @@ TestCase {
spy.expectedSequence = []
// Not testing Key_Enter and Key_Return because QGnomeTheme uses them for
// pressing buttons and the CI uses the QGnomeTheme platform theme.
- var keys = [Qt.Key_Escape, Qt.Key_Tab]
- for (var i = 0; i < keys.length; ++i) {
+ let keys = [Qt.Key_Escape, Qt.Key_Tab]
+ for (let i = 0; i < keys.length; ++i) {
keyClick(keys[i])
compare(control.checked, false)
verify(spy.success)
@@ -549,7 +551,7 @@ TestCase {
}
function test_binding() {
- var container = createTemporaryObject(twoSwitches, testCase)
+ let container = createTemporaryObject(twoSwitches, testCase)
verify(container)
compare(container.sw1.checked, false)
@@ -565,13 +567,13 @@ TestCase {
}
function test_baseline() {
- var control = createTemporaryObject(swtch, testCase)
+ let control = createTemporaryObject(swtch, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
}
function test_focus() {
- var control = createTemporaryObject(swtch, testCase)
+ let control = createTemporaryObject(swtch, testCase)
verify(control)
verify(!control.activeFocus)
@@ -597,9 +599,9 @@ TestCase {
}
function test_deletionOrder() {
- var control1 = createTemporaryObject(deletionOrder1, testCase)
+ let control1 = createTemporaryObject(deletionOrder1, testCase)
verify(control1)
- var control2 = createTemporaryObject(deletionOrder2, testCase)
+ let control2 = createTemporaryObject(deletionOrder2, testCase)
verify(control2)
}
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_switchdelegate.qml b/tests/auto/quickcontrols/controls/data/tst_switchdelegate.qml
index 42d58b9668..c03555f59c 100644
--- a/tests/auto/quickcontrols/controls/data/tst_switchdelegate.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_switchdelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -27,27 +27,29 @@ TestCase {
// TODO: data-fy tst_checkbox (rename to tst_check?) so we don't duplicate its tests here?
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(switchDelegate, testCase);
- verify(control);
- verify(!control.checked);
+ function test_defaults() {
+ let control = createTemporaryObject(switchDelegate, testCase);
+ verify(control)
+ verify(!control.checked)
}
function test_checked() {
- var control = createTemporaryObject(switchDelegate, testCase);
- verify(control);
+ let control = createTemporaryObject(switchDelegate, testCase);
+ verify(control)
- mouseClick(control);
- verify(control.checked);
+ mouseClick(control)
+ verify(control.checked)
- mouseClick(control);
- verify(!control.checked);
+ mouseClick(control)
+ verify(!control.checked)
}
function test_baseline() {
- var control = createTemporaryObject(switchDelegate, testCase);
+ let control = createTemporaryObject(switchDelegate, testCase);
verify(control);
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset);
}
@@ -60,7 +62,7 @@ TestCase {
}
function test_pressed(data) {
- var control = createTemporaryObject(switchDelegate, testCase, {padding: 10})
+ let control = createTemporaryObject(switchDelegate, testCase, {padding: 10})
verify(control)
// stays pressed when dragged outside
@@ -74,11 +76,11 @@ TestCase {
}
function test_mouse() {
- var control = createTemporaryObject(switchDelegate, testCase)
+ let control = createTemporaryObject(switchDelegate, testCase)
verify(control)
// check
- var spy = signalSequenceSpy.createObject(control, {target: control})
+ let spy = signalSequenceSpy.createObject(control, {target: control})
spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }],
"pressed"]
mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton)
@@ -175,13 +177,13 @@ TestCase {
}
function test_touch() {
- var control = createTemporaryObject(switchDelegate, testCase)
+ let control = createTemporaryObject(switchDelegate, testCase)
verify(control)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
// check
- var spy = signalSequenceSpy.createObject(control, {target: control})
+ let spy = signalSequenceSpy.createObject(control, {target: control})
spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }],
"pressed"]
touch.press(0, control, control.width / 2, control.height / 2).commit()
@@ -273,10 +275,10 @@ TestCase {
}
function test_mouseDrag() {
- var control = createTemporaryObject(switchDelegate, testCase, {leftPadding: 100, rightPadding: 100})
+ let control = createTemporaryObject(switchDelegate, testCase, {leftPadding: 100, rightPadding: 100})
verify(control)
- var spy = signalSequenceSpy.createObject(control, {target: control})
+ let spy = signalSequenceSpy.createObject(control, {target: control})
compare(control.position, 0.0)
compare(control.checked, false)
compare(control.pressed, false)
@@ -378,12 +380,12 @@ TestCase {
}
function test_touchDrag() {
- var control = createTemporaryObject(switchDelegate, testCase, {leftPadding: 100, rightPadding: 100})
+ let control = createTemporaryObject(switchDelegate, testCase, {leftPadding: 100, rightPadding: 100})
verify(control)
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
- var spy = signalSequenceSpy.createObject(control, {target: control})
+ let spy = signalSequenceSpy.createObject(control, {target: control})
compare(control.position, 0.0)
compare(control.checked, false)
compare(control.pressed, false)
@@ -488,11 +490,11 @@ TestCase {
}
function test_spacing() {
- var control = createTemporaryObject(switchDelegate, testCase, { text: "Some long, long, long text" })
+ let control = createTemporaryObject(switchDelegate, testCase, { text: "Some long, long, long text" })
verify(control)
verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth)
- var textLabel = findChild(control.contentItem, "label")
+ let textLabel = findChild(control.contentItem, "label")
verify(textLabel)
// The implicitWidth of the IconLabel that all buttons use as their contentItem should be
@@ -519,7 +521,7 @@ TestCase {
}
function test_display(data) {
- var control = createTemporaryObject(switchDelegate, testCase, {
+ let control = createTemporaryObject(switchDelegate, testCase, {
text: "SwitchDelegate",
display: data.display,
width: 400,
@@ -529,11 +531,11 @@ TestCase {
verify(control)
compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png")
- var iconImage = findChild(control.contentItem, "image")
- var textLabel = findChild(control.contentItem, "label")
+ let iconImage = findChild(control.contentItem, "image")
+ let textLabel = findChild(control.contentItem, "label")
- var availableWidth = control.availableWidth - control.indicator.width - control.spacing
- var indicatorOffset = control.mirrored ? control.indicator.width + control.spacing : 0
+ let availableWidth = control.availableWidth - control.indicator.width - control.spacing
+ let indicatorOffset = control.mirrored ? control.indicator.width + control.spacing : 0
switch (control.display) {
case SwitchDelegate.IconOnly:
diff --git a/tests/auto/quickcontrols/controls/data/tst_tabbar.qml b/tests/auto/quickcontrols/controls/data/tst_tabbar.qml
index 58c0b1ae61..19ba2a9678 100644
--- a/tests/auto/quickcontrols/controls/data/tst_tabbar.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_tabbar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -20,7 +20,12 @@ TestCase {
Component {
id: tabBar
- TabBar { }
+ TabBar {
+ topPadding: 0
+ bottomPadding: 0
+ leftPadding: 0
+ rightPadding: 0
+ }
}
Component {
@@ -53,10 +58,12 @@ TestCase {
SignalSpy { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(tabBar, testCase)
+ function test_defaults() {
+ let control = createTemporaryObject(tabBar, testCase)
verify(control)
compare(control.count, 0)
compare(control.currentIndex, -1)
@@ -64,7 +71,7 @@ TestCase {
}
function test_current() {
- var control = createTemporaryObject(tabBar, testCase)
+ let control = createTemporaryObject(tabBar, testCase)
compare(control.count, 0)
compare(control.currentIndex, -1)
@@ -110,7 +117,7 @@ TestCase {
}
function test_current_static() {
- var control = createTemporaryObject(tabBarStaticTabs, testCase)
+ let control = createTemporaryObject(tabBarStaticTabs, testCase)
compare(control.count, 2)
compare(control.currentIndex, 0)
@@ -126,7 +133,7 @@ TestCase {
}
function test_addRemove() {
- var control = createTemporaryObject(tabBar, testCase)
+ let control = createTemporaryObject(tabBar, testCase)
function verifyCurrentIndexCountDiff() {
verify(control.currentIndex < control.count)
@@ -134,7 +141,7 @@ TestCase {
control.currentIndexChanged.connect(verifyCurrentIndexCountDiff)
control.countChanged.connect(verifyCurrentIndexCountDiff)
- var contentChildrenSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "contentChildrenChanged"})
+ let contentChildrenSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "contentChildrenChanged"})
verify(contentChildrenSpy.valid)
compare(control.count, 0)
@@ -226,7 +233,7 @@ TestCase {
}
function test_removeCurrent() {
- var control = createTemporaryObject(tabBar, testCase)
+ let control = createTemporaryObject(tabBar, testCase)
control.addItem(tabButton.createObject(control, {text: "1"}))
control.addItem(tabButton.createObject(control, {text: "2"}))
@@ -260,19 +267,19 @@ TestCase {
}
function test_content() {
- var control = createTemporaryObject(contentBar, testCase)
+ let control = createTemporaryObject(contentBar, testCase)
function compareObjectNames(content, names) {
if (content.length !== names.length)
return false
- for (var i = 0; i < names.length; ++i) {
+ for (let i = 0; i < names.length; ++i) {
if (content[i].objectName !== names[i])
return false
}
return true
}
- var contentChildrenSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "contentChildrenChanged"})
+ let contentChildrenSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "contentChildrenChanged"})
verify(contentChildrenSpy.valid)
verify(compareObjectNames(control.contentData, ["object", "button1", "timer", "button2", ""]))
@@ -312,20 +319,20 @@ TestCase {
}
function test_repeater() {
- var control = createTemporaryObject(repeated, testCase)
+ let control = createTemporaryObject(repeated, testCase)
verify(control)
- var model = control.contentModel
+ let model = control.contentModel
verify(model)
- var repeater = control.repeater
+ let repeater = control.repeater
verify(repeater)
compare(repeater.count, 5)
compare(model.count, 5)
- for (var i = 0; i < 5; ++i) {
- var item1 = control.itemAt(i)
+ for (let i = 0; i < 5; ++i) {
+ let item1 = control.itemAt(i)
verify(item1)
compare(item1.idx, i)
compare(model.get(i), item1)
@@ -336,8 +343,8 @@ TestCase {
compare(repeater.count, 3)
compare(model.count, 3)
- for (var j = 0; j < 3; ++j) {
- var item2 = control.itemAt(j)
+ for (let j = 0; j < 3; ++j) {
+ let item2 = control.itemAt(j)
verify(item2)
compare(item2.idx, j)
compare(model.get(j), item2)
@@ -366,7 +373,7 @@ TestCase {
}
function test_order() {
- var control = createTemporaryObject(ordered, testCase)
+ let control = createTemporaryObject(ordered, testCase)
verify(control)
compare(control.count, 7)
@@ -415,12 +422,12 @@ TestCase {
}
function test_move(data) {
- var control = createTemporaryObject(tabBar, testCase)
+ let control = createTemporaryObject(tabBar, testCase)
compare(control.count, 0)
- var titles = ["1", "2", "3"]
+ let titles = ["1", "2", "3"]
- var i = 0;
+ let i = 0;
for (i = 0; i < titles.length; ++i)
control.addItem(tabButton.createObject(control, {text: titles[i]}))
@@ -434,7 +441,7 @@ TestCase {
compare(control.count, titles.length)
compare(control.currentIndex, data.currentAfter)
- var title = titles[data.from]
+ let title = titles[data.from]
titles.splice(data.from, 1)
titles.splice(data.to, 0, title)
@@ -457,13 +464,13 @@ TestCase {
}
function test_dynamic() {
- var control = createTemporaryObject(dynamicBar, testCase)
+ let control = createTemporaryObject(dynamicBar, testCase)
// insertItem(), addItem(), createObject() and static TabButton {}
compare(control.count, 4)
compare(control.itemAt(0).text, "inserted")
- var tab = tabButton.createObject(control, {text: "dying"})
+ let tab = tabButton.createObject(control, {text: "dying"})
compare(control.count, 5)
compare(control.itemAt(4).text, "dying")
@@ -482,13 +489,13 @@ TestCase {
}
function test_layout(data) {
- var control = createTemporaryObject(tabBar, testCase, {spacing: data.spacing, width: 200})
+ let control = createTemporaryObject(tabBar, testCase, {spacing: data.spacing, width: 200})
// remove the background so that it won't affect the implicit size of the tabbar,
// so the implicit sizes tested below are entirely based on the content size
control.background = null
- var tab1 = tabButton.createObject(control, {text: "First"})
+ let tab1 = tabButton.createObject(control, {text: "First"})
control.addItem(tab1)
tryCompare(tab1, "width", control.width)
compare(tab1.height, control.height)
@@ -499,7 +506,7 @@ TestCase {
compare(control.implicitWidth, control.contentWidth + control.leftPadding + control.rightPadding)
compare(control.implicitHeight, control.contentHeight + control.topPadding + control.bottomPadding)
- var tab2 = tabButton.createObject(control, {implicitHeight: tab1.implicitHeight + 10, text: "Second"})
+ let tab2 = tabButton.createObject(control, {implicitHeight: tab1.implicitHeight + 10, text: "Second"})
control.addItem(tab2)
tryCompare(tab1, "width", (control.width - data.spacing) / 2)
compare(tab1.height, control.height)
@@ -512,7 +519,7 @@ TestCase {
compare(control.implicitWidth, control.contentWidth + control.leftPadding + control.rightPadding)
compare(control.implicitHeight, control.contentHeight + control.topPadding + control.bottomPadding)
- var tab3 = tabButton.createObject(control, {width: 50, height: tab1.implicitHeight - 10, text: "Third"})
+ let tab3 = tabButton.createObject(control, {width: 50, height: tab1.implicitHeight - 10, text: "Third"})
control.addItem(tab3)
tryCompare(tab1, "width", (control.width - 2 * data.spacing - 50) / 2)
compare(tab1.y, 0)
@@ -531,7 +538,8 @@ TestCase {
compare(control.implicitWidth, control.contentWidth + control.leftPadding + control.rightPadding)
compare(control.implicitHeight, control.contentHeight + control.topPadding + control.bottomPadding)
- var expectedWidth = tab3.contentItem.implicitWidth + tab3.leftPadding + tab3.rightPadding
+ let expectedWidth = Math.max(tab3.implicitBackgroundWidth + tab3.leftInset + tab3.rightInset,
+ tab3.implicitContentWidth + tab3.leftPadding + tab3.rightPadding)
tab3.width = tab3.implicitWidth
tab3.height = tab3.implicitHeight
tryCompare(tab1, "width", (control.width - 2 * data.spacing - expectedWidth) / 2)
@@ -621,10 +629,10 @@ TestCase {
}
function test_attached() {
- var control = createTemporaryObject(tabBar, testCase, {position: TabBar.Footer})
+ let control = createTemporaryObject(tabBar, testCase, {position: TabBar.Footer})
// append
- var tab1 = createTemporaryObject(attachedButton, testCase)
+ let tab1 = createTemporaryObject(attachedButton, testCase)
compare(tab1.index, -1)
compare(tab1.tabBar, null)
compare(tab1.position, TabBar.Header)
@@ -635,7 +643,7 @@ TestCase {
compare(tab1.position, TabBar.Footer)
// insert in the beginning
- var tab2 = createTemporaryObject(attachedButton, testCase)
+ let tab2 = createTemporaryObject(attachedButton, testCase)
compare(tab2.index, -1)
compare(tab2.tabBar, null)
compare(tab2.position, TabBar.Header)
@@ -648,7 +656,7 @@ TestCase {
compare(tab1.index, 1)
// insert in the middle
- var tab3 = createTemporaryObject(attachedButton, testCase)
+ let tab3 = createTemporaryObject(attachedButton, testCase)
compare(tab3.index, -1)
compare(tab3.tabBar, null)
compare(tab3.position, TabBar.Header)
@@ -662,7 +670,7 @@ TestCase {
compare(tab1.index, 2)
// insert in the end
- var tab4 = createTemporaryObject(attachedButton, testCase)
+ let tab4 = createTemporaryObject(attachedButton, testCase)
compare(tab4.index, -1)
compare(tab4.tabBar, null)
compare(tab4.position, TabBar.Header)
diff --git a/tests/auto/quickcontrols/controls/data/tst_tabbutton.qml b/tests/auto/quickcontrols/controls/data/tst_tabbutton.qml
index 591622b8a2..1c6181a97f 100644
--- a/tests/auto/quickcontrols/controls/data/tst_tabbutton.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_tabbutton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -28,22 +28,24 @@ TestCase {
}
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(tabButton, testCase)
verify(control)
}
function test_autoExclusive() {
- var container = createTemporaryObject(repeater, testCase)
+ let container = createTemporaryObject(repeater, testCase)
- for (var i = 0; i < 3; ++i) {
+ for (let i = 0; i < 3; ++i) {
container.children[i].checked = true
compare(container.children[i].checked, true)
// check that all other buttons are unchecked
- for (var j = 0; j < 3; ++j) {
+ for (let j = 0; j < 3; ++j) {
if (j !== i)
compare(container.children[j].checked, false)
}
@@ -51,18 +53,18 @@ TestCase {
}
function test_baseline() {
- var control = createTemporaryObject(tabButton, testCase)
+ let control = createTemporaryObject(tabButton, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
}
function test_spacing() {
- var control = createTemporaryObject(tabButton, testCase, { text: "Some long, long, long text" })
+ let control = createTemporaryObject(tabButton, testCase, { text: "Some long, long, long text" })
verify(control)
if (control.background)
verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth)
- var textLabel = findChild(control.contentItem, "label")
+ let textLabel = findChild(control.contentItem, "label")
verify(textLabel)
// The implicitWidth of the IconLabel that all buttons use as their contentItem
@@ -91,7 +93,7 @@ TestCase {
}
function test_display(data) {
- var control = createTemporaryObject(tabButton, testCase, {
+ let control = createTemporaryObject(tabButton, testCase, {
text: "TabButton",
display: data.display,
"icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png",
@@ -100,8 +102,8 @@ TestCase {
verify(control)
compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png")
- var iconImage = findChild(control.contentItem, "image")
- var textLabel = findChild(control.contentItem, "label")
+ let iconImage = findChild(control.contentItem, "image")
+ let textLabel = findChild(control.contentItem, "label")
switch (control.display) {
case TabButton.IconOnly:
diff --git a/tests/auto/quickcontrols/controls/data/tst_textarea.qml b/tests/auto/quickcontrols/controls/data/tst_textarea.qml
index 0f295905f1..5e28b6733f 100644
--- a/tests/auto/quickcontrols/controls/data/tst_textarea.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_textarea.qml
@@ -1,9 +1,10 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
import QtQuick.Controls
+import Qt.test.controls
TestCase {
id: testCase
@@ -68,33 +69,35 @@ TestCase {
id: util
}
- function test_creation() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(textArea, testCase)
+ function test_creation() {
+ let control = createTemporaryObject(textArea, testCase)
verify(control)
}
function test_implicitSize() {
- var control = createTemporaryObject(textArea, testCase)
+ let control = createTemporaryObject(textArea, testCase)
verify(control)
- var implicitWidthSpy = signalSpy.createObject(control, { target: control, signalName: "implicitWidthChanged"} )
+ let implicitWidthSpy = signalSpy.createObject(control, { target: control, signalName: "implicitWidthChanged"} )
verify(implicitWidthSpy.valid)
- var implicitHeightSpy = signalSpy.createObject(control, { target: control, signalName: "implicitHeightChanged"} )
+ let implicitHeightSpy = signalSpy.createObject(control, { target: control, signalName: "implicitHeightChanged"} )
verify(implicitHeightSpy.valid)
- var implicitBackgroundWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundWidthChanged"})
+ let implicitBackgroundWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundWidthChanged"})
verify(implicitBackgroundWidthSpy.valid)
- var implicitBackgroundHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundHeightChanged"})
+ let implicitBackgroundHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundHeightChanged"})
verify(implicitBackgroundHeightSpy.valid)
- var implicitWidthChanges = 0
- var implicitHeightChanges = 0
- var implicitBackgroundWidthChanges = 0
- var implicitBackgroundHeightChanges = 0
+ let implicitWidthChanges = 0
+ let implicitHeightChanges = 0
+ let implicitBackgroundWidthChanges = 0
+ let implicitBackgroundHeightChanges = 0
verify(control.implicitWidth >= control.leftPadding + control.rightPadding)
verify(control.implicitHeight >= control.contentHeight + control.topPadding + control.bottomPadding)
@@ -129,11 +132,11 @@ TestCase {
compare(implicitWidthSpy.count, ++implicitWidthChanges)
defaultFontMetrics.font = control.font
- var leading = defaultFontMetrics.leading
- var ascent = defaultFontMetrics.ascent
- var descent = defaultFontMetrics.descent
+ let leading = defaultFontMetrics.leading
+ let ascent = defaultFontMetrics.ascent
+ let descent = defaultFontMetrics.descent
- var leadingOverflow = Math.ceil(ascent + descent) < Math.ceil(ascent + descent + leading)
+ let leadingOverflow = Math.ceil(ascent + descent) < Math.ceil(ascent + descent + leading)
// If the font in use triggers QTBUG-83894, it is possible that this will cause
// the following compare to fail if the implicitHeight from the TextEdit is ued.
@@ -206,20 +209,28 @@ TestCase {
}
function test_alignment(data) {
- var control = createTemporaryObject(textArea, testCase, {text: data.text, placeholderText: data.placeholderText, horizontalAlignment: data.textAlignment})
+ let control = createTemporaryObject(textArea, testCase, {text: data.text, placeholderText: data.placeholderText})
- if (data.textAlignment !== undefined)
+ if (data.textAlignment !== undefined) {
+ control.horizontalAlignment = data.textAlignment
compare(control.horizontalAlignment, data.textAlignment)
- for (var i = 0; i < control.children.length; ++i) {
- if (control.children[i].hasOwnProperty("horizontalAlignment"))
- compare(control.children[i].effectiveHorizontalAlignment, data.placeholderAlignment) // placeholder
+ }
+
+ // The placeholder text of the Material style doesn't currently respect the alignment of the control.
+ if (StyleInfo.styleName !== "Material") {
+ for (let i = 0; i < control.children.length; ++i) {
+ if (control.children[i].hasOwnProperty("horizontalAlignment"))
+ compare(control.children[i].effectiveHorizontalAlignment, data.placeholderAlignment) // placeholder
+ }
}
control.verticalAlignment = TextArea.AlignBottom
compare(control.verticalAlignment, TextArea.AlignBottom)
- for (var j = 0; j < control.children.length; ++j) {
- if (control.children[j].hasOwnProperty("verticalAlignment"))
- compare(control.children[j].verticalAlignment, Text.AlignBottom) // placeholder
+ if (StyleInfo.styleName !== "Material") {
+ for (let j = 0; j < control.children.length; ++j) {
+ if (control.children[j].hasOwnProperty("verticalAlignment"))
+ compare(control.children[j].verticalAlignment, Text.AlignBottom) // placeholder
+ }
}
}
@@ -227,7 +238,7 @@ TestCase {
return [
{tag: "bold", value: true},
{tag: "capitalization", value: Font.Capitalize},
- {tag: "family", value: "Courier"},
+ {tag: "family", value: "Tahoma"},
{tag: "italic", value: true},
{tag: "strikeout", value: true},
{tag: "underline", value: true},
@@ -237,19 +248,19 @@ TestCase {
}
function test_font_explicit_attributes(data) {
- var control = createTemporaryObject(textArea, testCase)
+ let control = createTemporaryObject(textArea, testCase)
verify(control)
- var child = textArea.createObject(control)
+ let child = textArea.createObject(control)
verify(child)
- var controlSpy = signalSpy.createObject(control, {target: control, signalName: "fontChanged"})
+ let controlSpy = signalSpy.createObject(control, {target: control, signalName: "fontChanged"})
verify(controlSpy.valid)
- var childSpy = signalSpy.createObject(child, {target: child, signalName: "fontChanged"})
+ let childSpy = signalSpy.createObject(child, {target: child, signalName: "fontChanged"})
verify(childSpy.valid)
- var defaultValue = control.font[data.tag]
+ let defaultValue = control.font[data.tag]
child.font[data.tag] = defaultValue
compare(child.font[data.tag], defaultValue)
@@ -265,33 +276,33 @@ TestCase {
}
function test_flickable() {
- var control = createTemporaryObject(flickable, testCase, {text:"line0", selectByMouse: true})
+ let control = createTemporaryObject(flickable, testCase)
verify(control)
- var textArea = control.TextArea.flickable
+ let textArea = control.TextArea.flickable
verify(textArea)
if (textArea.background)
compare(textArea.background.parent, control)
- for (var i = 1; i <= 100; ++i)
+ for (let i = 1; i <= 100; ++i)
textArea.text += "line\n" + i
verify(textArea.contentWidth > 0)
verify(textArea.contentHeight > 200)
- compare(control.contentWidth, textArea.contentWidth + textArea.leftPadding + textArea.rightPadding)
- compare(control.contentHeight, textArea.contentHeight + textArea.topPadding + textArea.bottomPadding)
+ compare(control.contentWidth, textArea.implicitWidth)
+ compare(control.contentHeight, textArea.implicitHeight)
compare(textArea.cursorPosition, 0)
- var center = textArea.positionAt(control.width / 2, control.height / 2)
+ let center = textArea.positionAt(control.width / 2, control.height / 2)
verify(center > 0)
mouseClick(textArea, control.width / 2, control.height / 2)
compare(textArea.cursorPosition, center)
// click inside text area, but below flickable
- var below = textArea.positionAt(control.width / 2, control.height + 1)
+ let below = textArea.positionAt(control.width / 2, control.height + 1)
verify(below > center)
mouseClick(textArea, control.width / 2, control.height + 1)
compare(textArea.cursorPosition, center) // no change
@@ -300,7 +311,7 @@ TestCase {
control.contentY = -(control.contentHeight - control.height) / 2
// click inside textarea, but above flickable
- var above = textArea.positionAt(control.width / 2, textArea.topPadding)
+ let above = textArea.positionAt(control.width / 2, textArea.topPadding)
verify(above > 0 && above < center)
mouseClick(textArea, control.width / 2, 0)
compare(textArea.cursorPosition, center) // no change
@@ -310,10 +321,10 @@ TestCase {
// Test that the TextArea background item is parented out of the
// TextArea and into the Flicable, and that it has the same size
// as the flickable.
- var flickable = createTemporaryObject(flickableCustomBackground, testCase)
+ let flickable = createTemporaryObject(flickableCustomBackground, testCase)
verify(flickable)
- var textArea = flickable.TextArea.flickable
+ let textArea = flickable.TextArea.flickable
verify(textArea)
verify(textArea.background)
compare(textArea.background.width, flickable.width)
@@ -321,10 +332,10 @@ TestCase {
}
function test_scrollable_paste_large() {
- var control = createTemporaryObject(flickableWithScrollBar, testCase)
+ let control = createTemporaryObject(flickableWithScrollBar, testCase)
verify(control)
- var textArea = control.TextArea.flickable
+ let textArea = control.TextArea.flickable
verify(textArea)
if (typeof(textArea.paste) !== "function")
@@ -352,7 +363,7 @@ TestCase {
}
function test_hover(data) {
- var control = createTemporaryObject(textArea, testCase, {text: "TextArea", hoverEnabled: data.hoverEnabled})
+ let control = createTemporaryObject(textArea, testCase, {text: "TextArea", hoverEnabled: data.hoverEnabled})
verify(control)
compare(control.hovered, false)
@@ -417,9 +428,9 @@ TestCase {
}
function test_pressedReleased(data) {
- var mouseArea = createTemporaryObject(mouseAreaComponent, testCase)
+ let mouseArea = createTemporaryObject(mouseAreaComponent, testCase)
verify(mouseArea)
- var control = textArea.createObject(mouseArea, {text: "TextArea"})
+ let control = textArea.createObject(mouseArea, {text: "TextArea"})
verify(control)
// Give enough room to check presses outside of the control and on the parent.
@@ -449,13 +460,13 @@ TestCase {
if (data.parentReleaseEvent)
control.onReleased.connect(checkParentReleaseEvent)
- var controlPressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" })
+ let controlPressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" })
verify(controlPressedSpy.valid)
- var controlReleasedSpy = signalSpy.createObject(control, { target: control, signalName: "released" })
+ let controlReleasedSpy = signalSpy.createObject(control, { target: control, signalName: "released" })
verify(controlReleasedSpy.valid)
- var parentPressedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "pressed" })
+ let parentPressedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "pressed" })
verify(parentPressedSpy.valid)
- var parentReleasedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "released" })
+ let parentReleasedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "released" })
verify(parentReleasedSpy.valid)
mousePress(control, data.x, data.y, data.button)
@@ -473,8 +484,8 @@ TestCase {
property bool ignorePress: false
property bool ignoreRelease: false
- onPressed: if (ignorePress) event.accepted = false
- onReleased: if (ignoreRelease) event.accepted = false
+ onPressed: function (event) { if (ignorePress) event.accepted = false }
+ onReleased: function (event) { if (ignoreRelease) event.accepted = false }
}
}
@@ -487,18 +498,18 @@ TestCase {
}
function test_ignorePressRelease() {
- var mouseArea = createTemporaryObject(mouseAreaComponent, testCase)
+ let mouseArea = createTemporaryObject(mouseAreaComponent, testCase)
verify(mouseArea)
- var control = ignoreTextArea.createObject(mouseArea)
+ let control = ignoreTextArea.createObject(mouseArea)
verify(control)
- var controlPressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" })
+ let controlPressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" })
verify(controlPressedSpy.valid)
- var controlReleasedSpy = signalSpy.createObject(control, { target: control, signalName: "released" })
+ let controlReleasedSpy = signalSpy.createObject(control, { target: control, signalName: "released" })
verify(controlReleasedSpy.valid)
- var parentPressedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "pressed" })
+ let parentPressedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "pressed" })
verify(parentPressedSpy.valid)
- var parentReleasedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "released" })
+ let parentReleasedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "released" })
verify(parentReleasedSpy.valid)
// Ignore only press events.
@@ -529,12 +540,12 @@ TestCase {
}
function test_multiClick() {
- var control = createTemporaryObject(textArea, testCase, {text: "Qt Quick Controls 2 TextArea", selectByMouse: true})
+ let control = createTemporaryObject(textArea, testCase, {text: "Qt Quick Controls 2 TextArea", selectByMouse: true})
verify(control)
waitForRendering(control)
control.width = control.contentWidth
- var rect = control.positionToRectangle(12)
+ let rect = control.positionToRectangle(12)
// double click -> select word
mouseDoubleClickSequence(control, rect.x + rect.width / 2, rect.y + rect.height / 2)
@@ -553,7 +564,7 @@ TestCase {
}
function test_scrollView() {
- var control = createTemporaryObject(scrollView, testCase)
+ let control = createTemporaryObject(scrollView, testCase)
verify(control)
// don't crash (QTBUG-62292)
@@ -562,7 +573,7 @@ TestCase {
}
function test_placeholderTextColor() {
- var control = createTemporaryObject(textArea, testCase)
+ let control = createTemporaryObject(textArea, testCase)
verify(control)
// usually default value should not be pure opacue black
@@ -570,32 +581,32 @@ TestCase {
control.placeholderTextColor = "#12345678"
compare(control.placeholderTextColor, "#12345678")
- for (var i = 0; i < control.children.length; ++i) {
+ for (let i = 0; i < control.children.length; ++i) {
if (control.children[i].hasOwnProperty("text"))
compare(control.children[i].color, control.placeholderTextColor) // placeholder.color
}
}
function test_inset() {
- var control = createTemporaryObject(textArea, testCase, {background: rectangle.createObject(control)})
+ let control = createTemporaryObject(textArea, testCase, {background: rectangle.createObject(testCase)})
verify(control)
- var topInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topInsetChanged"})
+ let topInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topInsetChanged"})
verify(topInsetSpy.valid)
- var leftInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftInsetChanged"})
+ let leftInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftInsetChanged"})
verify(leftInsetSpy.valid)
- var rightInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightInsetChanged"})
+ let rightInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightInsetChanged"})
verify(rightInsetSpy.valid)
- var bottomInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomInsetChanged"})
+ let bottomInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomInsetChanged"})
verify(bottomInsetSpy.valid)
- var topInsetChanges = 0
- var leftInsetChanges = 0
- var rightInsetChanges = 0
- var bottomInsetChanges = 0
+ let topInsetChanges = 0
+ let leftInsetChanges = 0
+ let rightInsetChanges = 0
+ let bottomInsetChanges = 0
compare(control.topInset, 0)
compare(control.leftInset, 0)
@@ -756,7 +767,7 @@ TestCase {
}
function test_resize_background() {
- var control = createTemporaryObject(testResizeBackground, testCase)
+ let control = createTemporaryObject(testResizeBackground, testCase)
compare(control.textArea.background.width, control.width)
compare(control.textArea.background.height, 1)
diff --git a/tests/auto/quickcontrols/controls/data/tst_textfield.qml b/tests/auto/quickcontrols/controls/data/tst_textfield.qml
index f5b3d91fe1..ef1cca71b5 100644
--- a/tests/auto/quickcontrols/controls/data/tst_textfield.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_textfield.qml
@@ -1,10 +1,11 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
import QtQuick.Controls
import QtQuick.Layouts
+import Qt.test.controls
TestCase {
id: testCase
@@ -29,33 +30,35 @@ TestCase {
SignalSpy { }
}
- function test_creation() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(textField, testCase)
+ function test_creation() {
+ let control = createTemporaryObject(textField, testCase)
verify(control)
}
function test_implicitSize() {
- var control = createTemporaryObject(textField, testCase)
+ let control = createTemporaryObject(textField, testCase)
verify(control)
- var implicitWidthSpy = signalSpy.createObject(control, { target: control, signalName: "implicitWidthChanged"} )
+ let implicitWidthSpy = signalSpy.createObject(control, { target: control, signalName: "implicitWidthChanged"} )
verify(implicitWidthSpy.valid)
- var implicitHeightSpy = signalSpy.createObject(control, { target: control, signalName: "implicitHeightChanged"} )
+ let implicitHeightSpy = signalSpy.createObject(control, { target: control, signalName: "implicitHeightChanged"} )
verify(implicitHeightSpy.valid)
- var implicitBackgroundWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundWidthChanged"})
+ let implicitBackgroundWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundWidthChanged"})
verify(implicitBackgroundWidthSpy.valid)
- var implicitBackgroundHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundHeightChanged"})
+ let implicitBackgroundHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundHeightChanged"})
verify(implicitBackgroundHeightSpy.valid)
- var implicitWidthChanges = 0
- var implicitHeightChanges = 0
- var implicitBackgroundWidthChanges = 0
- var implicitBackgroundHeightChanges = 0
+ let implicitWidthChanges = 0
+ let implicitHeightChanges = 0
+ let implicitBackgroundWidthChanges = 0
+ let implicitBackgroundHeightChanges = 0
verify(control.implicitWidth >= control.leftPadding + control.rightPadding)
verify(control.implicitHeight >= control.contentHeight + control.topPadding + control.bottomPadding)
@@ -153,20 +156,27 @@ TestCase {
}
function test_alignment(data) {
- var control = createTemporaryObject(textField, testCase, {text: data.text, placeholderText: data.placeholderText, horizontalAlignment: data.textAlignment})
+ let control = createTemporaryObject(textField, testCase, {text: data.text, placeholderText: data.placeholderText})
- if (data.textAlignment !== undefined)
+ if (data.textAlignment !== undefined) {
+ control.horizontalAlignment = data.textAlignment
compare(control.horizontalAlignment, data.textAlignment)
- for (var i = 0; i < control.children.length; ++i) {
- if (control.children[i].hasOwnProperty("text") && control.children[i].hasOwnProperty("horizontalAlignment"))
- compare(control.children[i].effectiveHorizontalAlignment, data.placeholderAlignment) // placeholder
+ }
+ // The placeholder text of the Material style doesn't currently respect the alignment of the control.
+ if (StyleInfo.styleName !== "Material") {
+ for (let i = 0; i < control.children.length; ++i) {
+ if (control.children[i].hasOwnProperty("text") && control.children[i].hasOwnProperty("horizontalAlignment"))
+ compare(control.children[i].effectiveHorizontalAlignment, data.placeholderAlignment) // placeholder
+ }
}
control.verticalAlignment = TextField.AlignBottom
compare(control.verticalAlignment, TextField.AlignBottom)
- for (var j = 0; j < control.children.length; ++j) {
- if (control.children[j].hasOwnProperty("text") && control.children[j].hasOwnProperty("verticalAlignment"))
- compare(control.children[j].verticalAlignment, Text.AlignBottom) // placeholder
+ if (StyleInfo.styleName !== "Material") {
+ for (let j = 0; j < control.children.length; ++j) {
+ if (control.children[j].hasOwnProperty("text") && control.children[j].hasOwnProperty("verticalAlignment"))
+ compare(control.children[j].verticalAlignment, Text.AlignBottom) // placeholder
+ }
}
}
@@ -174,7 +184,7 @@ TestCase {
return [
{tag: "bold", value: true},
{tag: "capitalization", value: Font.Capitalize},
- {tag: "family", value: "Courier"},
+ {tag: "family", value: "Tahoma"},
{tag: "italic", value: true},
{tag: "strikeout", value: true},
{tag: "underline", value: true},
@@ -184,19 +194,19 @@ TestCase {
}
function test_font_explicit_attributes(data) {
- var control = createTemporaryObject(textField, testCase)
+ let control = createTemporaryObject(textField, testCase)
verify(control)
- var child = textField.createObject(control)
+ let child = textField.createObject(control)
verify(child)
- var controlSpy = signalSpy.createObject(control, {target: control, signalName: "fontChanged"})
+ let controlSpy = signalSpy.createObject(control, {target: control, signalName: "fontChanged"})
verify(controlSpy.valid)
- var childSpy = signalSpy.createObject(child, {target: child, signalName: "fontChanged"})
+ let childSpy = signalSpy.createObject(child, {target: child, signalName: "fontChanged"})
verify(childSpy.valid)
- var defaultValue = control.font[data.tag]
+ let defaultValue = control.font[data.tag]
child.font[data.tag] = defaultValue
compare(child.font[data.tag], defaultValue)
@@ -219,7 +229,7 @@ TestCase {
}
function test_hover(data) {
- var control = createTemporaryObject(textField, testCase, {hoverEnabled: data.hoverEnabled})
+ let control = createTemporaryObject(textField, testCase, {hoverEnabled: data.hoverEnabled})
verify(control)
compare(control.hovered, false)
@@ -284,9 +294,9 @@ TestCase {
}
function test_pressedReleased(data) {
- var mouseArea = createTemporaryObject(mouseAreaComponent, testCase)
+ let mouseArea = createTemporaryObject(mouseAreaComponent, testCase)
verify(mouseArea)
- var control = textField.createObject(mouseArea)
+ let control = textField.createObject(mouseArea)
verify(control)
// Give enough room to check presses outside of the control and on the parent.
@@ -316,13 +326,13 @@ TestCase {
if (data.parentReleaseEvent)
control.onReleased.connect(checkParentReleaseEvent)
- var controlPressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" })
+ let controlPressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" })
verify(controlPressedSpy.valid)
- var controlReleasedSpy = signalSpy.createObject(control, { target: control, signalName: "released" })
+ let controlReleasedSpy = signalSpy.createObject(control, { target: control, signalName: "released" })
verify(controlReleasedSpy.valid)
- var parentPressedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "pressed" })
+ let parentPressedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "pressed" })
verify(parentPressedSpy.valid)
- var parentReleasedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "released" })
+ let parentReleasedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "released" })
verify(parentReleasedSpy.valid)
mousePress(control, data.x, data.y, data.button)
@@ -340,8 +350,8 @@ TestCase {
property bool ignorePress: false
property bool ignoreRelease: false
- onPressed: if (ignorePress) event.accepted = false
- onReleased: if (ignoreRelease) event.accepted = false
+ onPressed: function (event) { if (ignorePress) event.accepted = false }
+ onReleased: function (event) { if (ignoreRelease) event.accepted = false }
}
}
@@ -354,18 +364,18 @@ TestCase {
}
function test_ignorePressRelease() {
- var mouseArea = createTemporaryObject(mouseAreaComponent, testCase)
+ let mouseArea = createTemporaryObject(mouseAreaComponent, testCase)
verify(mouseArea)
- var control = ignoreTextField.createObject(mouseArea)
+ let control = ignoreTextField.createObject(mouseArea)
verify(control)
- var controlPressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" })
+ let controlPressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" })
verify(controlPressedSpy.valid)
- var controlReleasedSpy = signalSpy.createObject(control, { target: control, signalName: "released" })
+ let controlReleasedSpy = signalSpy.createObject(control, { target: control, signalName: "released" })
verify(controlReleasedSpy.valid)
- var parentPressedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "pressed" })
+ let parentPressedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "pressed" })
verify(parentPressedSpy.valid)
- var parentReleasedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "released" })
+ let parentReleasedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "released" })
verify(parentReleasedSpy.valid)
// Ignore only press events.
@@ -396,12 +406,12 @@ TestCase {
}
function test_multiClick() {
- var control = createTemporaryObject(textField, testCase, {text: "Qt Quick Controls 2 TextArea"})
+ let control = createTemporaryObject(textField, testCase, {text: "Qt Quick Controls 2 TextArea"})
verify(control)
waitForRendering(control)
control.width = control.contentWidth
- var rect = control.positionToRectangle(12)
+ let rect = control.positionToRectangle(12)
// double click -> select word
mouseDoubleClickSequence(control, rect.x + rect.width / 2, rect.y + rect.height / 2)
@@ -414,7 +424,7 @@ TestCase {
// QTBUG-64048
function test_rightClick() {
- var control = createTemporaryObject(textField, testCase, {text: "TextField"})
+ let control = createTemporaryObject(textField, testCase, {text: "TextField"})
verify(control)
control.selectAll()
@@ -428,10 +438,10 @@ TestCase {
}
function test_mouseSelect() {
- var control = createTemporaryObject(textField, testCase, {text: "Text", width: parent.width})
+ let control = createTemporaryObject(textField, testCase, {text: "Text", width: parent.width})
verify(control)
verify(control.selectByMouse) // true by default since 6.4
- var pressSpy = signalSpy.createObject(control, {target: control, signalName: "pressed"})
+ let pressSpy = signalSpy.createObject(control, {target: control, signalName: "pressed"})
const y = control.height / 2
mousePress(control, 0, y, Qt.LeftButton)
@@ -442,11 +452,11 @@ TestCase {
}
function test_noTouchSelect() {
- var control = createTemporaryObject(textField, testCase, {text: "Text"})
+ let control = createTemporaryObject(textField, testCase, {text: "Text"})
verify(control)
verify(control.selectByMouse) // true by default since 6.4
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
const y = control.height / 2
touch.press(0, control, 0, y).commit()
touch.move(0, control, control.implicitWidth, 0).commit()
@@ -455,13 +465,13 @@ TestCase {
}
function test_aaTouchPressAndHold() {
- var control = createTemporaryObject(textField, testCase, {text: "Text"})
+ let control = createTemporaryObject(textField, testCase, {text: "Text"})
verify(control)
verify(control.selectByMouse) // true by default since 6.4
- var pressSpy = signalSpy.createObject(control, {target: control, signalName: "pressed"})
- var pressAndHoldSpy = signalSpy.createObject(control, {target: control, signalName: "pressAndHold"})
+ let pressSpy = signalSpy.createObject(control, {target: control, signalName: "pressed"})
+ let pressAndHoldSpy = signalSpy.createObject(control, {target: control, signalName: "pressAndHold"})
- var touch = touchEvent(control)
+ let touch = touchEvent(control)
touch.press(0, control).commit()
tryCompare(pressSpy, "count", 1)
tryCompare(pressAndHoldSpy, "count", 1)
@@ -470,7 +480,7 @@ TestCase {
// QTBUG-66260
function test_placeholderTextColor() {
- var control = createTemporaryObject(textField, testCase)
+ let control = createTemporaryObject(textField, testCase)
verify(control)
// usually default value should not be pure opacue black
@@ -478,32 +488,32 @@ TestCase {
control.placeholderTextColor = "#12345678"
compare(control.placeholderTextColor, "#12345678")
- for (var i = 0; i < control.children.length; ++i) {
+ for (let i = 0; i < control.children.length; ++i) {
if (control.children[i].hasOwnProperty("text"))
compare(control.children[i].color, control.placeholderTextColor) // placeholder.color
}
}
function test_inset() {
- var control = createTemporaryObject(textField, testCase, {background: rectangle.createObject(control)})
+ let control = createTemporaryObject(textField, testCase, {background: rectangle.createObject(testCase)})
verify(control)
- var topInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topInsetChanged"})
+ let topInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topInsetChanged"})
verify(topInsetSpy.valid)
- var leftInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftInsetChanged"})
+ let leftInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftInsetChanged"})
verify(leftInsetSpy.valid)
- var rightInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightInsetChanged"})
+ let rightInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightInsetChanged"})
verify(rightInsetSpy.valid)
- var bottomInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomInsetChanged"})
+ let bottomInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomInsetChanged"})
verify(bottomInsetSpy.valid)
- var topInsetChanges = 0
- var leftInsetChanges = 0
- var rightInsetChanges = 0
- var bottomInsetChanges = 0
+ let topInsetChanges = 0
+ let leftInsetChanges = 0
+ let rightInsetChanges = 0
+ let bottomInsetChanges = 0
compare(control.topInset, 0)
compare(control.leftInset, 0)
@@ -647,10 +657,10 @@ TestCase {
}
function test_inLayout() {
- var layout = createTemporaryObject(layoutComponent, testCase)
+ let layout = createTemporaryObject(layoutComponent, testCase)
verify(layout)
- var control = layout.textField
+ let control = layout.textField
verify(control)
compare(control.width, control.parent.width)
@@ -676,14 +686,12 @@ TestCase {
// macOS is special: 43eca45b061fe965fe2a6f1876d4a35a58e3a9e4
if (Qt.platform.os === "osx" || Qt.platform.os === "macos")
skip("TextField hard-codes pixel size on macOS")
- failOnWarning("Both point size and pixel size set. Using pixel size.")
- var textField = createTemporaryObject(textFieldWithPointSizeSet, testCase)
+ let textField = createTemporaryObject(textFieldWithPointSizeSet, testCase)
verify(textField)
}
function test_setPixelSizeDoesNotWarn() {
- failOnWarning("Both point size and pixel size set. Using pixel size.")
- var textField = createTemporaryObject(textFieldWithPixelSizeSet, testCase)
+ let textField = createTemporaryObject(textFieldWithPixelSizeSet, testCase)
verify(textField)
}
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_toolbar.qml b/tests/auto/quickcontrols/controls/data/tst_toolbar.qml
index d2c9e4a20d..e6be264a03 100644
--- a/tests/auto/quickcontrols/controls/data/tst_toolbar.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_toolbar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -52,10 +52,12 @@ TestCase {
}
}
- function test_empty() {
+ function init() {
failOnWarning(/.?/)
+ }
- var control = createTemporaryObject(toolBar, testCase)
+ function test_empty() {
+ let control = createTemporaryObject(toolBar, testCase)
verify(control)
verify(control.contentItem)
@@ -66,7 +68,7 @@ TestCase {
}
function test_oneChild() {
- var control = createTemporaryObject(oneChildBar, testCase)
+ let control = createTemporaryObject(oneChildBar, testCase)
verify(control)
compare(control.contentWidth, 100)
@@ -78,7 +80,7 @@ TestCase {
}
function test_twoChildren() {
- var control = createTemporaryObject(twoChildrenBar, testCase)
+ let control = createTemporaryObject(twoChildrenBar, testCase)
verify(control)
compare(control.contentWidth, 0)
@@ -90,7 +92,7 @@ TestCase {
}
function test_contentItem() {
- var control = createTemporaryObject(contentBar, testCase)
+ let control = createTemporaryObject(contentBar, testCase)
verify(control)
compare(control.contentWidth, 100)
diff --git a/tests/auto/quickcontrols/controls/data/tst_toolbutton.qml b/tests/auto/quickcontrols/controls/data/tst_toolbutton.qml
index 4879e91611..2cf746d288 100644
--- a/tests/auto/quickcontrols/controls/data/tst_toolbutton.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_toolbutton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -23,15 +23,17 @@ TestCase {
ToolButton { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(toolButton, testCase)
verify(control)
}
function test_text() {
- var control = createTemporaryObject(toolButton, testCase)
+ let control = createTemporaryObject(toolButton, testCase)
verify(control)
compare(control.text, "")
@@ -42,16 +44,16 @@ TestCase {
}
function test_mouse() {
- var control = createTemporaryObject(toolButton, testCase)
+ let control = createTemporaryObject(toolButton, testCase)
verify(control)
- var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
+ let pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
verify(pressedSpy.valid)
- var downSpy = signalSpy.createObject(control, {target: control, signalName: "downChanged"})
+ let downSpy = signalSpy.createObject(control, {target: control, signalName: "downChanged"})
verify(downSpy.valid)
- var clickedSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
+ let clickedSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
verify(clickedSpy.valid)
// check
@@ -111,10 +113,10 @@ TestCase {
}
function test_keys() {
- var control = createTemporaryObject(toolButton, testCase)
+ let control = createTemporaryObject(toolButton, testCase)
verify(control)
- var clickedSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
+ let clickedSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
verify(clickedSpy.valid)
control.forceActiveFocus()
@@ -131,15 +133,15 @@ TestCase {
// no change
// Not testing Key_Enter and Key_Return because QGnomeTheme uses them for
// pressing buttons and the CI uses the QGnomeTheme platform theme.
- var keys = [Qt.Key_Escape, Qt.Key_Tab]
- for (var i = 0; i < keys.length; ++i) {
+ let keys = [Qt.Key_Escape, Qt.Key_Tab]
+ for (let i = 0; i < keys.length; ++i) {
keyClick(keys[i])
compare(clickedSpy.count, 2)
}
}
function test_baseline() {
- var control = createTemporaryObject(toolButton, testCase)
+ let control = createTemporaryObject(toolButton, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
}
@@ -158,7 +160,7 @@ TestCase {
}
function test_display(data) {
- var control = createTemporaryObject(toolButton, testCase, {
+ let control = createTemporaryObject(toolButton, testCase, {
text: "ToolButton",
display: data.display,
"icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png",
@@ -167,8 +169,8 @@ TestCase {
verify(control)
compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png")
- var iconImage = findChild(control.contentItem, "image")
- var textLabel = findChild(control.contentItem, "label")
+ let iconImage = findChild(control.contentItem, "image")
+ let textLabel = findChild(control.contentItem, "label")
switch (control.display) {
case ToolButton.IconOnly:
diff --git a/tests/auto/quickcontrols/controls/data/tst_toolseparator.qml b/tests/auto/quickcontrols/controls/data/tst_toolseparator.qml
index ef7fc35758..f9ca5aec72 100644
--- a/tests/auto/quickcontrols/controls/data/tst_toolseparator.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_toolseparator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -17,15 +17,17 @@ TestCase {
ToolSeparator {}
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(toolSeparator, testCase)
verify(control)
}
function test_size() {
- var control = createTemporaryObject(toolSeparator, testCase);
+ let control = createTemporaryObject(toolSeparator, testCase);
verify(control);
verify(control.width > 1);
verify(control.height > 1);
@@ -37,15 +39,15 @@ TestCase {
}
function test_orientation() {
- var control = createTemporaryObject(toolSeparator, testCase);
+ let control = createTemporaryObject(toolSeparator, testCase);
verify(control);
compare(control.horizontal, false);
compare(control.vertical, true);
- var orientationSpy = signalSpyComponent.createObject(control, { target: control, signalName: "orientationChanged" });
+ let orientationSpy = signalSpyComponent.createObject(control, { target: control, signalName: "orientationChanged" });
- var originalWidth = control.width;
- var originalHeight = control.height;
+ let originalWidth = control.width;
+ let originalHeight = control.height;
control.orientation = Qt.Horizontal;
compare(control.orientation, Qt.Horizontal);
compare(control.width, originalHeight);
diff --git a/tests/auto/quickcontrols/controls/data/tst_tooltip.qml b/tests/auto/quickcontrols/controls/data/tst_tooltip.qml
index 1aa63e56a2..205536c61c 100644
--- a/tests/auto/quickcontrols/controls/data/tst_tooltip.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_tooltip.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -37,9 +37,11 @@ TestCase {
target: ToolTip.toolTip
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(toolTip, testCase)
verify(control)
}
@@ -53,12 +55,12 @@ TestCase {
}
function test_properties(data) {
- var control = createTemporaryObject(toolTip, testCase)
+ let control = createTemporaryObject(toolTip, testCase)
verify(control)
compare(control[data.property], data.defaultValue)
- var spy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: data.signalName})
+ let spy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: data.signalName})
verify(spy.valid)
control[data.property] = data.setValue
@@ -75,24 +77,24 @@ TestCase {
}
function test_attached(data) {
- var item1 = createTemporaryObject(mouseArea, testCase)
+ let item1 = createTemporaryObject(mouseArea, testCase)
verify(item1)
- var item2 = createTemporaryObject(mouseArea, testCase)
+ let item2 = createTemporaryObject(mouseArea, testCase)
verify(item2)
// Reset the properties to the expected default values, in case
// we're not the first test that uses attached properties to be run.
- var sharedTip = ToolTip.toolTip
+ let sharedTip = ToolTip.toolTip
sharedTip[data.property] = data.defaultValue
compare(item1.ToolTip[data.property], data.defaultValue)
compare(item2.ToolTip[data.property], data.defaultValue)
- var spy1 = signalSpy.createObject(item1, {target: item1.ToolTip, signalName: data.signalName})
+ let spy1 = signalSpy.createObject(item1, {target: item1.ToolTip, signalName: data.signalName})
verify(spy1.valid)
- var spy2 = signalSpy.createObject(item2, {target: item2.ToolTip, signalName: data.signalName})
+ let spy2 = signalSpy.createObject(item2, {target: item2.ToolTip, signalName: data.signalName})
verify(spy2.valid)
sharedSpy.signalName = data.signalName
@@ -138,7 +140,7 @@ TestCase {
}
function test_delay(data) {
- var control = createTemporaryObject(toolTip, testCase, {delay: data.delay})
+ let control = createTemporaryObject(toolTip, testCase, {delay: data.delay})
compare(control.visible, false)
if (data.imperative)
@@ -157,7 +159,7 @@ TestCase {
}
function test_timeout(data) {
- var control = createTemporaryObject(toolTip, testCase, {timeout: 100})
+ let control = createTemporaryObject(toolTip, testCase, {timeout: 100})
compare(control.visible, false)
if (data.imperative)
@@ -179,7 +181,6 @@ TestCase {
function test_warning() {
ignoreWarning(new RegExp(".*QML QtObject: ToolTip must be attached to an Item"))
- ignoreWarning(new RegExp(".*: QML ToolTip: cannot find any window to open popup in."))
object.ToolTip.show("") // don't crash (QTBUG-56243)
}
@@ -206,7 +207,7 @@ TestCase {
}
function test_makeVisibleWhileExitTransitionRunning(data) {
- var control = createTemporaryObject(toolTipWithExitTransition, testCase)
+ let control = createTemporaryObject(toolTipWithExitTransition, testCase)
// Show, hide, and show the tooltip again. Its exit transition should
// start and get cancelled, and then its enter transition should run.
@@ -259,18 +260,18 @@ TestCase {
skip("Mouse hovering not functional on offscreen/minimal platforms")
// Window shortcuts (the default context for Shortcut) require the window to have focus.
- var window = testCase.Window.window
+ let window = testCase.Window.window
verify(window)
window.requestActivate()
tryCompare(window, "active", true)
- var root = createTemporaryObject(buttonAndShortcutComponent, testCase)
+ let root = createTemporaryObject(buttonAndShortcutComponent, testCase)
verify(root)
mouseMove(root.button, root.button.width / 2, root.button.height / 2)
tryCompare(root.button.ToolTip.toolTip, "visible", true)
- var shortcutActivatedSpy = signalSpy.createObject(root, { target: root.shortcut, signalName: "activated" })
+ let shortcutActivatedSpy = signalSpy.createObject(root, { target: root.shortcut, signalName: "activated" })
verify(shortcutActivatedSpy.valid)
keyPress(Qt.Key_A)
compare(shortcutActivatedSpy.count, 1)
@@ -295,13 +296,13 @@ TestCase {
// QTBUG-63644
function test_hover() {
- var root = createTemporaryObject(hoverComponent, testCase)
+ let root = createTemporaryObject(hoverComponent, testCase)
verify(root)
- var tooltip = root.tooltip
+ let tooltip = root.tooltip
verify(tooltip)
- for (var pos = 0; pos <= 25; pos += 5) {
+ for (let pos = 0; pos <= 25; pos += 5) {
mouseMove(root, pos, pos)
verify(tooltip.visible)
}
@@ -313,7 +314,7 @@ TestCase {
}
function test_nonAttachedToolTipShowAndHide() {
- var tip = createTemporaryObject(nonAttachedToolTipComponent, testCase)
+ let tip = createTemporaryObject(nonAttachedToolTipComponent, testCase)
verify(tip)
tip.show("hello");
verify(tip.visible)
@@ -346,11 +347,11 @@ TestCase {
// QTBUG-74226
function test_attachedTimeout() {
- var row = createTemporaryObject(timeoutButtonRowComponent, testCase)
+ let row = createTemporaryObject(timeoutButtonRowComponent, testCase)
verify(row)
// Press the button that has no timeout; it should stay visible.
- var button2 = row.children[1]
+ let button2 = row.children[1]
mousePress(button2)
compare(button2.down, true)
tryCompare(button2.ToolTip.toolTip, "opened", true)
@@ -365,7 +366,7 @@ TestCase {
tryCompare(button2.ToolTip, "visible", false)
// Now, press the first button that does have a timeout; it should close on its own eventually.
- var button1 = row.children[0]
+ let button1 = row.children[0]
mousePress(button1)
compare(button1.down, true)
// We use a short timeout to speed up the test, but tryCompare(...opened, true) then
@@ -402,7 +403,7 @@ TestCase {
// QTBUG-62350
function test_wrap() {
- var item = createTemporaryObject(wrapComponent, testCase)
+ let item = createTemporaryObject(wrapComponent, testCase)
verify(item)
// Avoid "cannot find window to popup in" warning that can occur if it's made visible too early.
@@ -466,4 +467,20 @@ TestCase {
mouseRelease(longTextButton)
tryCompare(longTextButton.ToolTip.toolTip, "visible", false)
}
+
+ Component {
+ id: initiallyVisibleComponent
+
+ Item {
+ ToolTip.text: "Some text"
+ ToolTip.visible: true
+ }
+ }
+
+ // QTBUG-75483
+ function test_initiallyVisible() {
+ let item = createTemporaryObject(initiallyVisibleComponent, testCase)
+ verify(item)
+ verify(item.ToolTip.visible)
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_tumbler.qml b/tests/auto/quickcontrols/controls/data/tst_tumbler.qml
index bb098f92db..3033dc756a 100644
--- a/tests/auto/quickcontrols/controls/data/tst_tumbler.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_tumbler.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
@@ -60,8 +60,8 @@ TestCase {
// visualItemIndex is from 0 to the amount of visible items.
function itemCenterPos(visualItemIndex) {
- var halfDelegateHeight = tumblerDelegateHeight / 2;
- var yCenter = tumbler.y + tumbler.topPadding + halfDelegateHeight
+ let halfDelegateHeight = tumblerDelegateHeight / 2;
+ let yCenter = tumbler.y + tumbler.topPadding + halfDelegateHeight
+ (tumblerDelegateHeight * visualItemIndex);
return Qt.point(tumblerXCenter(), yCenter);
}
@@ -71,22 +71,22 @@ TestCase {
}
function checkItemSizes() {
- var contentChildren = tumbler.wrap ? tumblerView.children : tumblerView.contentItem.children;
+ let contentChildren = tumbler.wrap ? tumblerView.children : tumblerView.contentItem.children;
verify(contentChildren.length >= tumbler.count);
- for (var i = 0; i < contentChildren.length; ++i) {
+ for (let i = 0; i < contentChildren.length; ++i) {
compare(contentChildren[i].width, tumbler.availableWidth);
compare(contentChildren[i].height, tumblerDelegateHeight);
}
}
function findView(parent) {
- for (var i = 0; i < parent.children.length; ++i) {
- var child = parent.children[i];
+ for (let i = 0; i < parent.children.length; ++i) {
+ let child = parent.children[i];
if (child.hasOwnProperty("currentIndex")) {
return child;
}
- var grandChild = findView(child);
+ let grandChild = findView(child);
if (grandChild)
return grandChild;
}
@@ -95,13 +95,13 @@ TestCase {
}
function findDelegateWithText(parent, text) {
- for (var i = 0; i < parent.children.length; ++i) {
- var child = parent.children[i];
+ for (let i = 0; i < parent.children.length; ++i) {
+ let child = parent.children[i];
if (child.hasOwnProperty("text") && child.text === text) {
return child;
}
- var grandChild = findDelegateWithText(child, text);
+ let grandChild = findDelegateWithText(child, text);
if (grandChild)
return grandChild;
}
@@ -113,9 +113,11 @@ TestCase {
text: modelData
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(defaultTumbler, testCase)
verify(control)
}
@@ -144,7 +146,7 @@ TestCase {
waitForRendering(tumbler);
// Set it through user interaction.
- var pos = Qt.point(tumblerXCenter(), tumbler.height / 2);
+ let pos = Qt.point(tumblerXCenter(), tumbler.height / 2);
mouseDrag(tumbler, pos.x, pos.y, 0, tumbler.height / 3, Qt.LeftButton, Qt.NoModifier, 200);
tryCompare(tumblerView, "offset", 1);
compare(tumbler.currentIndex, 4);
@@ -283,7 +285,7 @@ TestCase {
tumblerView.highlightMoveDuration = 0;
// Navigate upwards through entire wheel.
- for (var j = 0; j < tumbler.count - 1; ++j) {
+ for (let j = 0; j < tumbler.count - 1; ++j) {
keyClick(Qt.Key_Up, Qt.NoModifier);
tryCompare(tumblerView, "offset", j + 1);
compare(tumbler.currentIndex, tumbler.count - 1 - j);
@@ -294,7 +296,7 @@ TestCase {
compare(tumbler.currentIndex, 0);
// Navigate downwards through entire wheel.
- for (j = 0; j < tumbler.count - 1; ++j) {
+ for (let j = 0; j < tumbler.count - 1; ++j) {
keyClick(Qt.Key_Down, Qt.NoModifier);
tryCompare(tumblerView, "offset", tumbler.count - 1 - j);
compare(tumbler.currentIndex, j + 1);
@@ -314,9 +316,9 @@ TestCase {
checkItemSizes();
wait(tumblerView.highlightMoveDuration);
- var firstItemCenterPos = itemCenterPos(1);
- var firstItem = tumblerView.itemAt(firstItemCenterPos.x, firstItemCenterPos.y);
- var actualPos = testCase.mapFromItem(firstItem, 0, 0);
+ let firstItemCenterPos = itemCenterPos(1);
+ let firstItem = tumblerView.itemAt(firstItemCenterPos.x, firstItemCenterPos.y);
+ let actualPos = testCase.mapFromItem(firstItem, 0, 0);
compare(actualPos.x, tumbler.leftPadding);
compare(actualPos.y, tumbler.topPadding + 40);
@@ -332,13 +334,13 @@ TestCase {
fuzzyCompare(actualPos.x, tumbler.leftPadding, 0.0001);
fuzzyCompare(actualPos.y, tumbler.topPadding, 0.0001);
- var secondItemCenterPos = itemCenterPos(1);
- var secondItem = tumblerView.itemAt(secondItemCenterPos.x, secondItemCenterPos.y);
+ let secondItemCenterPos = itemCenterPos(1);
+ let secondItem = tumblerView.itemAt(secondItemCenterPos.x, secondItemCenterPos.y);
verify(secondItem);
verify(firstItem.y < secondItem.y);
- var thirdItemCenterPos = itemCenterPos(2);
- var thirdItem = tumblerView.itemAt(thirdItemCenterPos.x, thirdItemCenterPos.y);
+ let thirdItemCenterPos = itemCenterPos(2);
+ let thirdItem = tumblerView.itemAt(thirdItemCenterPos.x, thirdItemCenterPos.y);
verify(thirdItem);
verify(firstItem.y < thirdItem.y);
verify(secondItem.y < thirdItem.y);
@@ -348,7 +350,7 @@ TestCase {
tumbler = createTemporaryObject(tumblerComponent, testCase);
verify(tumbler);
- var mouseArea = createTemporaryQmlObject(
+ let mouseArea = createTemporaryQmlObject(
"import QtQuick; TextInput { activeFocusOnTab: true; width: 50; height: 50 }", testCase, "");
tumbler.forceActiveFocus();
@@ -360,7 +362,7 @@ TestCase {
}
function test_datePicker() {
- var component = Qt.createComponent("TumblerDatePicker.qml");
+ let component = Qt.createComponent("TumblerDatePicker.qml");
compare(component.status, Component.Ready, component.errorString());
tumbler = createTemporaryObject(component, testCase);
// Should not be any warnings.
@@ -422,7 +424,7 @@ TestCase {
}
function test_listViewTimePicker() {
- var root = createTemporaryObject(timePickerComponent, testCase);
+ let root = createTemporaryObject(timePickerComponent, testCase);
verify(root);
mouseDrag(root.minuteTumbler, root.minuteTumbler.width / 2, root.minuteTumbler.height / 2, 0, 50);
@@ -431,7 +433,7 @@ TestCase {
}
function test_displacement_data() {
- var data = [
+ let data = [
// At 0 offset, the first item is current.
{ count: 6, index: 0, offset: 0, expectedDisplacement: 0 },
{ count: 6, index: 1, offset: 0, expectedDisplacement: -1 },
@@ -462,9 +464,12 @@ TestCase {
// count == 1
{ count: 1, index: 0, offset: 0, expectedDisplacement: 0 }
];
- for (var i = 0; i < data.length; ++i) {
- var row = data[i];
- row.tag = "delegate" + row.index + " offset=" + row.offset + " expectedDisplacement=" + row.expectedDisplacement;
+ for (let i = 0; i < data.length; ++i) {
+ let row = data[i];
+ row.tag = "count=" + row.count
+ + " delegate" + row.index
+ + " offset=" + row.offset
+ + " expectedDisplacement=" + row.expectedDisplacement;
}
return data;
}
@@ -495,7 +500,7 @@ TestCase {
tumbler.model = data.count;
compare(tumbler.count, data.count);
- var delegate = findChild(tumblerView, "delegate" + data.index);
+ let delegate = findChild(tumblerView, "delegate" + data.index);
verify(delegate);
tumblerView.offset = data.offset;
@@ -552,7 +557,7 @@ TestCase {
function test_explicitlyNonwrapping() {
// Check that explicitly setting wrap to false works even when it was implicitly false.
- var explicitlyNonWrapping = createTemporaryObject(twoItemTumbler, testCase);
+ let explicitlyNonWrapping = createTemporaryObject(twoItemTumbler, testCase);
verify(explicitlyNonWrapping);
tryCompare(explicitlyNonWrapping, "wrap", false);
@@ -569,7 +574,7 @@ TestCase {
function test_explicitlyWrapping() {
// Check that explicitly setting wrap to true works even when it was implicitly true.
- var explicitlyWrapping = createTemporaryObject(tenItemTumbler, testCase);
+ let explicitlyWrapping = createTemporaryObject(tenItemTumbler, testCase);
verify(explicitlyWrapping);
compare(explicitlyWrapping.wrap, true);
@@ -641,14 +646,14 @@ TestCase {
}
function test_customContentItemAtConstruction(data) {
- var tumbler = createTemporaryObject(data.component, testCase);
+ let tumbler = createTemporaryObject(data.component, testCase);
// Shouldn't assert.
tumbler.model = 5;
compare(tumbler.count, 5);
tumbler.currentIndex = 2;
- var tumblerView = findView(tumbler);
+ let tumblerView = findView(tumbler);
compare(tumblerView.currentIndex, 2);
tumblerView.incrementCurrentIndex();
@@ -663,10 +668,10 @@ TestCase {
}
function findFirstDelegateWithText(view, text) {
- var delegate = null;
- var contentItem = view.hasOwnProperty("contentItem") ? view.contentItem : view;
- for (var i = 0; i < contentItem.children.length && !delegate; ++i) {
- var child = contentItem.children[i];
+ let delegate = null;
+ let contentItem = view.hasOwnProperty("contentItem") ? view.contentItem : view;
+ for (let i = 0; i < contentItem.children.length && !delegate; ++i) {
+ let child = contentItem.children[i];
if (child.hasOwnProperty("text") && child.text === text)
delegate = child;
}
@@ -689,16 +694,16 @@ TestCase {
tumbler.currentIndex = 2;
compare(tumblerView.currentIndex, 2);
- var contentItemComponent = Qt.createComponent(data.componentPath);
+ let contentItemComponent = Qt.createComponent(data.componentPath);
compare(contentItemComponent.status, Component.Ready);
- var customContentItem = createTemporaryObject(contentItemComponent, tumbler);
+ let customContentItem = createTemporaryObject(contentItemComponent, tumbler);
tumbler.contentItem = customContentItem;
compare(tumbler.count, 5);
tumblerView = findView(tumbler);
compare(tumblerView.currentIndex, 2);
- var delegate = findFirstDelegateWithText(tumblerView, "Custom2");
+ let delegate = findFirstDelegateWithText(tumblerView, "Custom2");
verify(delegate);
compare(delegate.height, defaultImplicitDelegateHeight);
tryCompare(delegate.Tumbler, "displacement", 0);
@@ -709,9 +714,9 @@ TestCase {
}
function test_displacementListView_data() {
- var offset = defaultListViewTumblerOffset;
+ let offset = defaultListViewTumblerOffset;
- var data = [
+ let data = [
// At 0 contentY, the first item is current.
{ contentY: offset, expectedDisplacements: [
{ index: 0, displacement: 0 },
@@ -738,8 +743,8 @@ TestCase {
{ index: 4, displacement: -0.5 } ]
}
];
- for (var i = 0; i < data.length; ++i) {
- var row = data[i];
+ for (let i = 0; i < data.length; ++i) {
+ let row = data[i];
row.tag = "contentY=" + row.contentY;
}
return data;
@@ -755,9 +760,9 @@ TestCase {
// Ensure assumptions about the tumbler used in our data() function are correct.
tumblerView = findView(tumbler);
compare(tumblerView.contentY, -defaultImplicitDelegateHeight);
- var delegateCount = 0;
- var listView = tumblerView;
- var listViewContentItem = tumblerView.contentItem;
+ let delegateCount = 0;
+ let listView = tumblerView;
+ let listViewContentItem = tumblerView.contentItem;
// We use the mouse instead of setting contentY directly, otherwise the
// items snap back into place. This doesn't seem to be an issue for
@@ -776,25 +781,25 @@ TestCase {
// to begin with, nothing changes (the displacement was always very close to 0 in the end).
// Ensure that we at least cover the distance required to reach the desired contentY.
- var distanceToReachContentY = data.contentY - defaultListViewTumblerOffset;
- var distance = Math.abs(distanceToReachContentY) + tumbler.height / 2;
+ let distanceToReachContentY = data.contentY - defaultListViewTumblerOffset;
+ let distance = Math.abs(distanceToReachContentY) + tumbler.height / 2;
// If distanceToReachContentY is 0, we're testing 0 displacement, so we don't need to do anything.
if (distanceToReachContentY != 0) {
mousePress(tumbler, tumblerXCenter(), tumblerYCenter());
- var dragDirection = distanceToReachContentY > 0 ? -1 : 1;
- for (var i = 0; i < distance && Math.floor(listView.contentY) !== Math.floor(data.contentY); ++i) {
+ let dragDirection = distanceToReachContentY > 0 ? -1 : 1;
+ for (let i = 0; i < distance && Math.floor(listView.contentY) !== Math.floor(data.contentY); ++i) {
mouseMove(tumbler, tumblerXCenter(), tumblerYCenter() + i * dragDirection);
wait(1); // because Flickable pays attention to velocity, we need some time between movements (qtdeclarative ebf07c3)
}
}
- for (var i = 0; i < data.expectedDisplacements.length; ++i) {
- var delegate = findChild(listViewContentItem, "delegate" + data.expectedDisplacements[i].index);
+ for (let i = 0; i < data.expectedDisplacements.length; ++i) {
+ let delegate = findChild(listViewContentItem, "delegate" + data.expectedDisplacements[i].index);
verify(delegate);
compare(delegate.height, defaultImplicitDelegateHeight);
// Due to the way we must perform this test, we can't expect high precision.
- var expectedDisplacement = data.expectedDisplacements[i].displacement;
+ let expectedDisplacement = data.expectedDisplacements[i].displacement;
fuzzyCompare(delegate.displacement, expectedDisplacement, 0.1,
"Delegate of ListView-based Tumbler at index " + data.expectedDisplacements[i].index
+ " has displacement of " + delegate.displacement + " when it should be " + expectedDisplacement);
@@ -807,10 +812,10 @@ TestCase {
function test_listViewFlickAboveBounds_data() {
// Tests that flicking above the bounds when already at the top of the
// tumbler doesn't result in an incorrect displacement.
- var data = [];
+ let data = [];
// Less than two items doesn't make sense. The default visibleItemCount
// is 3, so we test a bit more than double that.
- for (var i = 2; i <= 7; ++i) {
+ for (let i = 2; i <= 7; ++i) {
data.push({ tag: i + " items", model: i });
}
return data;
@@ -827,21 +832,21 @@ TestCase {
mousePress(tumbler, tumblerXCenter(), tumblerYCenter());
// Ensure it's stationary.
- var listView = tumblerView;
+ let listView = tumblerView;
compare(listView.contentY, defaultListViewTumblerOffset);
// We could just move up until the contentY changed, but this is safer.
- var distance = tumbler.height;
- var changed = false;
+ let distance = tumbler.height;
+ let changed = false;
- for (var i = 0; i < distance && !changed; ++i) {
+ for (let i = 0; i < distance && !changed; ++i) {
mouseMove(tumbler, tumblerXCenter(), tumblerYCenter() + i, 10);
// Don't test until the contentY has actually changed.
if (Math.abs(listView.contentY) - listView.preferredHighlightBegin > 0.01) {
- for (var delegateIndex = 0; delegateIndex < Math.min(tumbler.count, tumbler.visibleItemCount); ++delegateIndex) {
- var delegate = findChild(listView.contentItem, "delegate" + delegateIndex);
+ for (let delegateIndex = 0; delegateIndex < Math.min(tumbler.count, tumbler.visibleItemCount); ++delegateIndex) {
+ let delegate = findChild(listView.contentItem, "delegate" + delegateIndex);
verify(delegate);
verify(delegate.displacement <= -delegateIndex, "Delegate at index " + delegateIndex + " has a displacement of "
@@ -868,7 +873,7 @@ TestCase {
}
function test_visibleItemCount_data() {
- var data = [
+ let data = [
// e.g. {0: 2} = {delegate index: y pos / delegate height}
// Skip item at index 3, because it's out of view.
{ model: 6, visibleItemCount: 5, expectedYPositions: {0: 2, 1: 3, 2: 4, 4: 0} },
@@ -877,7 +882,7 @@ TestCase {
{ model: 2, visibleItemCount: 1, expectedYPositions: {0: 0} },
];
- for (var i = 0; i < data.length; ++i) {
+ for (let i = 0; i < data.length; ++i) {
data[i].tag = "items=" + data[i].model + ", visibleItemCount=" + data[i].visibleItemCount;
}
return data;
@@ -892,11 +897,11 @@ TestCase {
tumbler.model = data.model;
compare(tumbler.count, data.model);
- for (var delegateIndex = 0; delegateIndex < data.visibleItemCount; ++delegateIndex) {
+ for (let delegateIndex = 0; delegateIndex < data.visibleItemCount; ++delegateIndex) {
if (data.expectedYPositions.hasOwnProperty(delegateIndex)) {
- var delegate = findChild(tumblerView, "delegate" + delegateIndex);
+ let delegate = findChild(tumblerView, "delegate" + delegateIndex);
verify(delegate, "Delegate found at index " + delegateIndex);
- var expectedYPos = data.expectedYPositions[delegateIndex] * tumblerDelegateHeight;
+ let expectedYPos = data.expectedYPositions[delegateIndex] * tumblerDelegateHeight;
compare(delegate.mapToItem(tumbler.contentItem, 0, 0).y, expectedYPos);
}
}
@@ -925,7 +930,7 @@ TestCase {
createTemporaryObject(noParentDelegateComponent, null);
ignoreWarning(/.*Tumbler: attempting to access attached property on item without an \"index\" property/);
- var object = createTemporaryObject(noParentDelegateComponent, testCase);
+ let object = createTemporaryObject(noParentDelegateComponent, testCase);
verify(object);
}
@@ -944,15 +949,15 @@ TestCase {
}
function test_padding_data() {
- var data = [];
+ let data = [];
data.push({ padding: 0 });
data.push({ padding: 10 });
data.push({ left: 10, top: 10 });
data.push({ right: 10, bottom: 10 });
- for (var i = 0; i < data.length; ++i) {
- var tag = "";
+ for (let i = 0; i < data.length; ++i) {
+ let tag = "";
if (data[i].padding !== undefined)
tag += "padding: " + data[i].padding + " ";
@@ -1001,24 +1006,24 @@ TestCase {
compare(tumbler.contentItem.x, tumbler.leftPadding);
compare(tumbler.contentItem.y, tumbler.topPadding);
- var pathView = tumbler.contentItem;
- var expectedDelegateHeight = tumbler.availableHeight / tumbler.visibleItemCount;
- var itemIndicesInVisualOrder = [4, 0, 1];
- for (var i = 0; i < itemIndicesInVisualOrder.length; ++i) {
- var delegate = findChild(pathView, "delegate" + itemIndicesInVisualOrder[i]);
+ let pathView = tumbler.contentItem;
+ let expectedDelegateHeight = tumbler.availableHeight / tumbler.visibleItemCount;
+ let itemIndicesInVisualOrder = [4, 0, 1];
+ for (let i = 0; i < itemIndicesInVisualOrder.length; ++i) {
+ let delegate = findChild(pathView, "delegate" + itemIndicesInVisualOrder[i]);
verify(delegate, "Couldn't find delegate at index " + itemIndicesInVisualOrder[i]
+ " (iteration " + i + " out of " + (pathView.children.length - 1) + ")");
compare(delegate.width, tumbler.availableWidth);
compare(delegate.height, expectedDelegateHeight);
- var expectedY = tumbler.topPadding + i * expectedDelegateHeight;
- var mappedPos = delegate.mapToItem(null, delegate.width / 2, 0);
+ let expectedY = tumbler.topPadding + i * expectedDelegateHeight;
+ let mappedPos = delegate.mapToItem(null, delegate.width / 2, 0);
fuzzyCompare(mappedPos.y, expectedY, 0.5,
"Tumbler's PathView delegate at index " + itemIndicesInVisualOrder[i]
+ " should have a y pos of " + expectedY + ", but it's actually " + mappedPos.y.toFixed(20));
- var expectedX = tumbler.leftPadding;
+ let expectedX = tumbler.leftPadding;
compare(delegate.mapToItem(null, 0, 0).x, expectedX,
"Tumbler's PathView delegate at index " + itemIndicesInVisualOrder[i]
+ " should have a x pos of " + expectedX + ", but it's actually " + mappedPos.x.toFixed(20));
@@ -1047,7 +1052,7 @@ TestCase {
mousePress(tumbler, tumbler.width / 2, tumbler.height / 2, Qt.LeftButton)
compare(tumbler.moving, false)
- for (var y = tumbler.height / 2; y >= tumbler.height / 4; y -= 10)
+ for (let y = tumbler.height / 2; y >= tumbler.height / 4; y -= 10)
mouseMove(tumbler, tumbler.width / 2, y, 1)
compare(tumbler.moving, true)
@@ -1081,15 +1086,15 @@ TestCase {
}
function test_qtbug61374() {
- var row = createTemporaryObject(qtbug61374Component, testCase);
+ let row = createTemporaryObject(qtbug61374Component, testCase);
verify(row);
- var tumbler = row.tumbler;
+ let tumbler = row.tumbler;
tryCompare(tumbler, "currentIndex", 2);
tumblerView = findView(tumbler);
- var label = row.label;
+ let label = row.label;
compare(label.text, "2");
}
@@ -1121,16 +1126,16 @@ TestCase {
tryCompare(tumbler, "moving", false)
compare(tumbler.visibleItemCount, 5)
- for (var i = 0; i < 5; ++i) {
+ for (let i = 0; i < 5; ++i) {
// Find the item through its text, as that's easier than child/itemAt().
- var text = data.expectedVisibleIndices[i].toString()
- var item = findDelegateWithText(tumblerView, text)
+ let text = data.expectedVisibleIndices[i].toString()
+ let item = findDelegateWithText(tumblerView, text)
verify(item, "found no item with text \"" + text + "\"")
compare(item.text, data.expectedVisibleIndices[i].toString())
// Ensure that it's at the position we expect.
- var expectedPos = itemTopLeftPos(i)
- var actualPos = testCase.mapFromItem(item, 0, 0)
+ let expectedPos = itemTopLeftPos(i)
+ let actualPos = testCase.mapFromItem(item, 0, 0)
compare(actualPos.x, expectedPos.x, "expected delegate with text " + item.text
+ " to have an x pos of " + expectedPos.x + " but it was " + actualPos.x)
compare(actualPos.y, expectedPos.y, "expected delegate with text " + item.text
@@ -1147,7 +1152,7 @@ TestCase {
}
function test_setCurrentIndexOnImperativeModelChange() {
- var tumbler = createTemporaryObject(setCurrentIndexOnImperativeModelChangeComponent, testCase);
+ let tumbler = createTemporaryObject(setCurrentIndexOnImperativeModelChangeComponent, testCase);
verify(tumbler);
tumbler.model = 4
@@ -1184,10 +1189,10 @@ TestCase {
}
function test_setCurrentIndexOnDeclarativeModelChange() {
- var root = createTemporaryObject(setCurrentIndexOnDeclarativeModelChangeComponent, testCase);
+ let root = createTemporaryObject(setCurrentIndexOnDeclarativeModelChangeComponent, testCase);
verify(root);
- var tumbler = root.tumbler;
+ let tumbler = root.tumbler;
compare(tumbler.count, 4);
compare(tumbler.wrap, false);
tumblerView = findView(tumbler);
@@ -1214,7 +1219,7 @@ TestCase {
currentIndex: 15
})
- var delegate = findChild(tumblerView, "delegate15")
+ let delegate = findChild(tumblerView, "delegate15")
verify(delegate)
tryCompare(delegate, "displacement", 0)
@@ -1239,9 +1244,51 @@ TestCase {
}
function test_initialCurrentIndex() {
- var tumbler = createTemporaryObject(initialCurrentIndexTumbler, testCase, {wrap: true});
+ let tumbler = createTemporaryObject(initialCurrentIndexTumbler, testCase, {wrap: true});
compare(tumbler.currentIndex, 4);
tumbler = createTemporaryObject(initialCurrentIndexTumbler, testCase, {wrap: false});
compare(tumbler.currentIndex, 4);
}
+
+ // QTBUG-109995
+ Component {
+ id: flickTumbler
+ Flickable {
+ width: 50
+ height: 200
+ interactive: true
+ contentHeight: 400
+ property alias tumblerItem: noWrapTumbler
+ Tumbler {
+ id: noWrapTumbler
+ anchors.fill: parent
+ model: 20
+ wrap: false
+ }
+ }
+ }
+
+ function test_flick() {
+ let control = createTemporaryObject(flickTumbler, testCase)
+ verify(control)
+
+ let tumbler = control.tumblerItem
+ compare(tumbler.count, 20)
+ compare(tumbler.wrap, false)
+
+ let touch = touchEvent(tumbler)
+ let tumblerView = findView(tumbler)
+ let delegateHeight = tumblerView.children[0].children[0].height
+
+ // Move delegates through touch operation and check the current index
+ touch.press(0, tumblerView, control.width / 2, control.height / 2).commit()
+ // Move slowly, otherwise its considered as flick which cause current index
+ // to be varied according to its velocity
+ let scrollOffset = control.height / 2
+ for (; scrollOffset > delegateHeight / 2; scrollOffset-=5) {
+ touch.move(0, tumblerView, control.width / 2, scrollOffset).commit()
+ }
+ touch.release(0, tumblerView, control.width / 2, scrollOffset).commit()
+ tryCompare(tumblerView, "currentIndex", 2)
+ }
}
diff --git a/tests/auto/quickcontrols/controls/data/tst_weeknumbercolumn.qml b/tests/auto/quickcontrols/controls/data/tst_weeknumbercolumn.qml
index 40566b018c..11868bfbbf 100644
--- a/tests/auto/quickcontrols/controls/data/tst_weeknumbercolumn.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_weeknumbercolumn.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
@@ -18,15 +18,17 @@ TestCase {
WeekNumberColumn { }
}
- function test_defaults() {
+ function init() {
failOnWarning(/.?/)
+ }
+ function test_defaults() {
let control = createTemporaryObject(component, testCase)
verify(control)
}
function test_locale() {
- var control = component.createObject(testCase)
+ let control = component.createObject(testCase)
compare(control.contentItem.children.length, 6 + 1)
@@ -35,12 +37,12 @@ TestCase {
// en_US: [48...53]
control.locale = Qt.locale("en_US")
- for (var i = 0; i < 6; ++i)
+ for (let i = 0; i < 6; ++i)
compare(control.contentItem.children[i].text, (i + 48).toString())
// no_NO: [49...1]
control.locale = Qt.locale("no_NO")
- for (var j = 0; j < 5; ++j)
+ for (let j = 0; j < 5; ++j)
compare(control.contentItem.children[j].text, (j + 49).toString())
compare(control.contentItem.children[5].text, "1")
@@ -48,7 +50,7 @@ TestCase {
}
function test_range() {
- var control = component.createObject(testCase)
+ let control = component.createObject(testCase)
control.month = 0
compare(control.month, 0)
@@ -82,7 +84,7 @@ TestCase {
}
function test_font() {
- var control = component.createObject(testCase)
+ let control = component.createObject(testCase)
verify(control.contentItem.children[0])
diff --git a/tests/auto/quickcontrols/controls/fluentwinui3/BLACKLIST b/tests/auto/quickcontrols/controls/fluentwinui3/BLACKLIST
new file mode 100644
index 0000000000..3867b52f90
--- /dev/null
+++ b/tests/auto/quickcontrols/controls/fluentwinui3/BLACKLIST
@@ -0,0 +1,14 @@
+# See qtbase/src/testlib/qtestblacklist.cpp for format
+
+# until adding FluentWinUI3's own BusyIndicator implementation
+[BusyIndicator::test_visibility]
+*
+
+# until adding FluentWinUI3's own Page implementation
+[Page::test_layout]
+*
+
+# QTBUG-95750
+[RangeSlider::test_overlappingHandles]
+b2qt
+qnx
diff --git a/tests/auto/quickcontrols/controls/fluentwinui3/CMakeLists.txt b/tests/auto/quickcontrols/controls/fluentwinui3/CMakeLists.txt
new file mode 100644
index 0000000000..384b8c47f4
--- /dev/null
+++ b/tests/auto/quickcontrols/controls/fluentwinui3/CMakeLists.txt
@@ -0,0 +1,38 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_fluentwinui3 LANGUAGES C CXX ASM)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+# Collect test data
+file(GLOB_RECURSE test_data_glob
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../data/tst_*)
+list(APPEND test_data ${test_data_glob})
+
+qt_internal_add_test(tst_fluentwinui3
+ GUI
+ QMLTEST
+ SOURCES
+ tst_fluentwinui3.cpp
+ DEFINES
+ TST_CONTROLS_DATA="${CMAKE_CURRENT_SOURCE_DIR}/../data"
+ LIBRARIES
+ Qt::Gui
+ Qt::QuickControls2
+ TESTDATA ${test_data}
+)
+
+# Make the QML files available to Creator's locator.
+target_sources(tst_fluentwinui3
+ PRIVATE
+ ${test_data}
+)
+
+set_source_files_properties(${test_data}
+ PROPERTIES
+ HEADER_FILE_ONLY ON
+)
diff --git a/tests/auto/quickcontrols/controls/fluentwinui3/dependencies.qml b/tests/auto/quickcontrols/controls/fluentwinui3/dependencies.qml
new file mode 100644
index 0000000000..2b442ac527
--- /dev/null
+++ b/tests/auto/quickcontrols/controls/fluentwinui3/dependencies.qml
@@ -0,0 +1,6 @@
+import QtTest
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Controls.FluentWinUI3
+
+TestCase { }
diff --git a/tests/auto/quickcontrols/controls/fluentwinui3/dummy_imports.qml b/tests/auto/quickcontrols/controls/fluentwinui3/dummy_imports.qml
new file mode 100644
index 0000000000..66e184f138
--- /dev/null
+++ b/tests/auto/quickcontrols/controls/fluentwinui3/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 QtCore
+import QtQuick
+import QtQuick.NativeStyle
+import QtQuick.Layouts
+import Qt.labs.qmlmodels
+
+QtObject { }
diff --git a/tests/auto/quickcontrols/controls/fluentwinui3/tst_fluentwinui3.cpp b/tests/auto/quickcontrols/controls/fluentwinui3/tst_fluentwinui3.cpp
new file mode 100644
index 0000000000..9f67b3dc9e
--- /dev/null
+++ b/tests/auto/quickcontrols/controls/fluentwinui3/tst_fluentwinui3.cpp
@@ -0,0 +1,13 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtQuickTest/quicktest.h>
+#include <QtQuickControls2/qquickstyle.h>
+
+int main(int argc, char *argv[])
+{
+ QTEST_SET_MAIN_SOURCE_PATH
+ qputenv("QML_NO_TOUCH_COMPRESSION", "1");
+ QQuickStyle::setStyle("FluentWinUI3");
+ return quick_test_main(argc, argv, "tst_controls::FluentWinUI3", TST_CONTROLS_DATA);
+}
diff --git a/tests/auto/quickcontrols/controls/fusion/CMakeLists.txt b/tests/auto/quickcontrols/controls/fusion/CMakeLists.txt
index 5495efd858..672e0e18c3 100644
--- a/tests/auto/quickcontrols/controls/fusion/CMakeLists.txt
+++ b/tests/auto/quickcontrols/controls/fusion/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_fusion LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/controls/fusion/tst_fusion.cpp b/tests/auto/quickcontrols/controls/fusion/tst_fusion.cpp
index b7aa9aa434..3c1f255d6e 100644
--- a/tests/auto/quickcontrols/controls/fusion/tst_fusion.cpp
+++ b/tests/auto/quickcontrols/controls/fusion/tst_fusion.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
#include <QtQuickControls2/qquickstyle.h>
@@ -8,6 +8,9 @@ int main(int argc, char *argv[])
{
QTEST_SET_MAIN_SOURCE_PATH
qputenv("QML_NO_TOUCH_COMPRESSION", "1");
+ // The tests were originally written before native menus existed,
+ // and some of them try to open menus, which we can't test natively.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
QQuickStyle::setStyle("Fusion");
return quick_test_main(argc, argv, "tst_controls::Fusion", TST_CONTROLS_DATA);
}
diff --git a/tests/auto/quickcontrols/controls/imagine/CMakeLists.txt b/tests/auto/quickcontrols/controls/imagine/CMakeLists.txt
index 6efb1a0a45..6e95134e1b 100644
--- a/tests/auto/quickcontrols/controls/imagine/CMakeLists.txt
+++ b/tests/auto/quickcontrols/controls/imagine/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_imagine LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/controls/imagine/tst_imagine.cpp b/tests/auto/quickcontrols/controls/imagine/tst_imagine.cpp
index 1a46d26c1c..ca9ff3fddd 100644
--- a/tests/auto/quickcontrols/controls/imagine/tst_imagine.cpp
+++ b/tests/auto/quickcontrols/controls/imagine/tst_imagine.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
#include <QtQuickControls2/qquickstyle.h>
@@ -8,6 +8,9 @@ int main(int argc, char *argv[])
{
QTEST_SET_MAIN_SOURCE_PATH
qputenv("QML_NO_TOUCH_COMPRESSION", "1");
+ // The tests were originally written before native menus existed,
+ // and some of them try to open menus, which we can't test natively.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
QQuickStyle::setStyle("Imagine");
return quick_test_main(argc, argv, "tst_controls::Imagine", TST_CONTROLS_DATA);
}
diff --git a/tests/auto/quickcontrols/controls/ios/CMakeLists.txt b/tests/auto/quickcontrols/controls/ios/CMakeLists.txt
index fe6839990f..d0f111e66f 100644
--- a/tests/auto/quickcontrols/controls/ios/CMakeLists.txt
+++ b/tests/auto/quickcontrols/controls/ios/CMakeLists.txt
@@ -4,7 +4,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_ios LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
# Collect test data
diff --git a/tests/auto/quickcontrols/controls/ios/tst_ios.cpp b/tests/auto/quickcontrols/controls/ios/tst_ios.cpp
index 954b964958..b34a580e3c 100644
--- a/tests/auto/quickcontrols/controls/ios/tst_ios.cpp
+++ b/tests/auto/quickcontrols/controls/ios/tst_ios.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
#include <QtQuickControls2/qquickstyle.h>
@@ -8,6 +8,9 @@ int main(int argc, char *argv[])
{
QTEST_SET_MAIN_SOURCE_PATH
qputenv("QML_NO_TOUCH_COMPRESSION", "1");
+ // The tests were originally written before native menus existed,
+ // and some of them try to open menus, which we can't test natively.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
QQuickStyle::setStyle("iOS");
return quick_test_main(argc, argv, "tst_controls::iOS", TST_CONTROLS_DATA);
}
diff --git a/tests/auto/quickcontrols/controls/macos/CMakeLists.txt b/tests/auto/quickcontrols/controls/macos/CMakeLists.txt
index 04d186c63f..0d2e523a2a 100644
--- a/tests/auto/quickcontrols/controls/macos/CMakeLists.txt
+++ b/tests/auto/quickcontrols/controls/macos/CMakeLists.txt
@@ -4,7 +4,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_macos LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
# Collect test data
diff --git a/tests/auto/quickcontrols/controls/macos/tst_macos.cpp b/tests/auto/quickcontrols/controls/macos/tst_macos.cpp
index 59c8585f03..91ce22cc0b 100644
--- a/tests/auto/quickcontrols/controls/macos/tst_macos.cpp
+++ b/tests/auto/quickcontrols/controls/macos/tst_macos.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
#include <QtQuickControls2/qquickstyle.h>
@@ -10,6 +10,9 @@ int main(int argc, char *argv[])
qputenv("QML_NO_TOUCH_COMPRESSION", "1");
// See comment in tst_windows.cpp.
qputenv("QT_QUICK_CONTROLS_IGNORE_CUSTOMIZATION_WARNINGS", "1");
+ // The tests were originally written before native menus existed,
+ // and some of them try to open menus, which we can't test natively.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
QQuickStyle::setStyle("macOS");
return quick_test_main(argc, argv, "tst_controls::macOS", TST_CONTROLS_DATA);
}
diff --git a/tests/auto/quickcontrols/controls/material/CMakeLists.txt b/tests/auto/quickcontrols/controls/material/CMakeLists.txt
index 3e87bf1609..a528834c04 100644
--- a/tests/auto/quickcontrols/controls/material/CMakeLists.txt
+++ b/tests/auto/quickcontrols/controls/material/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_material LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/controls/material/tst_material.cpp b/tests/auto/quickcontrols/controls/material/tst_material.cpp
index 1fa55ab4dc..9a76046d23 100644
--- a/tests/auto/quickcontrols/controls/material/tst_material.cpp
+++ b/tests/auto/quickcontrols/controls/material/tst_material.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
#include <QtQuickControls2/qquickstyle.h>
@@ -8,6 +8,9 @@ int main(int argc, char *argv[])
{
QTEST_SET_MAIN_SOURCE_PATH
qputenv("QML_NO_TOUCH_COMPRESSION", "1");
+ // The tests were originally written before native menus existed,
+ // and some of them try to open menus, which we can't test natively.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
QQuickStyle::setStyle("Material");
return quick_test_main(argc, argv, "tst_controls::Material", TST_CONTROLS_DATA);
}
diff --git a/tests/auto/quickcontrols/controls/universal/CMakeLists.txt b/tests/auto/quickcontrols/controls/universal/CMakeLists.txt
index f0c7d2ed80..9e779420e7 100644
--- a/tests/auto/quickcontrols/controls/universal/CMakeLists.txt
+++ b/tests/auto/quickcontrols/controls/universal/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_universal LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/controls/universal/tst_universal.cpp b/tests/auto/quickcontrols/controls/universal/tst_universal.cpp
index 87faccc5ff..3cd41be836 100644
--- a/tests/auto/quickcontrols/controls/universal/tst_universal.cpp
+++ b/tests/auto/quickcontrols/controls/universal/tst_universal.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
#include <QtQuickControls2/qquickstyle.h>
@@ -8,6 +8,9 @@ int main(int argc, char *argv[])
{
QTEST_SET_MAIN_SOURCE_PATH
qputenv("QML_NO_TOUCH_COMPRESSION", "1");
+ // The tests were originally written before native menus existed,
+ // and some of them try to open menus, which we can't test natively.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
QQuickStyle::setStyle("Universal");
return quick_test_main(argc, argv, "tst_controls::Universal", TST_CONTROLS_DATA);
}
diff --git a/tests/auto/quickcontrols/controls/windows/CMakeLists.txt b/tests/auto/quickcontrols/controls/windows/CMakeLists.txt
index a5ba30a51b..e5f30d146b 100644
--- a/tests/auto/quickcontrols/controls/windows/CMakeLists.txt
+++ b/tests/auto/quickcontrols/controls/windows/CMakeLists.txt
@@ -4,7 +4,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_windows LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
# Collect test data
diff --git a/tests/auto/quickcontrols/controls/windows/tst_windows.cpp b/tests/auto/quickcontrols/controls/windows/tst_windows.cpp
index 560cec4383..bcd8fa35d8 100644
--- a/tests/auto/quickcontrols/controls/windows/tst_windows.cpp
+++ b/tests/auto/quickcontrols/controls/windows/tst_windows.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
#include <QtQuickControls2/qquickstyle.h>
@@ -17,6 +17,9 @@ int main(int argc, char *argv[])
// issued when default-constructing controls. For that we have
// tst_customization::noCustomizationWarningsForDefaultControls.
qputenv("QT_QUICK_CONTROLS_IGNORE_CUSTOMIZATION_WARNINGS", "1");
+ // The tests were originally written before native menus existed,
+ // and some of them try to open menus, which we can't test natively.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
QQuickStyle::setStyle("Windows");
return quick_test_main(argc, argv, "tst_controls::Windows", TST_CONTROLS_DATA);
}
diff --git a/tests/auto/quickcontrols/cursor/CMakeLists.txt b/tests/auto/quickcontrols/cursor/CMakeLists.txt
index 6d0fa9eed6..55ef2ebb5d 100644
--- a/tests/auto/quickcontrols/cursor/CMakeLists.txt
+++ b/tests/auto/quickcontrols/cursor/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_cursor LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/cursor/data/buttons.qml b/tests/auto/quickcontrols/cursor/data/buttons.qml
index b2a3cccc34..988233dfdd 100644
--- a/tests/auto/quickcontrols/cursor/data/buttons.qml
+++ b/tests/auto/quickcontrols/cursor/data/buttons.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/cursor/data/containers.qml b/tests/auto/quickcontrols/cursor/data/containers.qml
index 420a1a592d..51533db7f1 100644
--- a/tests/auto/quickcontrols/cursor/data/containers.qml
+++ b/tests/auto/quickcontrols/cursor/data/containers.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/cursor/data/editable.qml b/tests/auto/quickcontrols/cursor/data/editable.qml
index 1750c481b9..fdf2e1ada2 100644
--- a/tests/auto/quickcontrols/cursor/data/editable.qml
+++ b/tests/auto/quickcontrols/cursor/data/editable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/cursor/data/pageindicator.qml b/tests/auto/quickcontrols/cursor/data/pageindicator.qml
index 3f9178a50d..a29d1531e3 100644
--- a/tests/auto/quickcontrols/cursor/data/pageindicator.qml
+++ b/tests/auto/quickcontrols/cursor/data/pageindicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/cursor/data/scrollbar.qml b/tests/auto/quickcontrols/cursor/data/scrollbar.qml
index 1269cc9c6b..9e308e16a5 100644
--- a/tests/auto/quickcontrols/cursor/data/scrollbar.qml
+++ b/tests/auto/quickcontrols/cursor/data/scrollbar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/cursor/data/sliders.qml b/tests/auto/quickcontrols/cursor/data/sliders.qml
index ae2f8a962d..b27d8bd305 100644
--- a/tests/auto/quickcontrols/cursor/data/sliders.qml
+++ b/tests/auto/quickcontrols/cursor/data/sliders.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/cursor/tst_cursor.cpp b/tests/auto/quickcontrols/cursor/tst_cursor.cpp
index 02a25848dc..5f900e7ce0 100644
--- a/tests/auto/quickcontrols/cursor/tst_cursor.cpp
+++ b/tests/auto/quickcontrols/cursor/tst_cursor.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
diff --git a/tests/auto/quickcontrols/customization/CMakeLists.txt b/tests/auto/quickcontrols/customization/CMakeLists.txt
index 79dd408257..aa5106ee03 100644
--- a/tests/auto/quickcontrols/customization/CMakeLists.txt
+++ b/tests/auto/quickcontrols/customization/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_customization LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/AbstractButton.qml b/tests/auto/quickcontrols/customization/data/styles/empty/AbstractButton.qml
index 82e9e4bd4a..070ea02d2d 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/AbstractButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/AbstractButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/ApplicationWindow.qml b/tests/auto/quickcontrols/customization/data/styles/empty/ApplicationWindow.qml
index 92067837d3..cde9da12bd 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/ApplicationWindow.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/ApplicationWindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/BusyIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/empty/BusyIndicator.qml
index 2364737a9d..aa86dfd390 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/BusyIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/BusyIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Button.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Button.qml
index 7f14f150c1..78eca1d91e 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Button.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Button.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/CheckBox.qml b/tests/auto/quickcontrols/customization/data/styles/empty/CheckBox.qml
index 29b63ab1d4..3a2848fd24 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/CheckBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/CheckBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/CheckDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/empty/CheckDelegate.qml
index 0760efad05..5d1947be84 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/CheckDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/CheckDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/ComboBox.qml b/tests/auto/quickcontrols/customization/data/styles/empty/ComboBox.qml
index 4bb5b6538e..6f24f84f11 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/ComboBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/ComboBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Container.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Container.qml
index bcf0a906ac..b12be91825 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Container.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Container.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Control.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Control.qml
index 0a1db09a82..c9cf94064c 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Control.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Control.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/DelayButton.qml b/tests/auto/quickcontrols/customization/data/styles/empty/DelayButton.qml
index 849a82f9f7..231cc42459 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/DelayButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/DelayButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Dial.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Dial.qml
index b4d062c47b..2880dc1f90 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Dial.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Dial.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Dialog.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Dialog.qml
index b43550817a..a93d862d72 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Dialog.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Dialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/DialogButtonBox.qml b/tests/auto/quickcontrols/customization/data/styles/empty/DialogButtonBox.qml
index 14c4982d8c..1d668f6d3a 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/DialogButtonBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/DialogButtonBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Drawer.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Drawer.qml
index eee198aa10..2b9cca2123 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Drawer.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Drawer.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Frame.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Frame.qml
index cb7dc659e8..6879f49c2d 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Frame.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Frame.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/GroupBox.qml b/tests/auto/quickcontrols/customization/data/styles/empty/GroupBox.qml
index 42a26c114d..624ce1b472 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/GroupBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/GroupBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/ItemDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/empty/ItemDelegate.qml
index ff7cc8dac8..c6dc9097c3 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/ItemDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/ItemDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Label.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Label.qml
index a70541c788..c0a53b1ef7 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Label.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Label.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Menu.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Menu.qml
index 7f03fd0193..66fca1d3a9 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Menu.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Menu.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/MenuBar.qml b/tests/auto/quickcontrols/customization/data/styles/empty/MenuBar.qml
index 742492a467..ef60883189 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/MenuBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/MenuBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/MenuBarItem.qml b/tests/auto/quickcontrols/customization/data/styles/empty/MenuBarItem.qml
index b17f33bedc..6e39d5a323 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/MenuBarItem.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/MenuBarItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/MenuItem.qml b/tests/auto/quickcontrols/customization/data/styles/empty/MenuItem.qml
index c0639e3dc2..c8e5cfe1fc 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/MenuItem.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/MenuItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/MenuSeparator.qml b/tests/auto/quickcontrols/customization/data/styles/empty/MenuSeparator.qml
index f470175d9e..3fa89b958a 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/MenuSeparator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/MenuSeparator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Page.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Page.qml
index 39631703f7..76bbf857bf 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Page.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Page.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/PageIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/empty/PageIndicator.qml
index fa47a9e8e1..95d03279a5 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/PageIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/PageIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Pane.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Pane.qml
index 090ca74ef0..08b6fb7b69 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Pane.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Pane.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Popup.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Popup.qml
index 3fac8c15dd..766aee5c80 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Popup.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Popup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/ProgressBar.qml b/tests/auto/quickcontrols/customization/data/styles/empty/ProgressBar.qml
index 19701a3566..270fa946e8 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/ProgressBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/ProgressBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/RadioButton.qml b/tests/auto/quickcontrols/customization/data/styles/empty/RadioButton.qml
index e39736a523..a51248e730 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/RadioButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/RadioButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/RadioDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/empty/RadioDelegate.qml
index 1f4aa70f04..b22ddc74e0 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/RadioDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/RadioDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/RangeSlider.qml b/tests/auto/quickcontrols/customization/data/styles/empty/RangeSlider.qml
index 26f410b4b7..69ca2ae440 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/RangeSlider.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/RangeSlider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/RoundButton.qml b/tests/auto/quickcontrols/customization/data/styles/empty/RoundButton.qml
index adaaddc6e4..7415e98166 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/RoundButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/RoundButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/ScrollBar.qml b/tests/auto/quickcontrols/customization/data/styles/empty/ScrollBar.qml
index f10d4c9ce7..fafad4bb0f 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/ScrollBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/ScrollBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/ScrollIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/empty/ScrollIndicator.qml
index 211178f39a..68c20b6d98 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/ScrollIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/ScrollIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/ScrollView.qml b/tests/auto/quickcontrols/customization/data/styles/empty/ScrollView.qml
index b80618674b..5044d22853 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/ScrollView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/ScrollView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Slider.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Slider.qml
index 098b615ffa..c88530b5d5 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Slider.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Slider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/SpinBox.qml b/tests/auto/quickcontrols/customization/data/styles/empty/SpinBox.qml
index f7ef626944..c5a442111e 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/SpinBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/SpinBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/StackView.qml b/tests/auto/quickcontrols/customization/data/styles/empty/StackView.qml
index 5dc2edc34c..afb9e95767 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/StackView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/StackView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/SwipeDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/empty/SwipeDelegate.qml
index f802533d97..5e2d2e6b86 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/SwipeDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/SwipeDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/SwipeView.qml b/tests/auto/quickcontrols/customization/data/styles/empty/SwipeView.qml
index b4b6d3be6c..729be7853c 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/SwipeView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/SwipeView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Switch.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Switch.qml
index ace8f83321..0b808a9099 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Switch.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Switch.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/SwitchDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/empty/SwitchDelegate.qml
index c516e8b178..4b401bcaad 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/SwitchDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/SwitchDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/TabBar.qml b/tests/auto/quickcontrols/customization/data/styles/empty/TabBar.qml
index 3f71b3a0ec..26305ee022 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/TabBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/TabBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/TabButton.qml b/tests/auto/quickcontrols/customization/data/styles/empty/TabButton.qml
index 1bf2625589..3d9977c478 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/TabButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/TabButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/TextArea.qml b/tests/auto/quickcontrols/customization/data/styles/empty/TextArea.qml
index 01807d1606..e20a005b61 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/TextArea.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/TextArea.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/TextField.qml b/tests/auto/quickcontrols/customization/data/styles/empty/TextField.qml
index 6001e445a1..c816aeda65 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/TextField.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/TextField.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/ToolBar.qml b/tests/auto/quickcontrols/customization/data/styles/empty/ToolBar.qml
index b8dd897b6e..7beea9edb9 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/ToolBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/ToolBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/ToolButton.qml b/tests/auto/quickcontrols/customization/data/styles/empty/ToolButton.qml
index c6d9c4df5b..a15c893083 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/ToolButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/ToolButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/ToolSeparator.qml b/tests/auto/quickcontrols/customization/data/styles/empty/ToolSeparator.qml
index a9a26e562e..e9eb7e1dc8 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/ToolSeparator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/ToolSeparator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/ToolTip.qml b/tests/auto/quickcontrols/customization/data/styles/empty/ToolTip.qml
index 73ccddb576..383b36c108 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/ToolTip.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/ToolTip.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/empty/Tumbler.qml b/tests/auto/quickcontrols/customization/data/styles/empty/Tumbler.qml
index 11c3b0b552..63c7e9e848 100644
--- a/tests/auto/quickcontrols/customization/data/styles/empty/Tumbler.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/empty/Tumbler.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/AbstractButton.qml b/tests/auto/quickcontrols/customization/data/styles/identified/AbstractButton.qml
index 2db395fe7a..6f20decf6c 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/AbstractButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/AbstractButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/ApplicationWindow.qml b/tests/auto/quickcontrols/customization/data/styles/identified/ApplicationWindow.qml
index 846cc0fd00..f6c2d26599 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/ApplicationWindow.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/ApplicationWindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/BusyIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/identified/BusyIndicator.qml
index 177685b980..33e67d3f03 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/BusyIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/BusyIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Button.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Button.qml
index 2fea6704dc..2142cfb0d4 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Button.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Button.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/CheckBox.qml b/tests/auto/quickcontrols/customization/data/styles/identified/CheckBox.qml
index 3813aeeb7a..3c6235230d 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/CheckBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/CheckBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/CheckDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/identified/CheckDelegate.qml
index f78b3f7984..53b96f362f 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/CheckDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/CheckDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/ComboBox.qml b/tests/auto/quickcontrols/customization/data/styles/identified/ComboBox.qml
index 0945e49bb4..154ea327b0 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/ComboBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/ComboBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Container.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Container.qml
index 941b9b7467..bdd55c9995 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Container.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Container.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Control.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Control.qml
index f2f3928c8a..9daceba2d8 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Control.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Control.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/DelayButton.qml b/tests/auto/quickcontrols/customization/data/styles/identified/DelayButton.qml
index 18119a8aa6..fb94304c0b 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/DelayButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/DelayButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Dial.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Dial.qml
index 84dea2aa70..d4f30b834d 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Dial.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Dial.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Dialog.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Dialog.qml
index 4beace01e7..a77206778a 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Dialog.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Dialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/DialogButtonBox.qml b/tests/auto/quickcontrols/customization/data/styles/identified/DialogButtonBox.qml
index 0cec0f5a6c..288eb06c5c 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/DialogButtonBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/DialogButtonBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Drawer.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Drawer.qml
index d8634410cd..4c6d6fad97 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Drawer.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Drawer.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Frame.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Frame.qml
index 014b2a74b3..fe643bc3d5 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Frame.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Frame.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/GroupBox.qml b/tests/auto/quickcontrols/customization/data/styles/identified/GroupBox.qml
index 767259242c..7b8332e24f 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/GroupBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/GroupBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/ItemDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/identified/ItemDelegate.qml
index c7d4002407..13b99ae0a8 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/ItemDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/ItemDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Label.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Label.qml
index c9b00ff1ca..a611f58fa8 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Label.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Label.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Menu.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Menu.qml
index 822824dca8..6d273fbfe3 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Menu.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Menu.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/MenuBar.qml b/tests/auto/quickcontrols/customization/data/styles/identified/MenuBar.qml
index 94b5997165..ad8f72c7dd 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/MenuBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/MenuBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/MenuBarItem.qml b/tests/auto/quickcontrols/customization/data/styles/identified/MenuBarItem.qml
index da6c584ebc..16c4ecc8a5 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/MenuBarItem.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/MenuBarItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/MenuItem.qml b/tests/auto/quickcontrols/customization/data/styles/identified/MenuItem.qml
index 4ba04908ad..7a199e5e67 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/MenuItem.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/MenuItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/MenuSeparator.qml b/tests/auto/quickcontrols/customization/data/styles/identified/MenuSeparator.qml
index 6928eb01bc..b3f08a4b76 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/MenuSeparator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/MenuSeparator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Page.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Page.qml
index d63e4ce80d..7b7e45952e 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Page.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Page.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/PageIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/identified/PageIndicator.qml
index c47cb69e9e..bcbe688e7a 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/PageIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/PageIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Pane.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Pane.qml
index c5739700d3..01c08ecabd 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Pane.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Pane.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Popup.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Popup.qml
index e71be2f3de..f944b58382 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Popup.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Popup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/ProgressBar.qml b/tests/auto/quickcontrols/customization/data/styles/identified/ProgressBar.qml
index d1cfd16419..c3e5734fe4 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/ProgressBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/ProgressBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/RadioButton.qml b/tests/auto/quickcontrols/customization/data/styles/identified/RadioButton.qml
index ce64bdee5a..8147129984 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/RadioButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/RadioButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/RadioDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/identified/RadioDelegate.qml
index eeba29faa7..3c5ae0e1c3 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/RadioDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/RadioDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/RangeSlider.qml b/tests/auto/quickcontrols/customization/data/styles/identified/RangeSlider.qml
index 1fae11c2fa..5c21f529da 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/RangeSlider.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/RangeSlider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/RoundButton.qml b/tests/auto/quickcontrols/customization/data/styles/identified/RoundButton.qml
index b431a3a02c..910f788d02 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/RoundButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/RoundButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/ScrollBar.qml b/tests/auto/quickcontrols/customization/data/styles/identified/ScrollBar.qml
index 4bb5da5a18..8f225e378c 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/ScrollBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/ScrollBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/ScrollIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/identified/ScrollIndicator.qml
index a62b36afa2..6e312c99cc 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/ScrollIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/ScrollIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/ScrollView.qml b/tests/auto/quickcontrols/customization/data/styles/identified/ScrollView.qml
index 94cb1bc1a5..2bc4d83305 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/ScrollView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/ScrollView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Slider.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Slider.qml
index 5298a1556e..806243e3ba 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Slider.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Slider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/SpinBox.qml b/tests/auto/quickcontrols/customization/data/styles/identified/SpinBox.qml
index 2e285b0f47..345113ee2b 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/SpinBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/SpinBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/StackView.qml b/tests/auto/quickcontrols/customization/data/styles/identified/StackView.qml
index 5c5cd31af4..d770b5f356 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/StackView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/StackView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/SwipeDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/identified/SwipeDelegate.qml
index 403b7d5a82..1cc00a4dfb 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/SwipeDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/SwipeDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/SwipeView.qml b/tests/auto/quickcontrols/customization/data/styles/identified/SwipeView.qml
index 8c8345a524..3525a0102a 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/SwipeView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/SwipeView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Switch.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Switch.qml
index 9fc0c0f010..0bf7f07176 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Switch.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Switch.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/SwitchDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/identified/SwitchDelegate.qml
index 3f7f9568fb..87f8fe72bf 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/SwitchDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/SwitchDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/TabBar.qml b/tests/auto/quickcontrols/customization/data/styles/identified/TabBar.qml
index 50e36498b7..dd02c30d38 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/TabBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/TabBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/TabButton.qml b/tests/auto/quickcontrols/customization/data/styles/identified/TabButton.qml
index 19145e14fd..f054365b04 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/TabButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/TabButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/TextArea.qml b/tests/auto/quickcontrols/customization/data/styles/identified/TextArea.qml
index a7d4e212f0..7029f69c65 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/TextArea.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/TextArea.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/TextField.qml b/tests/auto/quickcontrols/customization/data/styles/identified/TextField.qml
index 3d78c4b73c..06ffbd57f8 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/TextField.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/TextField.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/ToolBar.qml b/tests/auto/quickcontrols/customization/data/styles/identified/ToolBar.qml
index b328828267..2fe8d79446 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/ToolBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/ToolBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/ToolButton.qml b/tests/auto/quickcontrols/customization/data/styles/identified/ToolButton.qml
index 465de9a6f1..28ce2d0309 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/ToolButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/ToolButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/ToolSeparator.qml b/tests/auto/quickcontrols/customization/data/styles/identified/ToolSeparator.qml
index 81c8f40178..e1ebb0164f 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/ToolSeparator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/ToolSeparator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/ToolTip.qml b/tests/auto/quickcontrols/customization/data/styles/identified/ToolTip.qml
index 2d8533dd0a..dfd5d71dea 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/ToolTip.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/ToolTip.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/identified/Tumbler.qml b/tests/auto/quickcontrols/customization/data/styles/identified/Tumbler.qml
index 67d4cd9b64..0a60e52ba7 100644
--- a/tests/auto/quickcontrols/customization/data/styles/identified/Tumbler.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/identified/Tumbler.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/AbstractButton.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/AbstractButton.qml
index b29c8fa15e..7f9faffc6f 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/AbstractButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/AbstractButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/ApplicationWindow.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/ApplicationWindow.qml
index 437410b72d..d733a7d90d 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/ApplicationWindow.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/ApplicationWindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/BusyIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/BusyIndicator.qml
index 6c1ed812b7..bd33867410 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/BusyIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/BusyIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Button.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Button.qml
index d0bfc4c563..43aacf2f01 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Button.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Button.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/CheckBox.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/CheckBox.qml
index 34d01e4e70..fb11260f8d 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/CheckBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/CheckBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/CheckDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/CheckDelegate.qml
index e17820ac4e..9eada2bc70 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/CheckDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/CheckDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/ComboBox.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/ComboBox.qml
index 611358a381..de49947e22 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/ComboBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/ComboBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Container.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Container.qml
index d6276f222e..d595d9ffc1 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Container.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Container.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Control.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Control.qml
index bb924ce15c..82b60c4f8a 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Control.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Control.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/DelayButton.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/DelayButton.qml
index 60a1d67e62..39c866faa5 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/DelayButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/DelayButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Dial.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Dial.qml
index a16ad247ac..a1568274b4 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Dial.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Dial.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Dialog.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Dialog.qml
index 2cd9bb9b20..5a6e94cd5c 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Dialog.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Dialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/DialogButtonBox.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/DialogButtonBox.qml
index 23eea3c0df..7e034fca9e 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/DialogButtonBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/DialogButtonBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Drawer.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Drawer.qml
index 0fbc879fb2..aee8d27814 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Drawer.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Drawer.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Frame.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Frame.qml
index c84280cb21..14a34ed78c 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Frame.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Frame.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/GroupBox.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/GroupBox.qml
index 518a836e92..07eb825747 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/GroupBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/GroupBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/ItemDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/ItemDelegate.qml
index 7150c79aa4..e6a99f7042 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/ItemDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/ItemDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Label.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Label.qml
index 662e22eac5..c1edb306a8 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Label.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Label.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Menu.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Menu.qml
index 173c50f7e8..198c58a66a 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Menu.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Menu.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuBar.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuBar.qml
index 680caa9ada..6b7d869992 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuBarItem.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuBarItem.qml
index b3cdc391b9..7c0b048739 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuBarItem.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuBarItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuItem.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuItem.qml
index 1f277bc466..a1fbe406c5 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuItem.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuSeparator.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuSeparator.qml
index e9ad13b303..41b0fea578 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuSeparator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/MenuSeparator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Page.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Page.qml
index 0ddf3f5b51..0f2222310f 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Page.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Page.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/PageIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/PageIndicator.qml
index bc4c22f093..339ee26989 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/PageIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/PageIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Pane.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Pane.qml
index 816dcf5669..8e375a1c19 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Pane.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Pane.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Popup.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Popup.qml
index 55dac84936..d6cf4057ae 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Popup.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Popup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/ProgressBar.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/ProgressBar.qml
index 9ce1cd99f3..ffc9de2d35 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/ProgressBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/ProgressBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/RadioButton.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/RadioButton.qml
index e76b465c69..729f27ad7a 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/RadioButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/RadioButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/RadioDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/RadioDelegate.qml
index 4514f466c8..1c2fbf539a 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/RadioDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/RadioDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/RangeSlider.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/RangeSlider.qml
index d747ce8bc2..24da75f6d5 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/RangeSlider.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/RangeSlider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/RoundButton.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/RoundButton.qml
index 5152ed430f..2280e1a0a9 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/RoundButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/RoundButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollBar.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollBar.qml
index 55e74e088b..19f19955e6 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollIndicator.qml
index 9bf0a176e1..87548c46a7 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollView.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollView.qml
index 1029e4ed20..8c8e460006 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/ScrollView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Slider.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Slider.qml
index 52038ea8ed..643b586f2a 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Slider.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Slider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/SpinBox.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/SpinBox.qml
index 388e82e51b..487207d534 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/SpinBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/SpinBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/StackView.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/StackView.qml
index 2664fea8d7..2e6f395587 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/StackView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/StackView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/SwipeDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/SwipeDelegate.qml
index 71df762fe8..71b6936ced 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/SwipeDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/SwipeDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/SwipeView.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/SwipeView.qml
index b0801f7a74..ba3ead1ce9 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/SwipeView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/SwipeView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Switch.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Switch.qml
index f413f5b310..a93766a29d 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Switch.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Switch.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/SwitchDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/SwitchDelegate.qml
index 9342280478..5a2987b7cf 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/SwitchDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/SwitchDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/TabBar.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/TabBar.qml
index ec59e9eedc..9a003d1bed 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/TabBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/TabBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/TabButton.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/TabButton.qml
index 9a3eda7aa9..bdc2dfb02f 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/TabButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/TabButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/TextArea.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/TextArea.qml
index fe03103e9f..c4ae8ece64 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/TextArea.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/TextArea.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/TextField.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/TextField.qml
index ff2e08e82e..4857153785 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/TextField.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/TextField.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolBar.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolBar.qml
index 73e8d45187..0792bd668f 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolButton.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolButton.qml
index f45e98f851..76fc32bcad 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolSeparator.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolSeparator.qml
index 840bd16711..eedac97c3e 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolSeparator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolSeparator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolTip.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolTip.qml
index 9d6e77cb60..6cfb463c27 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolTip.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/ToolTip.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/incomplete/Tumbler.qml b/tests/auto/quickcontrols/customization/data/styles/incomplete/Tumbler.qml
index dba21f56d1..170aa2ffc3 100644
--- a/tests/auto/quickcontrols/customization/data/styles/incomplete/Tumbler.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/incomplete/Tumbler.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/AbstractButton.qml b/tests/auto/quickcontrols/customization/data/styles/override/AbstractButton.qml
index ba1b1cb8fa..1a2baaa0ce 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/AbstractButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/AbstractButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/ApplicationWindow.qml b/tests/auto/quickcontrols/customization/data/styles/override/ApplicationWindow.qml
index d2439bfb84..84df787316 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/ApplicationWindow.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/ApplicationWindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/BusyIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/override/BusyIndicator.qml
index 827b45810a..bc2ad21833 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/BusyIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/BusyIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Button.qml b/tests/auto/quickcontrols/customization/data/styles/override/Button.qml
index a5bea3ebfe..367d074ba6 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Button.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Button.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/CheckBox.qml b/tests/auto/quickcontrols/customization/data/styles/override/CheckBox.qml
index aa7230cbd9..e60790b716 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/CheckBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/CheckBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/CheckDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/override/CheckDelegate.qml
index ea0b768bb4..cfcecd22e4 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/CheckDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/CheckDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/ComboBox.qml b/tests/auto/quickcontrols/customization/data/styles/override/ComboBox.qml
index ba2467e0be..081975ab4b 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/ComboBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/ComboBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Container.qml b/tests/auto/quickcontrols/customization/data/styles/override/Container.qml
index 68186cd2e0..8774f692f0 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Container.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Container.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Control.qml b/tests/auto/quickcontrols/customization/data/styles/override/Control.qml
index b9ca4c2643..a47f59306e 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Control.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Control.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/DelayButton.qml b/tests/auto/quickcontrols/customization/data/styles/override/DelayButton.qml
index 68ff2684d3..e329c5c2de 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/DelayButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/DelayButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Dial.qml b/tests/auto/quickcontrols/customization/data/styles/override/Dial.qml
index e451b6b0c2..b8dc00e7ef 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Dial.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Dial.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Dialog.qml b/tests/auto/quickcontrols/customization/data/styles/override/Dialog.qml
index 1870887243..aa6daebb61 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Dialog.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Dialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/DialogButtonBox.qml b/tests/auto/quickcontrols/customization/data/styles/override/DialogButtonBox.qml
index 4e7ceb0ab6..f37b1f8f04 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/DialogButtonBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/DialogButtonBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Drawer.qml b/tests/auto/quickcontrols/customization/data/styles/override/Drawer.qml
index 0de7097601..63bae6f606 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Drawer.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Drawer.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Frame.qml b/tests/auto/quickcontrols/customization/data/styles/override/Frame.qml
index 3e4effff0a..21b11a370b 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Frame.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Frame.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/GroupBox.qml b/tests/auto/quickcontrols/customization/data/styles/override/GroupBox.qml
index a50e3a519b..db173c00ea 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/GroupBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/GroupBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/ItemDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/override/ItemDelegate.qml
index 4e4f8d0fdd..c1d25096ed 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/ItemDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/ItemDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Label.qml b/tests/auto/quickcontrols/customization/data/styles/override/Label.qml
index 22ea5aab7c..e7d03faf00 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Label.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Label.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Menu.qml b/tests/auto/quickcontrols/customization/data/styles/override/Menu.qml
index 88d8510675..e040f7e0c9 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Menu.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Menu.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/MenuBar.qml b/tests/auto/quickcontrols/customization/data/styles/override/MenuBar.qml
index 90aa93ca19..9f33e0f4e3 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/MenuBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/MenuBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/MenuBarItem.qml b/tests/auto/quickcontrols/customization/data/styles/override/MenuBarItem.qml
index 18db0060a1..39fbf4b991 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/MenuBarItem.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/MenuBarItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/MenuItem.qml b/tests/auto/quickcontrols/customization/data/styles/override/MenuItem.qml
index 43acebc514..96aab5f75e 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/MenuItem.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/MenuItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/MenuSeparator.qml b/tests/auto/quickcontrols/customization/data/styles/override/MenuSeparator.qml
index 703e381698..a5989b9506 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/MenuSeparator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/MenuSeparator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Page.qml b/tests/auto/quickcontrols/customization/data/styles/override/Page.qml
index 2fa1ad4d44..22cc330f47 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Page.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Page.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/PageIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/override/PageIndicator.qml
index 4e4cef6d90..3e5342725e 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/PageIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/PageIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Pane.qml b/tests/auto/quickcontrols/customization/data/styles/override/Pane.qml
index 8a281da2b0..d476c5d60b 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Pane.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Pane.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Popup.qml b/tests/auto/quickcontrols/customization/data/styles/override/Popup.qml
index 6dfa3b20e4..98b157e010 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Popup.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Popup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/ProgressBar.qml b/tests/auto/quickcontrols/customization/data/styles/override/ProgressBar.qml
index e111790fe3..4477c659da 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/ProgressBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/ProgressBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/RadioButton.qml b/tests/auto/quickcontrols/customization/data/styles/override/RadioButton.qml
index b7a3a0a10d..751104590d 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/RadioButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/RadioButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/RadioDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/override/RadioDelegate.qml
index 83c0d73551..8a093c9870 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/RadioDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/RadioDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/RangeSlider.qml b/tests/auto/quickcontrols/customization/data/styles/override/RangeSlider.qml
index 3025960649..a4286f6b95 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/RangeSlider.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/RangeSlider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/RoundButton.qml b/tests/auto/quickcontrols/customization/data/styles/override/RoundButton.qml
index 3949749ed2..77ce760dff 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/RoundButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/RoundButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/ScrollBar.qml b/tests/auto/quickcontrols/customization/data/styles/override/ScrollBar.qml
index a546bf2eec..ebf1078181 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/ScrollBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/ScrollBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/ScrollIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/override/ScrollIndicator.qml
index f514210c1a..876425cb1f 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/ScrollIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/ScrollIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/ScrollView.qml b/tests/auto/quickcontrols/customization/data/styles/override/ScrollView.qml
index ae6da7860b..6b2aea3c1b 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/ScrollView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/ScrollView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Slider.qml b/tests/auto/quickcontrols/customization/data/styles/override/Slider.qml
index 5ced07590a..19e11901e3 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Slider.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Slider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/SpinBox.qml b/tests/auto/quickcontrols/customization/data/styles/override/SpinBox.qml
index 66c13d3cf8..34fa33089e 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/SpinBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/SpinBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/StackView.qml b/tests/auto/quickcontrols/customization/data/styles/override/StackView.qml
index 8759551ae1..e9ec4fda2f 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/StackView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/StackView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/SwipeDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/override/SwipeDelegate.qml
index ae994c612c..fc669d48df 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/SwipeDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/SwipeDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/SwipeView.qml b/tests/auto/quickcontrols/customization/data/styles/override/SwipeView.qml
index d0b584bfd4..a6517cf521 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/SwipeView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/SwipeView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Switch.qml b/tests/auto/quickcontrols/customization/data/styles/override/Switch.qml
index 83e5f2b56b..cf564ac8d5 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Switch.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Switch.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/SwitchDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/override/SwitchDelegate.qml
index 5e75fdbd64..6e297aafe2 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/SwitchDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/SwitchDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/TabBar.qml b/tests/auto/quickcontrols/customization/data/styles/override/TabBar.qml
index 0437d3b5af..22bb535e05 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/TabBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/TabBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/TabButton.qml b/tests/auto/quickcontrols/customization/data/styles/override/TabButton.qml
index ab78b3246f..cdbdfb2a65 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/TabButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/TabButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/TextArea.qml b/tests/auto/quickcontrols/customization/data/styles/override/TextArea.qml
index 17d1883624..b986c8358d 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/TextArea.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/TextArea.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/TextField.qml b/tests/auto/quickcontrols/customization/data/styles/override/TextField.qml
index 22c21fd751..e4c11beb7b 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/TextField.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/TextField.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/ToolBar.qml b/tests/auto/quickcontrols/customization/data/styles/override/ToolBar.qml
index 957f3f7b5b..fd169b57ba 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/ToolBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/ToolBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/ToolButton.qml b/tests/auto/quickcontrols/customization/data/styles/override/ToolButton.qml
index 19999c8a4a..cc6e3e916f 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/ToolButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/ToolButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/ToolSeparator.qml b/tests/auto/quickcontrols/customization/data/styles/override/ToolSeparator.qml
index b88fba1bab..683fdf72f5 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/ToolSeparator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/ToolSeparator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/ToolTip.qml b/tests/auto/quickcontrols/customization/data/styles/override/ToolTip.qml
index b4922d05eb..720328ed14 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/ToolTip.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/ToolTip.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/override/Tumbler.qml b/tests/auto/quickcontrols/customization/data/styles/override/Tumbler.qml
index ac49cd7675..e972865093 100644
--- a/tests/auto/quickcontrols/customization/data/styles/override/Tumbler.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/override/Tumbler.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import "../simple" as Simple
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/AbstractButton.qml b/tests/auto/quickcontrols/customization/data/styles/simple/AbstractButton.qml
index f0d9935706..b26f291ef0 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/AbstractButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/AbstractButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/ApplicationWindow.qml b/tests/auto/quickcontrols/customization/data/styles/simple/ApplicationWindow.qml
index 8f3f02a05a..1e529d0631 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/ApplicationWindow.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/ApplicationWindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/BusyIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/simple/BusyIndicator.qml
index d5520d2ba6..5fef119a82 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/BusyIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/BusyIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Button.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Button.qml
index b71c5e3af9..8ee7716b77 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Button.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Button.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/CheckBox.qml b/tests/auto/quickcontrols/customization/data/styles/simple/CheckBox.qml
index aef812111a..ff507b930a 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/CheckBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/CheckBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/CheckDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/simple/CheckDelegate.qml
index 06d5ac9cb0..b61e305c84 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/CheckDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/CheckDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/ComboBox.qml b/tests/auto/quickcontrols/customization/data/styles/simple/ComboBox.qml
index c5519f1c2a..2d8ceb8503 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/ComboBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/ComboBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Container.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Container.qml
index 85c59b4053..b8953a5944 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Container.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Container.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Control.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Control.qml
index 7e4808101b..3fc90a7d64 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Control.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Control.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/DelayButton.qml b/tests/auto/quickcontrols/customization/data/styles/simple/DelayButton.qml
index db6dd16514..0bba61fd3b 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/DelayButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/DelayButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Dial.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Dial.qml
index 6365f50387..d75c267fa9 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Dial.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Dial.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Dialog.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Dialog.qml
index b17a593b84..d847bed730 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Dialog.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Dialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/DialogButtonBox.qml b/tests/auto/quickcontrols/customization/data/styles/simple/DialogButtonBox.qml
index b994d6a8b6..5e62f4bcba 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/DialogButtonBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/DialogButtonBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Drawer.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Drawer.qml
index 3b6257b4f2..cd7839812e 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Drawer.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Drawer.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Frame.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Frame.qml
index e1730dfbe6..229c2d7a35 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Frame.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Frame.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/GroupBox.qml b/tests/auto/quickcontrols/customization/data/styles/simple/GroupBox.qml
index 9aaad3a0c1..53b9cb9857 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/GroupBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/GroupBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/ItemDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/simple/ItemDelegate.qml
index 0f5c22addd..cb157f6e4f 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/ItemDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/ItemDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Label.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Label.qml
index f128725923..10e801f909 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Label.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Label.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Menu.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Menu.qml
index f494d37711..90129b88f8 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Menu.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Menu.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/MenuBar.qml b/tests/auto/quickcontrols/customization/data/styles/simple/MenuBar.qml
index ee6aecefe6..91f129471a 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/MenuBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/MenuBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/MenuBarItem.qml b/tests/auto/quickcontrols/customization/data/styles/simple/MenuBarItem.qml
index f0271ba20f..101aecf079 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/MenuBarItem.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/MenuBarItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/MenuItem.qml b/tests/auto/quickcontrols/customization/data/styles/simple/MenuItem.qml
index 7dee9ce2f3..991c2b0de7 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/MenuItem.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/MenuItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/MenuSeparator.qml b/tests/auto/quickcontrols/customization/data/styles/simple/MenuSeparator.qml
index bbb90b6f62..a620732015 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/MenuSeparator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/MenuSeparator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Page.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Page.qml
index 4dc17112e9..ee06dcca31 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Page.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Page.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/PageIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/simple/PageIndicator.qml
index 59ce9282dc..31b6f99581 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/PageIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/PageIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Pane.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Pane.qml
index 0873baa770..76a852aff8 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Pane.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Pane.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Popup.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Popup.qml
index ebdb88f8a2..ed6c99da64 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Popup.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Popup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/ProgressBar.qml b/tests/auto/quickcontrols/customization/data/styles/simple/ProgressBar.qml
index c6cd7bb7d6..a47e1b7ec2 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/ProgressBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/ProgressBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/RadioButton.qml b/tests/auto/quickcontrols/customization/data/styles/simple/RadioButton.qml
index a80230c455..dd0f335bac 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/RadioButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/RadioButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/RadioDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/simple/RadioDelegate.qml
index cdded1165c..db61d8302a 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/RadioDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/RadioDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/RangeSlider.qml b/tests/auto/quickcontrols/customization/data/styles/simple/RangeSlider.qml
index 0227f4d296..0da700d6f6 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/RangeSlider.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/RangeSlider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/RoundButton.qml b/tests/auto/quickcontrols/customization/data/styles/simple/RoundButton.qml
index 0a9e5e13d1..faa3211241 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/RoundButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/RoundButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/ScrollBar.qml b/tests/auto/quickcontrols/customization/data/styles/simple/ScrollBar.qml
index a5cd90089c..304eff76a4 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/ScrollBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/ScrollBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/ScrollIndicator.qml b/tests/auto/quickcontrols/customization/data/styles/simple/ScrollIndicator.qml
index ce1d6a919c..00fd335883 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/ScrollIndicator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/ScrollIndicator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/ScrollView.qml b/tests/auto/quickcontrols/customization/data/styles/simple/ScrollView.qml
index 765bb87f4a..7dafc4dfaf 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/ScrollView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/ScrollView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Slider.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Slider.qml
index b91e93941f..8695be1ae8 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Slider.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Slider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/SpinBox.qml b/tests/auto/quickcontrols/customization/data/styles/simple/SpinBox.qml
index 6c4cee6298..87ad0df995 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/SpinBox.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/SpinBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/StackView.qml b/tests/auto/quickcontrols/customization/data/styles/simple/StackView.qml
index 35b668df49..0e314d4583 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/StackView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/StackView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/SwipeDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/simple/SwipeDelegate.qml
index 95ddab00cc..1edf89377a 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/SwipeDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/SwipeDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/SwipeView.qml b/tests/auto/quickcontrols/customization/data/styles/simple/SwipeView.qml
index 73ecba8586..4c0666cd85 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/SwipeView.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/SwipeView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Switch.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Switch.qml
index c8e42d3ada..0b9a9518d9 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Switch.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Switch.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/SwitchDelegate.qml b/tests/auto/quickcontrols/customization/data/styles/simple/SwitchDelegate.qml
index 00831df6c3..af563dfd54 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/SwitchDelegate.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/SwitchDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/TabBar.qml b/tests/auto/quickcontrols/customization/data/styles/simple/TabBar.qml
index 282a11aa52..ff5cdd63a1 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/TabBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/TabBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/TabButton.qml b/tests/auto/quickcontrols/customization/data/styles/simple/TabButton.qml
index 83de47fe54..2e5c464a3b 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/TabButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/TabButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/TextArea.qml b/tests/auto/quickcontrols/customization/data/styles/simple/TextArea.qml
index 6125d255be..3ff5ee56bd 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/TextArea.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/TextArea.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/TextField.qml b/tests/auto/quickcontrols/customization/data/styles/simple/TextField.qml
index a49bbed804..82981b53d2 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/TextField.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/TextField.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/ToolBar.qml b/tests/auto/quickcontrols/customization/data/styles/simple/ToolBar.qml
index 0e7c697722..be796e25f5 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/ToolBar.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/ToolBar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/ToolButton.qml b/tests/auto/quickcontrols/customization/data/styles/simple/ToolButton.qml
index e91a0d9335..74e65ba03e 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/ToolButton.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/ToolButton.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/ToolSeparator.qml b/tests/auto/quickcontrols/customization/data/styles/simple/ToolSeparator.qml
index c766f50754..979618f392 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/ToolSeparator.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/ToolSeparator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/ToolTip.qml b/tests/auto/quickcontrols/customization/data/styles/simple/ToolTip.qml
index 58bf428f72..7a9b3e708e 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/ToolTip.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/ToolTip.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/data/styles/simple/Tumbler.qml b/tests/auto/quickcontrols/customization/data/styles/simple/Tumbler.qml
index 3e7a2f486b..1b1755d63e 100644
--- a/tests/auto/quickcontrols/customization/data/styles/simple/Tumbler.qml
+++ b/tests/auto/quickcontrols/customization/data/styles/simple/Tumbler.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/customization/tst_customization.cpp b/tests/auto/quickcontrols/customization/tst_customization.cpp
index 8e5ac2a95a..d011f24d6a 100644
--- a/tests/auto/quickcontrols/customization/tst_customization.cpp
+++ b/tests/auto/quickcontrols/customization/tst_customization.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtCore/private/qhooks_p.h>
@@ -365,18 +365,18 @@ void tst_customization::override_data()
{
"macOS",
{
- "Button", "CheckBox", "ComboBox", "Dial", "Dialog", "DialogButtonBox", "Frame", "GroupBox",
- "ProgressBar", "RadioButton", "SelectionRectangle", "Slider",
- "SpinBox", "TextArea", "TextField", "TreeViewDelegate"
+ "Button", "CheckBox", "CheckDelegate", "ComboBox", "DelayButton", "Dial", "Frame",
+ "GroupBox", "ProgressBar", "RadioButton", "RadioDelegate", "SelectionRectangle",
+ "RangeSlider", "Slider", "SpinBox", "TextArea", "TextField", "TreeViewDelegate"
// TODO: ScrollView, ScrollBar
}
},
{
"Windows",
{
- "Button", "CheckBox", "ComboBox", "Frame", "GroupBox", "ProgressBar", "RadioButton",
- "SelectionRectangle", "Slider", "SpinBox", "TextArea", "TextField"
- // TODO: ScrollView
+ "Button", "CheckBox", "CheckDelegate", "ComboBox", "DelayButton", "Frame", "GroupBox",
+ "ProgressBar", "RadioButton", "RadioDelegate", "RangeSlider", "SelectionRectangle",
+ "ScrollBar", "Slider", "SpinBox", "Switch", "SwitchDelegate", "TextArea", "TextField"
}
}
};
diff --git a/tests/auto/quickcontrols/deferred/CMakeLists.txt b/tests/auto/quickcontrols/deferred/CMakeLists.txt
index 58ae1653e6..07df0b6d3d 100644
--- a/tests/auto/quickcontrols/deferred/CMakeLists.txt
+++ b/tests/auto/quickcontrols/deferred/CMakeLists.txt
@@ -1,3 +1,9 @@
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickdeferred LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
data/*)
diff --git a/tests/auto/quickcontrols/deferred/data/abortedIncubation.qml b/tests/auto/quickcontrols/deferred/data/abortedIncubation.qml
new file mode 100644
index 0000000000..6cd4c1c04a
--- /dev/null
+++ b/tests/auto/quickcontrols/deferred/data/abortedIncubation.qml
@@ -0,0 +1,171 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Controls.Basic
+
+ApplicationWindow {
+ id: appWindow
+
+ // QQuickDeferredPointer<QQuickItem> background;
+ background: Rectangle {
+ id: backgroundRect
+ color: "black"
+ }
+
+ // internal property handle
+ ColorDialog {
+ id: colorDialog
+ options: ColorDialog.DontUseNativeDialog
+ }
+
+ // internal property upButton
+ // internal property textField
+ FolderDialog {
+ id: folderDialog
+ options: FolderDialog.DontUseNativeDialog
+ }
+
+ // indicator property of AbstractButton
+ Button {
+ id: basicButton
+ indicator: Rectangle {
+ id: basicButtonIndicator
+ color: "pink"
+ }
+ }
+
+ Dial {
+ id: dial
+ // QQuickDeferredPointer<QQuickItem> handle;
+ handle: Item {
+ Rectangle {
+ id: dialRect
+ }
+ }
+ }
+
+ GroupBox {
+ id: groupBox
+ // QQuickDeferredPointer<QQuickItem> label;
+ label: Label {
+ id: groupBoxLabel
+ text: "yo"
+ }
+ }
+
+ Label {
+ id: label
+ text: "yo2"
+ background: Rectangle {
+ id: labelBackground
+ color: "green"
+ }
+ }
+
+ Menu {
+ id: menu
+
+ MenuItem {
+ id: menuItem
+ text: "New..."
+ arrow: Rectangle {
+ id: menuItemArrow
+ color: "pink"
+ }
+ }
+ }
+
+ ScrollBar {
+ id: scrollbar
+ }
+
+ SpinBox {
+ id: spinBox
+
+ up.indicator: Rectangle {
+ id: spinBoxUpIndicator
+ color: "pink"
+ }
+ down.indicator: Rectangle {
+ id: spinBoxDownIndicator
+ color: "blue"
+ }
+ }
+
+ Control {
+ id: genericControl
+ background: Rectangle {
+ id: genericControlBackground
+ color: "red"
+ }
+ contentItem: Canvas {
+ id: genericControlContentItem
+ }
+ }
+
+ ComboBox {
+ id: comboBox
+ model: ["foo", "bar"]
+
+ popup: Popup {
+ id: comboBoxPopup
+ contentItem: ListView {
+ ScrollBar.vertical: ScrollBar {}
+ }
+ }
+ indicator: Item {
+ id: emptyPopupItem
+ }
+ }
+
+ Slider {
+ id: slider
+ // QQuickDeferredPointer<QQuickItem> handle;
+ handle: Item {
+ Rectangle {
+ id: rect
+ }
+ }
+ }
+
+ RangeSlider {
+ id: rangeSlider
+ first.handle: Item {
+ Rectangle {
+ id: rangeSliderRect1
+ }
+ }
+ second.handle: Item {
+ Rectangle {
+ id: rangeSliderRect2
+ }
+ }
+ }
+
+ TextArea {
+ id: textArea
+ background: Rectangle {
+ id: textAreaBackground
+ color: "pink"
+ }
+ }
+
+ TextField {
+ id: textField
+ background: Rectangle {
+ id: textFieldBackground
+ color: "pink"
+ }
+ }
+
+ TabBar {
+ id: bar
+ TabButton {
+ text: qsTr("One")
+ }
+ TabButton {
+ text: qsTr("Two")
+ }
+ }
+}
+
diff --git a/tests/auto/quickcontrols/deferred/tst_qquickdeferred.cpp b/tests/auto/quickcontrols/deferred/tst_qquickdeferred.cpp
index 4d3eadbea4..1c50531d57 100644
--- a/tests/auto/quickcontrols/deferred/tst_qquickdeferred.cpp
+++ b/tests/auto/quickcontrols/deferred/tst_qquickdeferred.cpp
@@ -1,11 +1,12 @@
// Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtTest/qtest.h>
#include <QQmlEngine>
#include <QtQuick/qquickitem.h>
#include <QtQuickTemplates2/private/qquickdeferredexecute_p_p.h>
+#include <QQmlIncubator>
class DeferredPropertyTester : public QObject
{
@@ -48,6 +49,7 @@ public:
tst_qquickdeferred() : QQmlDataTest(QT_QMLTEST_DATADIR) {}
private slots:
void noSpuriousBinding();
+ void abortedIncubation();
};
@@ -63,6 +65,25 @@ void tst_qquickdeferred::noSpuriousBinding() {
root->setProperty("toggle", false);
}
+// QTBUG-116828
+// This test checks the case where we cancel incubation of a componet with a deferred property
+// Components that have deferred properties should also provide an itemDestoryed method that
+// that resets the deferred property to null to prevent issues with dangling pointers.
+void tst_qquickdeferred::abortedIncubation()
+{
+ QQmlEngine engine;
+ QQmlIncubationController controller;
+ engine.setIncubationController(&controller);
+
+ {
+ QQmlIncubator incubator;
+ QQmlComponent componet(&engine, testFileUrl("abortedIncubation.qml"));
+ componet.create(incubator);
+ controller.incubateFor(1);
+ incubator.clear(); // abort incubation (and dont crash)
+ }
+}
+
QTEST_MAIN(tst_qquickdeferred)
#include "tst_qquickdeferred.moc"
diff --git a/tests/auto/quickcontrols/designer/CMakeLists.txt b/tests/auto/quickcontrols/designer/CMakeLists.txt
index 9ad0512f80..5157ad562a 100644
--- a/tests/auto/quickcontrols/designer/CMakeLists.txt
+++ b/tests/auto/quickcontrols/designer/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_designer LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/designer/tst_designer.cpp b/tests/auto/quickcontrols/designer/tst_designer.cpp
index 760f739a02..5b3c7690e2 100644
--- a/tests/auto/quickcontrols/designer/tst_designer.cpp
+++ b/tests/auto/quickcontrols/designer/tst_designer.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest>
#include <QtQuick>
diff --git a/tests/auto/quickcontrols/focus/CMakeLists.txt b/tests/auto/quickcontrols/focus/CMakeLists.txt
index 87200bf05c..ca22f82924 100644
--- a/tests/auto/quickcontrols/focus/CMakeLists.txt
+++ b/tests/auto/quickcontrols/focus/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_focus LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/focus/data/activeFocusOnTab.qml b/tests/auto/quickcontrols/focus/data/activeFocusOnTab.qml
index b158c673f0..856d026750 100644
--- a/tests/auto/quickcontrols/focus/data/activeFocusOnTab.qml
+++ b/tests/auto/quickcontrols/focus/data/activeFocusOnTab.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/focus/data/keyNavigation.qml b/tests/auto/quickcontrols/focus/data/keyNavigation.qml
index f1a10a2569..d617b78899 100644
--- a/tests/auto/quickcontrols/focus/data/keyNavigation.qml
+++ b/tests/auto/quickcontrols/focus/data/keyNavigation.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/focus/data/visualFocus.qml b/tests/auto/quickcontrols/focus/data/visualFocus.qml
index ec35905e27..64c4ea65bc 100644
--- a/tests/auto/quickcontrols/focus/data/visualFocus.qml
+++ b/tests/auto/quickcontrols/focus/data/visualFocus.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/focus/tst_focus.cpp b/tests/auto/quickcontrols/focus/tst_focus.cpp
index ca70146885..9f68e3b61d 100644
--- a/tests/auto/quickcontrols/focus/tst_focus.cpp
+++ b/tests/auto/quickcontrols/focus/tst_focus.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtTest/QSignalSpy>
@@ -15,6 +15,7 @@
#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
#include <QtQuickTemplates2/private/qquickcontrol_p.h>
+#include <QtQuickTemplates2/private/qquicktextfield_p.h>
#include <QtQuickControls2/qquickstyle.h>
#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
@@ -29,6 +30,7 @@ public:
tst_focus();
private slots:
+ void init() override;
void initTestCase() override;
void navigation_data();
@@ -50,8 +52,15 @@ tst_focus::tst_focus()
{
}
+void tst_focus::init()
+{
+ QTest::failOnWarning(QRegularExpression(".?"));
+}
+
void tst_focus::initTestCase()
{
+ SKIP_IF_NO_WINDOW_ACTIVATION
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
QQuickStyle::setStyle("Basic");
QQmlDataTest::initTestCase();
}
@@ -198,6 +207,7 @@ void tst_focus::policy()
control->setFocus(false);
QVERIFY(!control->hasActiveFocus());
+#if QT_CONFIG(wheelevent)
// Qt::WheelFocus
QWheelEvent wheelEvent(QPointF(control->width() / 2, control->height() / 2), QPointF(),
QPoint(), QPoint(0, 10), Qt::NoButton, Qt::NoModifier,
@@ -212,6 +222,7 @@ void tst_focus::policy()
QGuiApplication::sendEvent(control, &wheelEvent);
QVERIFY(control->hasActiveFocus());
QVERIFY(!control->hasVisualFocus());
+#endif
}
void tst_focus::reason()
@@ -234,7 +245,7 @@ void tst_focus::reason()
QQuickControl *customText = view.findChild<QQuickControl *>("customText");
QQuickControl *customItem = view.findChild<QQuickControl *>("customItem");
// not a QQuickControl subclass
- QQuickItem *textfield = view.findChild<QQuickItem *>("textfield");
+ QQuickTextField *textfield = view.findChild<QQuickTextField *>("textfield");
// helper for clicking into a control
const auto itemCenter = [](const QQuickItem *item) -> QPoint {
@@ -263,21 +274,35 @@ void tst_focus::reason()
}
QCOMPARE(control->focusReason(), Qt::ActiveWindowFocusReason);
+ QSignalSpy controlSpy(control, SIGNAL(focusReasonChanged()));
+ QSignalSpy textfieldSpy(textfield, SIGNAL(focusReasonChanged()));
+ QSignalSpy customItemSpy(customItem, SIGNAL(focusReasonChanged()));
+ int controlSpyCount = 0, textfieldSpyCount = 0, customItemSpyCount = 0;
+ QVERIFY(!controlSpy.count());
+ QVERIFY(!textfieldSpy.count());
+ QVERIFY(!customItemSpy.count());
+
// test setter/getter
control->setFocus(false, Qt::MouseFocusReason);
QCOMPARE(control->focusReason(), Qt::MouseFocusReason);
+ QCOMPARE(controlSpy.count(), ++controlSpyCount);
control->setFocus(true, Qt::TabFocusReason);
QCOMPARE(control->focusReason(), Qt::TabFocusReason);
+ QCOMPARE(controlSpy.count(), ++controlSpyCount);
control->setFocus(false, Qt::BacktabFocusReason);
QCOMPARE(control->focusReason(), Qt::BacktabFocusReason);
+ QCOMPARE(controlSpy.count(), ++controlSpyCount);
control->forceActiveFocus(Qt::ShortcutFocusReason);
QCOMPARE(control->focusReason(), Qt::ShortcutFocusReason);
+ QCOMPARE(controlSpy.count(), ++controlSpyCount);
control->setFocusReason(Qt::PopupFocusReason);
QCOMPARE(control->focusReason(), Qt::PopupFocusReason);
+ QCOMPARE(controlSpy.count(), ++controlSpyCount);
// programmatic focus changes
combobox->setFocus(true, Qt::OtherFocusReason);
QCOMPARE(control->focusReason(), Qt::OtherFocusReason);
+ QCOMPARE(controlSpy.count(), ++controlSpyCount);
QVERIFY(combobox->hasFocus());
QVERIFY(combobox->hasActiveFocus());
@@ -314,27 +339,35 @@ void tst_focus::reason()
QVERIFY(customItem->hasActiveFocus());
QCOMPARE(customText->focusReason(), Qt::TabFocusReason);
QCOMPARE(customItem->focusReason(), Qt::TabFocusReason);
+ QCOMPARE(customItemSpy.count(),++customItemSpyCount);
customItem->setFocusReason(Qt::NoFocusReason);
+ QCOMPARE(customItemSpy.count(),++customItemSpyCount);
QTest::keyClick(&view, Qt::Key_Tab);
QVERIFY(textfield->hasFocus());
QVERIFY(textfield->hasActiveFocus());
QCOMPARE(qApp->focusObject(), textfield);
QCOMPARE(customItem->focusReason(), Qt::TabFocusReason);
+ QCOMPARE(customItemSpy.count(),++customItemSpyCount);
+ QCOMPARE(textfieldSpy.count(), ++textfieldSpyCount);
QTest::keyClick(&view, Qt::Key_Tab);
QVERIFY(control->hasFocus());
QVERIFY(control->hasActiveFocus());
QCOMPARE(control->focusReason(), Qt::TabFocusReason);
+ QCOMPARE(controlSpy.count(), ++controlSpyCount);
// backtab -> BacktabFocusReason
QTest::keyClick(&view, Qt::Key_Tab, Qt::ShiftModifier);
QVERIFY(textfield->hasFocus());
QCOMPARE(control->focusReason(), Qt::BacktabFocusReason);
+ QCOMPARE(controlSpy.count(), ++controlSpyCount);
+ QCOMPARE(textfieldSpy.count(), ++textfieldSpyCount);
QTest::keyClick(&view, Qt::Key_Tab, Qt::ShiftModifier);
QVERIFY(customItem->hasFocus());
QCOMPARE(customItem->focusReason(), Qt::BacktabFocusReason);
+ QCOMPARE(customItemSpy.count(),++customItemSpyCount);
QTest::keyClick(&view, Qt::Key_Tab, Qt::ShiftModifier);
QVERIFY(customText->hasFocus());
@@ -389,13 +422,18 @@ void tst_focus::reason()
QVERIFY(customItem->hasActiveFocus());
QCOMPARE(customText->focusReason(), Qt::MouseFocusReason);
QCOMPARE(customItem->focusReason(), Qt::MouseFocusReason);
+ QCOMPARE(customItemSpy.count(),++customItemSpyCount);
customItem->setFocusReason(Qt::NoFocusReason);
+ QCOMPARE(customItemSpy.count(),++customItemSpyCount);
QTest::mouseClick(&view, Qt::LeftButton, {}, itemCenter(textfield));
QCOMPARE(customItem->focusReason(), Qt::MouseFocusReason);
+ QCOMPARE(customItemSpy.count(),++customItemSpyCount);
customItem->setFocusReason(Qt::NoFocusReason);
+ QCOMPARE(customItemSpy.count(),++customItemSpyCount);
customText->setFocusReason(Qt::NoFocusReason);
+#if QT_CONFIG(wheelevent)
// Wheel focus -> MouseFocusReason
QWheelEvent wheelEvent(QPointF(customItem->width() / 2, customItem->height() / 2), QPointF(),
QPoint(), QPoint(0, 10), Qt::NoButton, Qt::NoModifier,
@@ -403,12 +441,15 @@ void tst_focus::reason()
QGuiApplication::sendEvent(customItem, &wheelEvent);
QVERIFY(customItem->hasActiveFocus());
QCOMPARE(customItem->focusReason(), Qt::MouseFocusReason);
+ QCOMPARE(customItemSpy.count(),++customItemSpyCount);
// Popup opens -> PopupFocusReason
QTest::mouseClick(&view, Qt::RightButton, {}, itemCenter(control));
QTRY_VERIFY(!customItem->hasActiveFocus());
QCOMPARE(customItem->focusReason(), Qt::PopupFocusReason);
+ QCOMPARE(customItemSpy.count(),++customItemSpyCount);
QTest::keyClick(&view, Qt::Key_Escape); // close the popup
+#endif
}
void tst_focus::visualFocus()
@@ -502,6 +543,7 @@ void tst_focus::scope()
QVERIFY(child->hasActiveFocus());
QVERIFY(control->hasActiveFocus());
+#if QT_CONFIG(wheelevent)
// Qt::WheelFocus
QWheelEvent wheelEvent(QPointF(control->width() / 2, control->height() / 2), QPointF(),
QPoint(), QPoint(0, 10), Qt::NoButton, Qt::NoModifier,
@@ -509,6 +551,7 @@ void tst_focus::scope()
QGuiApplication::sendEvent(control, &wheelEvent);
QVERIFY(!child->hasActiveFocus());
QVERIFY(control->hasActiveFocus());
+#endif
}
QTEST_MAIN(tst_focus)
diff --git a/tests/auto/quickcontrols/font/CMakeLists.txt b/tests/auto/quickcontrols/font/CMakeLists.txt
index 9eaee341d0..150d77a358 100644
--- a/tests/auto/quickcontrols/font/CMakeLists.txt
+++ b/tests/auto/quickcontrols/font/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_font LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/font/data/font-appwindow-custom.qml b/tests/auto/quickcontrols/font/data/font-appwindow-custom.qml
index fa621ae6a0..7cd3e4d978 100644
--- a/tests/auto/quickcontrols/font/data/font-appwindow-custom.qml
+++ b/tests/auto/quickcontrols/font/data/font-appwindow-custom.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/font-appwindow-default.qml b/tests/auto/quickcontrols/font/data/font-appwindow-default.qml
index f9c767b876..62809ea03b 100644
--- a/tests/auto/quickcontrols/font/data/font-appwindow-default.qml
+++ b/tests/auto/quickcontrols/font/data/font-appwindow-default.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/font-control-custom.qml b/tests/auto/quickcontrols/font/data/font-control-custom.qml
index c7ee583d04..8b8b138939 100644
--- a/tests/auto/quickcontrols/font/data/font-control-custom.qml
+++ b/tests/auto/quickcontrols/font/data/font-control-custom.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/font-control-default.qml b/tests/auto/quickcontrols/font/data/font-control-default.qml
index 7cd58e12b3..48320fd3a8 100644
--- a/tests/auto/quickcontrols/font/data/font-control-default.qml
+++ b/tests/auto/quickcontrols/font/data/font-control-default.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/font-popup-custom.qml b/tests/auto/quickcontrols/font/data/font-popup-custom.qml
index fcf942e3a5..dcf1010892 100644
--- a/tests/auto/quickcontrols/font/data/font-popup-custom.qml
+++ b/tests/auto/quickcontrols/font/data/font-popup-custom.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/font-popup-default.qml b/tests/auto/quickcontrols/font/data/font-popup-default.qml
index b9db73c9fb..a6bc8d11db 100644
--- a/tests/auto/quickcontrols/font/data/font-popup-default.qml
+++ b/tests/auto/quickcontrols/font/data/font-popup-default.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/inheritance-childcontrol.qml b/tests/auto/quickcontrols/font/data/inheritance-childcontrol.qml
index f476020517..6b625ca1ca 100644
--- a/tests/auto/quickcontrols/font/data/inheritance-childcontrol.qml
+++ b/tests/auto/quickcontrols/font/data/inheritance-childcontrol.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/inheritance-childpopup.qml b/tests/auto/quickcontrols/font/data/inheritance-childpopup.qml
index 8b7a033bd7..d668c626ac 100644
--- a/tests/auto/quickcontrols/font/data/inheritance-childpopup.qml
+++ b/tests/auto/quickcontrols/font/data/inheritance-childpopup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/inheritance-control.qml b/tests/auto/quickcontrols/font/data/inheritance-control.qml
index 2cd5c125f4..fc67bd8735 100644
--- a/tests/auto/quickcontrols/font/data/inheritance-control.qml
+++ b/tests/auto/quickcontrols/font/data/inheritance-control.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/inheritance-dynamicchildcontrol.qml b/tests/auto/quickcontrols/font/data/inheritance-dynamicchildcontrol.qml
index 18305058bc..c4436bdd91 100644
--- a/tests/auto/quickcontrols/font/data/inheritance-dynamicchildcontrol.qml
+++ b/tests/auto/quickcontrols/font/data/inheritance-dynamicchildcontrol.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/inheritance-dynamicchildpopup.qml b/tests/auto/quickcontrols/font/data/inheritance-dynamicchildpopup.qml
index 6b16f1a46b..30dac26408 100644
--- a/tests/auto/quickcontrols/font/data/inheritance-dynamicchildpopup.qml
+++ b/tests/auto/quickcontrols/font/data/inheritance-dynamicchildpopup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/inheritance-dynamiccontrol.qml b/tests/auto/quickcontrols/font/data/inheritance-dynamiccontrol.qml
index df0e13bf2c..bf8cfdc3c8 100644
--- a/tests/auto/quickcontrols/font/data/inheritance-dynamiccontrol.qml
+++ b/tests/auto/quickcontrols/font/data/inheritance-dynamiccontrol.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/inheritance-dynamicpopup.qml b/tests/auto/quickcontrols/font/data/inheritance-dynamicpopup.qml
index 76b7d7cbda..b0454dc38c 100644
--- a/tests/auto/quickcontrols/font/data/inheritance-dynamicpopup.qml
+++ b/tests/auto/quickcontrols/font/data/inheritance-dynamicpopup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/inheritance-popup.qml b/tests/auto/quickcontrols/font/data/inheritance-popup.qml
index a5010f0f11..98698304a7 100644
--- a/tests/auto/quickcontrols/font/data/inheritance-popup.qml
+++ b/tests/auto/quickcontrols/font/data/inheritance-popup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/listview.qml b/tests/auto/quickcontrols/font/data/listview.qml
index aa07a337cf..1b59cb16a2 100644
--- a/tests/auto/quickcontrols/font/data/listview.qml
+++ b/tests/auto/quickcontrols/font/data/listview.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/data/resolve.qml b/tests/auto/quickcontrols/font/data/resolve.qml
index 00e5c767bb..4e82309dea 100644
--- a/tests/auto/quickcontrols/font/data/resolve.qml
+++ b/tests/auto/quickcontrols/font/data/resolve.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 yeshanshan <yeshanshan@uniontech.com>.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/font/tst_font.cpp b/tests/auto/quickcontrols/font/tst_font.cpp
index 26caf0c476..ec8e927693 100644
--- a/tests/auto/quickcontrols/font/tst_font.cpp
+++ b/tests/auto/quickcontrols/font/tst_font.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
@@ -38,6 +38,9 @@ private slots:
void listView();
void resolve();
+
+ void variableAxes_data();
+ void variableAxes();
};
static QFont testFont()
@@ -110,7 +113,7 @@ void tst_font::font()
QFETCH(QString, testFile);
QFETCH(QFont, expectedFont);
- if (QSysInfo::productType().compare(QLatin1String("osx"), Qt::CaseInsensitive) == 0
+ if (QSysInfo::productType().compare(QLatin1String("macos"), Qt::CaseInsensitive) == 0
&& qgetenv("QTEST_ENVIRONMENT").split(' ').contains("CI")) {
QSKIP("This test crashes on macOS: QTBUG-70063");
}
@@ -371,6 +374,39 @@ void tst_font::resolve()
QVERIFY(control2ChildControlFont != control4Font);
}
+void tst_font::variableAxes_data()
+{
+ QTest::addColumn<QFont::Tag>("axesName");
+ QTest::addColumn<float>("axesValue");
+
+ QTest::addRow("wght") << QFont::Tag("wght") << 200.0f;
+}
+
+void tst_font::variableAxes()
+{
+ QFETCH(QFont::Tag, axesName);
+ QFETCH(float, axesValue);
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(QString(R"QML(
+ import QtQuick
+ import QtQuick.Controls
+
+ Text {
+ font.variableAxes: {
+ "%1": %2
+ }
+ }
+ )QML").arg(axesName.toString()).arg(axesValue).toUtf8(), QUrl());
+
+ QScopedPointer<QObject> control(component.create());
+ QVERIFY2(!control.isNull(), qPrintable(component.errorString()));
+
+ const QFont font = control->property("font").value<QFont>();
+ QCOMPARE(font.variableAxisValue(axesName), axesValue);
+}
+
QTEST_MAIN(tst_font)
#include "tst_font.moc"
diff --git a/tests/auto/quickcontrols/palette/CMakeLists.txt b/tests/auto/quickcontrols/palette/CMakeLists.txt
index fd4ee2d680..26c143d1c4 100644
--- a/tests/auto/quickcontrols/palette/CMakeLists.txt
+++ b/tests/auto/quickcontrols/palette/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_palette LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/palette/data/bindings.qml b/tests/auto/quickcontrols/palette/data/bindings.qml
index a584007e54..44f31ccf7d 100644
--- a/tests/auto/quickcontrols/palette/data/bindings.qml
+++ b/tests/auto/quickcontrols/palette/data/bindings.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/palette/data/childPopupInheritance.qml b/tests/auto/quickcontrols/palette/data/childPopupInheritance.qml
new file mode 100644
index 0000000000..35859b5798
--- /dev/null
+++ b/tests/auto/quickcontrols/palette/data/childPopupInheritance.qml
@@ -0,0 +1,40 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ id: window
+
+ Popup {
+ id: parentPopup
+ objectName: "parentPopup"
+ palette.windowText: "#ffdead"
+
+ Label {
+ text: "parentPopupLabel"
+ objectName: text
+ }
+
+ Popup {
+ id: childPopup
+ objectName: "childPopup"
+
+ Label {
+ text: "childPopupLabel"
+ objectName: text
+ }
+
+ Popup {
+ id: grandchildPopup
+ objectName: "grandchildPopup"
+
+ Label {
+ text: "grandchildPopupLabel"
+ objectName: text
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/palette/data/comboBoxPopupWithApplicationWindow.qml b/tests/auto/quickcontrols/palette/data/comboBoxPopupWithApplicationWindow.qml
new file mode 100644
index 0000000000..436d3cdad6
--- /dev/null
+++ b/tests/auto/quickcontrols/palette/data/comboBoxPopupWithApplicationWindow.qml
@@ -0,0 +1,32 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias topLevelComboBox: topLevelComboBox
+ property alias popup: popup
+ property alias comboBoxInPopup: comboBoxInPopup
+
+ ComboBox {
+ id: topLevelComboBox
+ model: ["ONE", "TWO", "THREE"]
+ }
+
+ Popup {
+ id: popup
+ width: 200
+ height: 200
+ visible: true
+ palette.window: "red"
+
+ ComboBox {
+ id: comboBoxInPopup
+ model: ["ONE", "TWO", "THREE"]
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/palette/data/comboBoxPopupWithThemeDefault.qml b/tests/auto/quickcontrols/palette/data/comboBoxPopupWithThemeDefault.qml
new file mode 100644
index 0000000000..592793fa3f
--- /dev/null
+++ b/tests/auto/quickcontrols/palette/data/comboBoxPopupWithThemeDefault.qml
@@ -0,0 +1,17 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias comboBox: comboBox
+
+ ComboBox {
+ id: comboBox
+ model: 1
+ }
+}
diff --git a/tests/auto/quickcontrols/palette/data/comboBoxPopupWithWindow.qml b/tests/auto/quickcontrols/palette/data/comboBoxPopupWithWindow.qml
new file mode 100644
index 0000000000..d806f30d01
--- /dev/null
+++ b/tests/auto/quickcontrols/palette/data/comboBoxPopupWithWindow.qml
@@ -0,0 +1,33 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Window
+import QtQuick.Controls
+
+Window {
+ width: 400
+ height: 400
+
+ property alias topLevelComboBox: topLevelComboBox
+ property alias popup: popup
+ property alias comboBoxInPopup: comboBoxInPopup
+
+ ComboBox {
+ id: topLevelComboBox
+ model: ["ONE", "TWO", "THREE"]
+ }
+
+ Popup {
+ id: popup
+ width: 200
+ height: 200
+ visible: true
+ palette.window: "red"
+
+ ComboBox {
+ id: comboBoxInPopup
+ model: ["ONE", "TWO", "THREE"]
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/palette/data/inheritance-childcontrol.qml b/tests/auto/quickcontrols/palette/data/inheritance-childcontrol.qml
index f476020517..6b625ca1ca 100644
--- a/tests/auto/quickcontrols/palette/data/inheritance-childcontrol.qml
+++ b/tests/auto/quickcontrols/palette/data/inheritance-childcontrol.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/palette/data/inheritance-childpopup.qml b/tests/auto/quickcontrols/palette/data/inheritance-childpopup.qml
index 8b7a033bd7..d668c626ac 100644
--- a/tests/auto/quickcontrols/palette/data/inheritance-childpopup.qml
+++ b/tests/auto/quickcontrols/palette/data/inheritance-childpopup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/palette/data/inheritance-control.qml b/tests/auto/quickcontrols/palette/data/inheritance-control.qml
index 2cd5c125f4..fc67bd8735 100644
--- a/tests/auto/quickcontrols/palette/data/inheritance-control.qml
+++ b/tests/auto/quickcontrols/palette/data/inheritance-control.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/palette/data/inheritance-dynamicchildcontrol.qml b/tests/auto/quickcontrols/palette/data/inheritance-dynamicchildcontrol.qml
index 18305058bc..c4436bdd91 100644
--- a/tests/auto/quickcontrols/palette/data/inheritance-dynamicchildcontrol.qml
+++ b/tests/auto/quickcontrols/palette/data/inheritance-dynamicchildcontrol.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/palette/data/inheritance-dynamicchildpopup.qml b/tests/auto/quickcontrols/palette/data/inheritance-dynamicchildpopup.qml
index 6b16f1a46b..30dac26408 100644
--- a/tests/auto/quickcontrols/palette/data/inheritance-dynamicchildpopup.qml
+++ b/tests/auto/quickcontrols/palette/data/inheritance-dynamicchildpopup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/palette/data/inheritance-dynamiccontrol.qml b/tests/auto/quickcontrols/palette/data/inheritance-dynamiccontrol.qml
index df0e13bf2c..bf8cfdc3c8 100644
--- a/tests/auto/quickcontrols/palette/data/inheritance-dynamiccontrol.qml
+++ b/tests/auto/quickcontrols/palette/data/inheritance-dynamiccontrol.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/palette/data/inheritance-dynamicpopup.qml b/tests/auto/quickcontrols/palette/data/inheritance-dynamicpopup.qml
index 76b7d7cbda..b0454dc38c 100644
--- a/tests/auto/quickcontrols/palette/data/inheritance-dynamicpopup.qml
+++ b/tests/auto/quickcontrols/palette/data/inheritance-dynamicpopup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/palette/data/inheritance-popup.qml b/tests/auto/quickcontrols/palette/data/inheritance-popup.qml
index a5010f0f11..98698304a7 100644
--- a/tests/auto/quickcontrols/palette/data/inheritance-popup.qml
+++ b/tests/auto/quickcontrols/palette/data/inheritance-popup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/palette/data/listview.qml b/tests/auto/quickcontrols/palette/data/listview.qml
index 92816fde19..8555b0b8ba 100644
--- a/tests/auto/quickcontrols/palette/data/listview.qml
+++ b/tests/auto/quickcontrols/palette/data/listview.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/palette/data/palette-appwindow-bindingpalette.qml b/tests/auto/quickcontrols/palette/data/palette-appwindow-bindingpalette.qml
new file mode 100644
index 0000000000..ce7ca82700
--- /dev/null
+++ b/tests/auto/quickcontrols/palette/data/palette-appwindow-bindingpalette.qml
@@ -0,0 +1,15 @@
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ id: window
+ width: 500
+ height: 300
+ palette: customPalette
+
+ property alias cstmPalette: customPalette
+
+ Palette { id: customPalette }
+
+ Component.onCompleted: { window.palette.buttonText = "white" }
+}
diff --git a/tests/auto/quickcontrols/palette/data/palette-appwindow-custom.qml b/tests/auto/quickcontrols/palette/data/palette-appwindow-custom.qml
index 22876b90fa..752385ac02 100644
--- a/tests/auto/quickcontrols/palette/data/palette-appwindow-custom.qml
+++ b/tests/auto/quickcontrols/palette/data/palette-appwindow-custom.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
@@ -25,4 +25,5 @@ ApplicationWindow {
palette.window: "plum"
palette.windowText: "salmon"
palette.placeholderText: "magenta"
+ palette.accent: "darkkhaki"
}
diff --git a/tests/auto/quickcontrols/palette/data/palette-appwindow-default.qml b/tests/auto/quickcontrols/palette/data/palette-appwindow-default.qml
index f9c767b876..62809ea03b 100644
--- a/tests/auto/quickcontrols/palette/data/palette-appwindow-default.qml
+++ b/tests/auto/quickcontrols/palette/data/palette-appwindow-default.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/palette/data/palette-control-custom.qml b/tests/auto/quickcontrols/palette/data/palette-control-custom.qml
index 4c4206cdfd..ae3eda25f7 100644
--- a/tests/auto/quickcontrols/palette/data/palette-control-custom.qml
+++ b/tests/auto/quickcontrols/palette/data/palette-control-custom.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
@@ -25,4 +25,5 @@ Control {
palette.window: "plum"
palette.windowText: "salmon"
palette.placeholderText: "magenta"
+ palette.accent: "darkkhaki"
}
diff --git a/tests/auto/quickcontrols/palette/data/palette-control-default.qml b/tests/auto/quickcontrols/palette/data/palette-control-default.qml
index 7cd58e12b3..48320fd3a8 100644
--- a/tests/auto/quickcontrols/palette/data/palette-control-default.qml
+++ b/tests/auto/quickcontrols/palette/data/palette-control-default.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/palette/data/palette-popup-custom.qml b/tests/auto/quickcontrols/palette/data/palette-popup-custom.qml
index c534d30156..a254fbcb99 100644
--- a/tests/auto/quickcontrols/palette/data/palette-popup-custom.qml
+++ b/tests/auto/quickcontrols/palette/data/palette-popup-custom.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
@@ -25,4 +25,5 @@ Popup {
palette.window: "plum"
palette.windowText: "salmon"
palette.placeholderText: "magenta"
+ palette.accent: "darkkhaki"
}
diff --git a/tests/auto/quickcontrols/palette/data/palette-popup-default.qml b/tests/auto/quickcontrols/palette/data/palette-popup-default.qml
index b9db73c9fb..a6bc8d11db 100644
--- a/tests/auto/quickcontrols/palette/data/palette-popup-default.qml
+++ b/tests/auto/quickcontrols/palette/data/palette-popup-default.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/palette/data/reset-color.qml b/tests/auto/quickcontrols/palette/data/reset-color.qml
new file mode 100644
index 0000000000..4b62211cdb
--- /dev/null
+++ b/tests/auto/quickcontrols/palette/data/reset-color.qml
@@ -0,0 +1,52 @@
+// Copyright (C) 2022 zccrs <zccrs@live.com>, JiDe Zhang <zhangjide@uniontech.com>.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ id: window
+ property alias control: control
+ property alias item1Palette: item1.palette
+ property alias item2Palette: item2.palette
+
+ palette {
+ disabled {
+ windowText: "blue"
+ }
+ }
+
+ Item {
+ id: item1
+
+ palette.disabled {
+ text: "yellow"
+ }
+
+ Item {
+ id: item2
+
+ palette.disabled {
+ window: "yellow"
+ }
+ }
+ }
+
+ Control {
+ id: control
+ objectName: "Control"
+
+ palette {
+ window: "red"
+ disabled: item2.palette.disabled
+ }
+ }
+
+ function resetColor() {
+ control.palette.window = undefined
+ }
+
+ function resetGroup() {
+ control.palette.disabled = undefined
+ }
+}
diff --git a/tests/auto/quickcontrols/palette/data/resolve.qml b/tests/auto/quickcontrols/palette/data/resolve.qml
index 78cf091848..72ee0a9a4a 100644
--- a/tests/auto/quickcontrols/palette/data/resolve.qml
+++ b/tests/auto/quickcontrols/palette/data/resolve.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 zccrs <zccrs@live.com>, JiDe Zhang <zhangjide@uniontech.com>.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/palette/data/set-palette.qml b/tests/auto/quickcontrols/palette/data/set-palette.qml
index b987a7d6b1..d263e6edb0 100644
--- a/tests/auto/quickcontrols/palette/data/set-palette.qml
+++ b/tests/auto/quickcontrols/palette/data/set-palette.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/palette/data/toolTipPaletteUpdate.qml b/tests/auto/quickcontrols/palette/data/toolTipPaletteUpdate.qml
new file mode 100644
index 0000000000..3968c54cd0
--- /dev/null
+++ b/tests/auto/quickcontrols/palette/data/toolTipPaletteUpdate.qml
@@ -0,0 +1,19 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ id: window
+
+ palette { toolTipBase: "white"; toolTipText: "black"}
+
+ Button {
+ objectName: "button"
+ text: qsTr("Button with Tooltip")
+
+ ToolTip.visible: false
+ ToolTip.text: qsTr("This is a tool tip.")
+ }
+}
diff --git a/tests/auto/quickcontrols/palette/qtquickcontrols2.conf b/tests/auto/quickcontrols/palette/qtquickcontrols2.conf
index c5de6b36dd..97b122c566 100644
--- a/tests/auto/quickcontrols/palette/qtquickcontrols2.conf
+++ b/tests/auto/quickcontrols/palette/qtquickcontrols2.conf
@@ -1,5 +1,3 @@
[Basic]
Palette\Base=#efefef
-
-[Basic\Palette]
-Text=#101010
+Palette\Text=#101010
diff --git a/tests/auto/quickcontrols/palette/tst_palette.cpp b/tests/auto/quickcontrols/palette/tst_palette.cpp
index e3a53f0c21..11a30e5a4b 100644
--- a/tests/auto/quickcontrols/palette/tst_palette.cpp
+++ b/tests/auto/quickcontrols/palette/tst_palette.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtGui/qpalette.h>
@@ -7,23 +7,23 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtQuickTestUtils/private/visualtestutils_p.h>
+#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
+#include <QtQuickTemplates2/private/qquickcombobox_p.h>
#include <QtQuickTemplates2/private/qquickcontrol_p.h>
#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
#include <QtQuickTemplates2/private/qquickpopup_p.h>
#include <QtQuickTemplates2/private/qquickpopup_p_p.h>
#include <QtQuickTemplates2/private/qquicktheme_p_p.h>
#include <QtQuickTemplates2/private/qquickbutton_p.h>
+#include <QtQuickTemplates2/private/qquicktooltip_p.h>
#include <QtQuickControls2/qquickstyle.h>
+#include <QSignalSpy>
-//using namespace QQuickVisualTestUtils;
-
-// Need a more descriptive failure message: QTBUG-87039
-#define COMPARE_PALETTES(actualPalette, expectedPalette) \
- QVERIFY2(actualPalette == expectedPalette, \
- qPrintable(QString::fromLatin1("\n Actual: %1\n Expected: %2") \
- .arg(QDebug::toString(actualPalette)).arg(QDebug::toString(expectedPalette))));
+using namespace QQuickVisualTestUtils;
+using namespace QQuickControlsTestUtils;
class tst_palette : public QQmlDataTest
{
@@ -40,6 +40,7 @@ private slots:
void inheritance_data();
void inheritance();
+ void childPopupInheritance();
void defaultPalette_data();
void defaultPalette();
@@ -52,6 +53,16 @@ private slots:
void updateBindings();
void resolve();
+
+ void resetColor();
+ void updateBindingPalette();
+
+ void comboBoxPopup_data();
+ void comboBoxPopup();
+ void comboBoxPopupWithThemeDefault_data();
+ void comboBoxPopupWithThemeDefault();
+
+ void toolTipPaletteUpdate();
};
tst_palette::tst_palette()
@@ -106,6 +117,7 @@ void tst_palette::palette_data()
customPalette.setColor(QPalette::Window, QColor("plum"));
customPalette.setColor(QPalette::WindowText, QColor("salmon"));
customPalette.setColor(QPalette::PlaceholderText, QColor("magenta"));
+ customPalette.setColor(QPalette::Accent, QColor("darkkhaki"));
QTest::newRow("Control:custom") << "palette-control-custom.qml" << customPalette;
QTest::newRow("AppWindow:custom") << "palette-appwindow-custom.qml" << customPalette;
@@ -127,7 +139,7 @@ void tst_palette::palette()
QVariant var = object->property("palette");
QVERIFY(var.isValid());
- COMPARE_PALETTES(var.value<QQuickPalette*>()->toQPalette(), expectedPalette);
+ QCOMPARE(var.value<QQuickPalette*>()->toQPalette(), expectedPalette);
}
void tst_palette::inheritance_data()
@@ -203,6 +215,40 @@ void tst_palette::inheritance()
QCOMPARE(grandChildPalette->window(), windowPalette->window());
}
+// The child popups in inheritance() don't test actual nested child popups,
+// only popups that are children of items and the items within those popups.
+// We need to specifically test this to prevent QTBUG-115707 from happening again.
+void tst_palette::childPopupInheritance()
+{
+ QQuickControlsApplicationHelper helper(this, QLatin1String("childPopupInheritance.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ const auto *windowPrivate = QQuickWindowPrivate::get(helper.window);
+ const auto windowsWindowTextColor = windowPrivate->palette()->toQPalette().color(QPalette::WindowText);
+
+ // parentPopup sets windowText explicitly, so its label should use that color.
+ auto *parentPopup = helper.appWindow->findChild<QQuickPopup *>("parentPopup");
+ QVERIFY(parentPopup);
+ parentPopup->open();
+ QTRY_VERIFY(parentPopup->isOpened());
+ auto *parentPopupLabel = helper.appWindow->findChild<QObject *>("parentPopupLabel");
+ QVERIFY(parentPopupLabel);
+ QCOMPARE(parentPopupLabel->property("color").value<QColor>(), "#ffdead");
+
+ // All other child popups don't set anything explicitly, and should inherit from their window.
+ auto *childPopup = helper.appWindow->findChild<QQuickPopup *>("childPopup");
+ QVERIFY(childPopup);
+ auto *childPopupLabel = helper.appWindow->findChild<QObject *>("childPopupLabel");
+ QVERIFY(childPopupLabel);
+ QCOMPARE(childPopupLabel->property("color").value<QColor>(), windowsWindowTextColor);
+
+ auto *grandchildPopup = helper.appWindow->findChild<QQuickPopup *>("grandchildPopup");
+ QVERIFY(grandchildPopup);
+ auto *grandchildPopupLabel = helper.appWindow->findChild<QObject *>("grandchildPopupLabel");
+ QVERIFY(grandchildPopupLabel);
+ QCOMPARE(grandchildPopupLabel->property("color").value<QColor>(), windowsWindowTextColor);
+}
+
class TestTheme : public QQuickTheme
{
public:
@@ -427,6 +473,209 @@ void tst_palette::resolve()
control->property("palette").value<QQuickPalette*>()->windowText());
}
+void tst_palette::resetColor()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("reset-color.qml"));
+
+ QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow*>(component.create()));
+ QVERIFY2(!window.isNull(), qPrintable(component.errorString()));
+ auto windowPalette = window->property("palette").value<QQuickPalette*>();
+ QVERIFY(windowPalette);
+
+ auto control = window->property("control").value<QQuickControl*>();
+ QVERIFY(control);
+ auto controlPalette = control->property("palette").value<QQuickPalette*>();
+ QVERIFY(controlPalette);
+ auto item1Palette = window->property("item1Palette").value<QQuickPalette*>();
+ QVERIFY(item1Palette);
+ auto item2Palette = window->property("item2Palette").value<QQuickPalette*>();
+ QVERIFY(item2Palette);
+
+ QCOMPARE(controlPalette->disabled()->window(), item2Palette->disabled()->window());
+ QCOMPARE(controlPalette->disabled()->text(), item1Palette->disabled()->text());
+ QCOMPARE(controlPalette->disabled()->windowText(), windowPalette->disabled()->windowText());
+
+ {
+ QSignalSpy spy(controlPalette, &QQuickPalette::changed);
+ item1Palette->disabled()->setText(Qt::red);
+ QVERIFY(spy.count() == 1 || spy.wait());
+ QCOMPARE(controlPalette->disabled()->text(), QColor(Qt::red));
+ }
+
+ {
+ QSignalSpy spy(controlPalette, &QQuickPalette::changed);
+ item1Palette->disabled()->setWindowText(Qt::red);
+ QVERIFY(spy.count() == 1 || spy.wait());
+ QCOMPARE(controlPalette->disabled()->windowText(), QColor(Qt::red));
+ }
+
+ {
+ QSignalSpy spy(controlPalette, &QQuickPalette::changed);
+ item2Palette->disabled()->setWindowText(Qt::blue);
+ QVERIFY(spy.count() == 1 || spy.wait());
+ QCOMPARE(controlPalette->disabled()->windowText(), QColor(Qt::blue));
+ }
+
+ {
+ QSignalSpy spy(controlPalette, &QQuickPalette::changed);
+ QMetaObject::invokeMethod(window.get(), "resetColor", Qt::DirectConnection);
+ QCOMPARE(controlPalette->window(), windowPalette->window());
+ windowPalette->setWindow(Qt::green);
+ QCOMPARE(controlPalette->window(), QColor(Qt::green));
+ QVERIFY(spy.count() >= 2);
+ }
+
+ {
+ QSignalSpy spy(controlPalette, &QQuickPalette::changed);
+ QMetaObject::invokeMethod(window.get(), "resetGroup", Qt::DirectConnection);
+ QCOMPARE(controlPalette->disabled()->windowText(), windowPalette->disabled()->windowText());
+ windowPalette->disabled()->setWindow(Qt::blue);
+ QCOMPARE(controlPalette->disabled()->window(), QColor(Qt::blue));
+ item2Palette->disabled()->setWindow(Qt::red);
+ QCOMPARE(controlPalette->disabled()->window(), QColor(Qt::blue));
+ if (spy.count() == 0)
+ spy.wait();
+ QCOMPARE(spy.count(), 2);
+ }
+}
+
+void tst_palette::updateBindingPalette()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("palette-appwindow-bindingpalette.qml"));
+
+ QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow*>(component.create()));
+ QVERIFY2(!window.isNull(), qPrintable(component.errorString()));
+ auto *windowPalette = window->property("palette").value<QQuickPalette *>();
+ QVERIFY(windowPalette);
+ auto *customPalette = window->property("cstmPalette").value<QQuickPalette *>();
+ QVERIFY(customPalette);
+
+ QCOMPARE(windowPalette->buttonText(), QColor("white"));
+
+ QColor buttonTextColor("red");
+ customPalette->setButtonText(buttonTextColor);
+ QCOMPARE(customPalette->buttonText(), buttonTextColor);
+ QCOMPARE(windowPalette->buttonText(), customPalette->buttonText());
+}
+
+void tst_palette::comboBoxPopup_data()
+{
+ QTest::addColumn<QString>("style");
+ QTest::addColumn<QString>("qmlFilePath");
+
+ QTest::newRow("Window, Basic") << "Basic" << "comboBoxPopupWithWindow.qml";
+ QTest::newRow("ApplicationWindow, Basic") << "Basic" << "comboBoxPopupWithApplicationWindow.qml";
+ QTest::newRow("Window, Fusion") << "Fusion" << "comboBoxPopupWithWindow.qml";
+ QTest::newRow("ApplicationWindow, Fusion") << "Fusion" << "comboBoxPopupWithApplicationWindow.qml";
+}
+
+// Unlike regular popups, which should inherit their palette from the window and not the parent popup,
+// combo box popups should inherit their palette from the combo box itself.
+void tst_palette::comboBoxPopup()
+{
+ QFETCH(QString, style);
+ QFETCH(QString, qmlFilePath);
+
+ qmlClearTypeRegistrations();
+ QQuickStyle::setStyle(style);
+
+ QQuickApplicationHelper helper(this, qmlFilePath);
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ const auto *windowPalette = window->property("palette").value<QQuickPalette *>();
+ QVERIFY(windowPalette);
+
+ const auto *popup = window->property("popup").value<QQuickPopup *>();
+ QVERIFY(popup);
+ const auto *popupBackground = popup->background();
+ QCOMPARE(popupBackground->property("color"), QColorConstants::Red);
+ QCOMPARE(popupBackground->property("palette").value<QQuickPalette*>()->toQPalette().window().color(),
+ QColorConstants::Red);
+
+ // This has the default palette.
+ const auto *topLevelComboBox = window->property("topLevelComboBox").value<QQuickComboBox *>();
+ QVERIFY(topLevelComboBox);
+ const auto *topLevelComboBoxBackground = topLevelComboBox->popup()->background();
+ QCOMPARE_NE(topLevelComboBoxBackground->property("color"), QColorConstants::Red);
+ QCOMPARE_NE(topLevelComboBoxBackground->property("palette").value<QQuickPalette*>()->toQPalette().window().color(),
+ QColorConstants::Red);
+
+ // The popup that this combo box is in has its window role set to red,
+ // so the combo box's popup background should be red too.
+ const auto *comboBoxInPopup = window->property("comboBoxInPopup").value<QQuickComboBox *>();
+ QVERIFY(comboBoxInPopup);
+ const auto *comboBoxInPopupBackground = comboBoxInPopup->popup()->background();
+ QCOMPARE(comboBoxInPopupBackground->property("color"), QColorConstants::Red);
+ QCOMPARE(comboBoxInPopupBackground->property("palette").value<QQuickPalette*>()->toQPalette().window().color(),
+ QColorConstants::Red);
+}
+
+void tst_palette::comboBoxPopupWithThemeDefault_data()
+{
+ QTest::addColumn<QString>("style");
+ QTest::addColumn<QColor>("expectedComboBoxPopupBackgroundColor");
+
+ QTest::newRow("Basic") << "Basic" << QColor::fromRgb(0xFFFFFF);
+
+ // We can't test Fusion because it uses the default application palette,
+ // which is the default-constructed QPalette, so the test would always pass.
+}
+
+void tst_palette::comboBoxPopupWithThemeDefault()
+{
+ QFETCH(QString, style);
+ QFETCH(QColor, expectedComboBoxPopupBackgroundColor);
+
+ qmlClearTypeRegistrations();
+ QQuickStyle::setStyle(style);
+
+ QQuickApplicationHelper helper(this, "comboBoxPopupWithThemeDefault.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ const auto *comboBox = window->property("comboBox").value<QQuickComboBox *>();
+ QVERIFY(comboBox);
+ const auto *comboBoxBackground = comboBox->popup()->background();
+ QCOMPARE(comboBoxBackground->property("color"), expectedComboBoxPopupBackgroundColor);
+}
+
+void tst_palette::toolTipPaletteUpdate()
+{
+ QQuickApplicationHelper helper(this, "toolTipPaletteUpdate.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *button = window->findChild<QQuickButton *>("button");
+ QVERIFY(button);
+ auto *attachedToolTip = button->findChild<QQuickToolTipAttached *>();
+ QVERIFY(attachedToolTip);
+ auto *toolTip = attachedToolTip->toolTip();
+ QVERIFY(toolTip);
+
+ auto windowPalette = QQuickWindowPrivate::get(window)->palette();
+ auto toolTipPalette = QQuickPopupPrivate::get(toolTip)->palette();
+
+ QCOMPARE(toolTipPalette->toolTipBase(), windowPalette->toolTipBase());
+ QCOMPARE(toolTipPalette->toolTipText(), windowPalette->toolTipText());
+
+ windowPalette->setToolTipBase(Qt::blue);
+ windowPalette->setToolTipText(Qt::red);
+
+ QCOMPARE(toolTipPalette->toolTipBase(), windowPalette->toolTipBase());
+ QCOMPARE(toolTipPalette->toolTipText(), windowPalette->toolTipText());
+}
+
QTEST_MAIN(tst_palette)
#include "tst_palette.moc"
diff --git a/tests/auto/quickcontrols/platform/CMakeLists.txt b/tests/auto/quickcontrols/platform/CMakeLists.txt
index a2f77fdd9c..5669052475 100644
--- a/tests/auto/quickcontrols/platform/CMakeLists.txt
+++ b/tests/auto/quickcontrols/platform/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_platform LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/platform/data/tst_colordialog.qml b/tests/auto/quickcontrols/platform/data/tst_colordialog.qml
index 093a99b31b..6d5b11e84b 100644
--- a/tests/auto/quickcontrols/platform/data/tst_colordialog.qml
+++ b/tests/auto/quickcontrols/platform/data/tst_colordialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
diff --git a/tests/auto/quickcontrols/platform/data/tst_filedialog.qml b/tests/auto/quickcontrols/platform/data/tst_filedialog.qml
index 63a6747e67..66f27cc9ec 100644
--- a/tests/auto/quickcontrols/platform/data/tst_filedialog.qml
+++ b/tests/auto/quickcontrols/platform/data/tst_filedialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
diff --git a/tests/auto/quickcontrols/platform/data/tst_folderdialog.qml b/tests/auto/quickcontrols/platform/data/tst_folderdialog.qml
index 67a5bf0ac0..ed975746b7 100644
--- a/tests/auto/quickcontrols/platform/data/tst_folderdialog.qml
+++ b/tests/auto/quickcontrols/platform/data/tst_folderdialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
diff --git a/tests/auto/quickcontrols/platform/data/tst_fontdialog.qml b/tests/auto/quickcontrols/platform/data/tst_fontdialog.qml
index 884ea7e7d2..684f6e9058 100644
--- a/tests/auto/quickcontrols/platform/data/tst_fontdialog.qml
+++ b/tests/auto/quickcontrols/platform/data/tst_fontdialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
diff --git a/tests/auto/quickcontrols/platform/data/tst_menu.qml b/tests/auto/quickcontrols/platform/data/tst_menu.qml
index 3119c459d6..5e5bf02a2f 100644
--- a/tests/auto/quickcontrols/platform/data/tst_menu.qml
+++ b/tests/auto/quickcontrols/platform/data/tst_menu.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
diff --git a/tests/auto/quickcontrols/platform/data/tst_menubar.qml b/tests/auto/quickcontrols/platform/data/tst_menubar.qml
index ea0d005528..180e656694 100644
--- a/tests/auto/quickcontrols/platform/data/tst_menubar.qml
+++ b/tests/auto/quickcontrols/platform/data/tst_menubar.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
diff --git a/tests/auto/quickcontrols/platform/data/tst_menuitem.qml b/tests/auto/quickcontrols/platform/data/tst_menuitem.qml
index a446bf8c4d..fe218bd32f 100644
--- a/tests/auto/quickcontrols/platform/data/tst_menuitem.qml
+++ b/tests/auto/quickcontrols/platform/data/tst_menuitem.qml
@@ -1,9 +1,10 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
import Qt.labs.platform
+import org.qtproject.Test
TestCase {
id: testCase
@@ -63,6 +64,30 @@ TestCase {
compare(spy.count, 1)
}
+ function test_shortcut() {
+ if (!TestHelper.shortcutsSupported)
+ return;
+
+ let item = createTemporaryObject(menuItem, testCase)
+ verify(item)
+ let spy = createTemporaryObject(signalSpyComponent, testCase, {
+ target: item, signalName: "triggered"
+ })
+ verify(spy)
+ verify(spy.valid)
+
+ data = [TestHelper.shortcutInt, TestHelper.shortcutString, TestHelper.shortcutKeySequence]
+ for (let i = 0; i < data.length; ++i) {
+ item.shortcut = data[i]
+
+ compare(spy.count, i)
+ keySequence("CTRL+P")
+ compare(spy.count, i + 1)
+
+ item.shortcut = {}
+ }
+ }
+
function test_role() {
// Q_ENUMS(QPlatformMenuItem::MenuRole)
compare(MenuItem.NoRole, 0)
diff --git a/tests/auto/quickcontrols/platform/data/tst_menuitemgroup.qml b/tests/auto/quickcontrols/platform/data/tst_menuitemgroup.qml
index 74f3a59a48..e83567cae2 100644
--- a/tests/auto/quickcontrols/platform/data/tst_menuitemgroup.qml
+++ b/tests/auto/quickcontrols/platform/data/tst_menuitemgroup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
diff --git a/tests/auto/quickcontrols/platform/data/tst_menuseparator.qml b/tests/auto/quickcontrols/platform/data/tst_menuseparator.qml
index 4fee4b9374..1c3b58ae98 100644
--- a/tests/auto/quickcontrols/platform/data/tst_menuseparator.qml
+++ b/tests/auto/quickcontrols/platform/data/tst_menuseparator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
diff --git a/tests/auto/quickcontrols/platform/data/tst_messagedialog.qml b/tests/auto/quickcontrols/platform/data/tst_messagedialog.qml
index 93ed4e261e..a42541a4a8 100644
--- a/tests/auto/quickcontrols/platform/data/tst_messagedialog.qml
+++ b/tests/auto/quickcontrols/platform/data/tst_messagedialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
diff --git a/tests/auto/quickcontrols/platform/data/tst_standardpaths.qml b/tests/auto/quickcontrols/platform/data/tst_standardpaths.qml
index 95cdbdf49d..d70323db52 100644
--- a/tests/auto/quickcontrols/platform/data/tst_standardpaths.qml
+++ b/tests/auto/quickcontrols/platform/data/tst_standardpaths.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
diff --git a/tests/auto/quickcontrols/platform/data/tst_systemtrayicon.qml b/tests/auto/quickcontrols/platform/data/tst_systemtrayicon.qml
index 3f043d275f..ef2e0b957c 100644
--- a/tests/auto/quickcontrols/platform/data/tst_systemtrayicon.qml
+++ b/tests/auto/quickcontrols/platform/data/tst_systemtrayicon.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
diff --git a/tests/auto/quickcontrols/platform/tst_platform.cpp b/tests/auto/quickcontrols/platform/tst_platform.cpp
index 94bf1d6a59..dbcc383f03 100644
--- a/tests/auto/quickcontrols/platform/tst_platform.cpp
+++ b/tests/auto/quickcontrols/platform/tst_platform.cpp
@@ -1,13 +1,26 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlengine.h>
#include <QtQuickTest/quicktest.h>
+using namespace Qt::Literals;
+
class Setup : public QObject
{
Q_OBJECT
Q_PROPERTY(bool shortcutsSupported READ areShortcutsSupported CONSTANT FINAL)
+ Q_PROPERTY(QString shortcutString MEMBER m_shortcutString CONSTANT FINAL)
+#if QT_CONFIG(shortcut)
+ Q_PROPERTY(int shortcutInt MEMBER m_shortcutInt CONSTANT FINAL)
+ Q_PROPERTY(QKeySequence shortcutKeySequence MEMBER m_shortcutKeySequence CONSTANT FINAL)
+#endif
+
+ const QString m_shortcutString = u"CTRL+P"_s;
+#if QT_CONFIG(shortcut)
+ const int m_shortcutInt = QKeySequence::Print;
+ const QKeySequence m_shortcutKeySequence{ Qt::CTRL | Qt::Key_P };
+#endif
public:
bool areShortcutsSupported() const
diff --git a/tests/auto/quickcontrols/pointerhandlers/CMakeLists.txt b/tests/auto/quickcontrols/pointerhandlers/CMakeLists.txt
index 8bc7b26b31..4715d15c95 100644
--- a/tests/auto/quickcontrols/pointerhandlers/CMakeLists.txt
+++ b/tests/auto/quickcontrols/pointerhandlers/CMakeLists.txt
@@ -4,7 +4,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_pointerhandlers LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/pointerhandlers/tst_pointerhandlers.cpp b/tests/auto/quickcontrols/pointerhandlers/tst_pointerhandlers.cpp
index aa83175252..46521aad8a 100644
--- a/tests/auto/quickcontrols/pointerhandlers/tst_pointerhandlers.cpp
+++ b/tests/auto/quickcontrols/pointerhandlers/tst_pointerhandlers.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuickTest/quicktest.h>
@@ -199,7 +199,7 @@ void tst_pointerhandlers::buttonTapHandler() // QTBUG-105609
case QPointingDevice::DeviceType::Mouse:
// click it
QTest::mouseClick(&window, mouseButton, Qt::NoModifier, pos);
- QTRY_COMPARE(clickedSpy.size(), 1); // perhaps Button should not react to right-click, but it does
+ QTRY_COMPARE(clickedSpy.size(), mouseButton == Qt::RightButton ? 0 : 1);
QCOMPARE(tappedSpy.size(), 1);
break;
diff --git a/tests/auto/quickcontrols/pressandhold/CMakeLists.txt b/tests/auto/quickcontrols/pressandhold/CMakeLists.txt
index 8d8c967a56..88213edbf3 100644
--- a/tests/auto/quickcontrols/pressandhold/CMakeLists.txt
+++ b/tests/auto/quickcontrols/pressandhold/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_pressandhold LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/pressandhold/tst_pressandhold.cpp b/tests/auto/quickcontrols/pressandhold/tst_pressandhold.cpp
index 98013a1d0c..e65c69a856 100644
--- a/tests/auto/quickcontrols/pressandhold/tst_pressandhold.cpp
+++ b/tests/auto/quickcontrols/pressandhold/tst_pressandhold.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest>
#include <QtQuick>
@@ -43,17 +43,19 @@ void tst_PressAndHold::pressAndHold_data()
{
QTest::addColumn<QByteArray>("data");
QTest::addColumn<QByteArray>("signal");
+ QTest::addColumn<bool>("acceptsRightMouseButton");
- QTest::newRow("Button") << QByteArray("import QtQuick.Controls; Button { text: 'Button' }") << QByteArray(SIGNAL(pressAndHold()));
- QTest::newRow("SwipeDelegate") << QByteArray("import QtQuick.Controls; SwipeDelegate { text: 'SwipeDelegate' }") << QByteArray(SIGNAL(pressAndHold()));
- QTest::newRow("TextField") << QByteArray("import QtQuick.Controls; TextField { text: 'TextField' }") << QByteArray(SIGNAL(pressAndHold(QQuickMouseEvent*)));
- QTest::newRow("TextArea") << QByteArray("import QtQuick.Controls; TextArea { text: 'TextArea' }") << QByteArray(SIGNAL(pressAndHold(QQuickMouseEvent*)));
+ QTest::newRow("Button") << QByteArray("import QtQuick.Controls; Button { text: 'Button' }") << QByteArray(SIGNAL(pressAndHold())) << false;
+ QTest::newRow("SwipeDelegate") << QByteArray("import QtQuick.Controls; SwipeDelegate { text: 'SwipeDelegate' }") << QByteArray(SIGNAL(pressAndHold())) << false;
+ QTest::newRow("TextField") << QByteArray("import QtQuick.Controls; TextField { text: 'TextField' }") << QByteArray(SIGNAL(pressAndHold(QQuickMouseEvent*))) << true;
+ QTest::newRow("TextArea") << QByteArray("import QtQuick.Controls; TextArea { text: 'TextArea' }") << QByteArray(SIGNAL(pressAndHold(QQuickMouseEvent*))) << true;
}
void tst_PressAndHold::pressAndHold()
{
QFETCH(QByteArray, data);
QFETCH(QByteArray, signal);
+ QFETCH(bool, acceptsRightMouseButton);
QQmlEngine engine;
QQmlComponent component(&engine);
@@ -106,19 +108,21 @@ void tst_PressAndHold::pressAndHold()
waitSpy.clear();
// pressAndHold() canceled by 2nd press
- QGuiApplication::sendEvent(control.data(), &press);
- QGuiApplication::sendEvent(control.data(), &press2); // cancels pressAndHold()
- QGuiApplication::sendEvent(waitControl.data(), &press);
- // by the time the second control emits pressAndHold(), we can reliably
- // assume that the first control would have emitted pressAndHold() if it
- // wasn't canceled as appropriate by the 2nd press event above
- QTRY_COMPARE(waitSpy.size(), 1);
- QCOMPARE(spy.size(), 0);
- QGuiApplication::sendEvent(control.data(), &release);
- QGuiApplication::sendEvent(waitControl.data(), &release);
- QCOMPARE(waitSpy.size(), 1);
- QCOMPARE(spy.size(), 0);
- waitSpy.clear();
+ if (acceptsRightMouseButton) {
+ QGuiApplication::sendEvent(control.data(), &press);
+ QGuiApplication::sendEvent(control.data(), &press2); // cancels pressAndHold()
+ QGuiApplication::sendEvent(waitControl.data(), &press);
+ // by the time the second control emits pressAndHold(), we can reliably
+ // assume that the first control would have emitted pressAndHold() if it
+ // wasn't canceled as appropriate by the 2nd press event above
+ QTRY_COMPARE(waitSpy.size(), 1);
+ QCOMPARE(spy.size(), 0);
+ QGuiApplication::sendEvent(control.data(), &release);
+ QGuiApplication::sendEvent(waitControl.data(), &release);
+ QCOMPARE(waitSpy.size(), 1);
+ QCOMPARE(spy.size(), 0);
+ waitSpy.clear();
+ }
}
void tst_PressAndHold::keepSelection_data()
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/CMakeLists.txt b/tests/auto/quickcontrols/qquickapplicationwindow/CMakeLists.txt
index 397441d16a..c8134173b7 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickapplicationwindow LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
@@ -40,11 +40,11 @@ qt_internal_add_test(tst_qquickapplicationwindow
TESTDATA ${test_data}
)
-#### Keys ignored in scope 1:.:.:qquickapplicationwindow.pro:<TRUE>:
-# OTHER_FILES = "data/*.qml"
-
-## Scopes:
-#####################################################################
+# Make the QML files available to Creator's locator.
+target_sources(tst_qquickapplicationwindow
+ PRIVATE
+ ${test_data}
+)
qt_internal_extend_target(tst_qquickapplicationwindow CONDITION ANDROID OR IOS
DEFINES
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/activeFocusControl.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/activeFocusControl.qml
index f699a27fc1..c6073fedeb 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/data/activeFocusControl.qml
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/activeFocusControl.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/activefocusontab.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/activefocusontab.qml
index 7798c4ff1d..dd53faf537 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/data/activefocusontab.qml
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/activefocusontab.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/attachedProperties.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/attachedProperties.qml
index 4bb773a831..d84cdc3daa 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/data/attachedProperties.qml
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/attachedProperties.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/backgroundSize.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/backgroundSize.qml
new file mode 100644
index 0000000000..db5470986f
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/backgroundSize.qml
@@ -0,0 +1,16 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 600
+ height: 400
+
+ background: Item {
+ objectName: "background"
+ implicitWidth: 123
+ implicitHeight: 456
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/basicapplicationwindow.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/basicapplicationwindow.qml
index ba4bf1597e..d59afa7e6b 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/data/basicapplicationwindow.qml
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/basicapplicationwindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/clearfocusondestruction.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/clearfocusondestruction.qml
index 56dfa89e68..e86902c12c 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/data/clearfocusondestruction.qml
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/clearfocusondestruction.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/defaultFocus.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/defaultFocus.qml
index 02ff15ff45..68b889bdc2 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/data/defaultFocus.qml
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/defaultFocus.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/explicitBackgroundSizeBinding.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/explicitBackgroundSizeBinding.qml
new file mode 100644
index 0000000000..67fdf7808c
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/explicitBackgroundSizeBinding.qml
@@ -0,0 +1,21 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ id: window
+ width: 600
+ height: 400
+
+ property real scaleFactor: 1
+
+ background: Rectangle {
+ objectName: "background"
+ color: "green"
+ width: window.width * window.scaleFactor
+ height: window.height * window.scaleFactor
+ anchors.centerIn: parent
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/fill.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/fill.qml
index d57c4c4f71..db0c2a4e89 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/data/fill.qml
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/fill.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/focusAfterPopupClosed.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/focusAfterPopupClosed.qml
index 5e13ac274a..a40277a45c 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/data/focusAfterPopupClosed.qml
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/focusAfterPopupClosed.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/font.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/font.qml
index 4f33439811..8909666b76 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/data/font.qml
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/font.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/layout.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/layout.qml
index 11f2371673..4bcb56e993 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/data/layout.qml
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/layout.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/layoutLayout.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/layoutLayout.qml
index e27fe07b12..3f6b51706c 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/data/layoutLayout.qml
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/layoutLayout.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/locale.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/locale.qml
index 7e0b40095e..e2ccd677d7 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/data/locale.qml
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/locale.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/data/opacity.qml b/tests/auto/quickcontrols/qquickapplicationwindow/data/opacity.qml
index ea2de5ccd2..5a7edc532b 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/data/opacity.qml
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/data/opacity.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp b/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp
index e055340dde..0b84bca678 100644
--- a/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp
+++ b/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtCore/qoperatingsystemversion.h>
@@ -12,6 +12,7 @@
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtGui/private/qguiapplication_p.h>
+#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
#include <QtQuickTemplates2/private/qquickoverlay_p.h>
#include <QtQuickTemplates2/private/qquickcontrol_p.h>
@@ -22,8 +23,10 @@
#include <QtQuickTemplates2/private/qquicktextfield_p.h>
#include <QtQuickTemplates2/private/qquicktheme_p_p.h>
#include <QtQuickControls2/qquickstyle.h>
+#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
using namespace QQuickVisualTestUtils;
+using namespace QQuickControlsTestUtils;
class tst_QQuickApplicationWindow : public QQmlDataTest
{
@@ -50,11 +53,15 @@ private slots:
void layoutLayout();
void componentComplete();
void opacity();
+ void backgroundSize();
+ void explicitBackgroundSizeBinding();
};
tst_QQuickApplicationWindow::tst_QQuickApplicationWindow()
: QQmlDataTest(QT_QMLTEST_DATADIR)
{
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
QQuickStyle::setStyle("Basic");
}
@@ -275,6 +282,10 @@ void tst_QQuickApplicationWindow::implicitFill()
void tst_QQuickApplicationWindow::attachedProperties()
{
+ if (QGuiApplication::platformName().startsWith(QLatin1String("eglfs"), Qt::CaseInsensitive))
+ {
+ QSKIP("This test uses multiple windows and it crashes on EGLFS because of that");
+ }
QQmlEngine engine;
QQmlComponent component(&engine);
component.loadUrl(testFileUrl("attachedProperties.qml"));
@@ -930,6 +941,68 @@ void tst_QQuickApplicationWindow::opacity()
QVERIFY(window);
}
+void tst_QQuickApplicationWindow::backgroundSize()
+{
+ QQuickControlsApplicationHelper helper(this, QLatin1String("backgroundSize.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ QCOMPARE(window->width(), 600);
+ QCOMPARE(window->height(), 400);
+
+ auto *background = window->background();
+ QCOMPARE(background->implicitWidth(), 123);
+ QCOMPARE(background->implicitHeight(), 456);
+ QCOMPARE(background->width(), window->width());
+ QCOMPARE(background->height(), window->height());
+
+ // Changing the implicit size of the background shouldn't have any effect
+ // on its size if it was never explicitly set.
+ background->setImplicitWidth(234);
+ QCOMPARE(background->implicitWidth(), 234);
+ QCOMPARE(window->width(), 600);
+ QCOMPARE(background->width(), window->width());
+
+ background->setImplicitHeight(567);
+ QCOMPARE(background->implicitHeight(), 567);
+ QCOMPARE(window->height(), 400);
+ QCOMPARE(background->height(), window->height());
+
+ // Explicitly setting the size of the background should ensure
+ // that it's respected from that point onwards.
+ background->setWidth(345);
+ QCOMPARE(background->implicitWidth(), 234);
+ QCOMPARE(window->width(), 600);
+ QCOMPARE(background->width(), 345);
+
+ window->setWidth(610);
+ QCOMPARE(background->width(), 345);
+
+ background->setHeight(678);
+ QCOMPARE(background->implicitHeight(), 567);
+ QCOMPARE(window->height(), 400);
+ QCOMPARE(background->height(), 678);
+
+ window->setHeight(410);
+ QCOMPARE(background->height(), 678);
+}
+
+void tst_QQuickApplicationWindow::explicitBackgroundSizeBinding()
+{
+ QQuickControlsApplicationHelper helper(this, QLatin1String("explicitBackgroundSizeBinding.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *background = window->background();
+ QCOMPARE(background->width(), window->width());
+ QCOMPARE(background->height(), window->height());
+
+ window->setProperty("scaleFactor", 0.5);
+ QCOMPARE(background->width(), window->width() / 2);
+ QCOMPARE(background->height(), window->height() / 2);
+}
+
QTEST_MAIN(tst_QQuickApplicationWindow)
#include "tst_qquickapplicationwindow.moc"
diff --git a/tests/auto/quickcontrols/qquickcolor/CMakeLists.txt b/tests/auto/quickcontrols/qquickcolor/CMakeLists.txt
index efd06f15ff..9cf98b4c84 100644
--- a/tests/auto/quickcontrols/qquickcolor/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickcolor/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickcolor LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickcolor/data/tst_color.qml b/tests/auto/quickcontrols/qquickcolor/data/tst_color.qml
index d7b6848c3c..cdbb7c41aa 100644
--- a/tests/auto/quickcontrols/qquickcolor/data/tst_color.qml
+++ b/tests/auto/quickcontrols/qquickcolor/data/tst_color.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtTest
diff --git a/tests/auto/quickcontrols/qquickcolor/tst_qquickcolor.cpp b/tests/auto/quickcontrols/qquickcolor/tst_qquickcolor.cpp
index ba92ef5b86..fc6ab552dd 100644
--- a/tests/auto/quickcontrols/qquickcolor/tst_qquickcolor.cpp
+++ b/tests/auto/quickcontrols/qquickcolor/tst_qquickcolor.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
QUICK_TEST_MAIN(tst_qquickcolor)
diff --git a/tests/auto/quickcontrols/qquickcontrol/CMakeLists.txt b/tests/auto/quickcontrols/qquickcontrol/CMakeLists.txt
index a43b14f1fa..69ae922913 100644
--- a/tests/auto/quickcontrols/qquickcontrol/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickcontrol/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickcontrol LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickcontrol/data/flickable.qml b/tests/auto/quickcontrols/qquickcontrol/data/flickable.qml
index 9378e3f9c0..e8ea9d0f76 100644
--- a/tests/auto/quickcontrols/qquickcontrol/data/flickable.qml
+++ b/tests/auto/quickcontrols/qquickcontrol/data/flickable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickcontrol/tst_qquickcontrol.cpp b/tests/auto/quickcontrols/qquickcontrol/tst_qquickcontrol.cpp
index ddb4b7ff8b..1060ddb7fe 100644
--- a/tests/auto/quickcontrols/qquickcontrol/tst_qquickcontrol.cpp
+++ b/tests/auto/quickcontrols/qquickcontrol/tst_qquickcontrol.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
diff --git a/tests/auto/quickcontrols/qquickdrawer/CMakeLists.txt b/tests/auto/quickcontrols/qquickdrawer/CMakeLists.txt
index 2515a8d30e..62a0ee1e96 100644
--- a/tests/auto/quickcontrols/qquickdrawer/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickdrawer/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickdrawer LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-button.qml b/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-button.qml
index ebba679f97..81f7218436 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-button.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-button.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-hover.qml b/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-hover.qml
index d3a9ba499f..b2d380cbda 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-hover.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-hover.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-wheel.qml b/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-wheel.qml
index f59bf5b2db..792fd6b814 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-wheel.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow-wheel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow.qml b/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow.qml
index dcc37f4307..e279c89b11 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/applicationwindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/dragOverModalShadow.qml b/tests/auto/quickcontrols/qquickdrawer/data/dragOverModalShadow.qml
index 73d01fe968..b91e0e9678 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/dragOverModalShadow.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/dragOverModalShadow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/flickable.qml b/tests/auto/quickcontrols/qquickdrawer/data/flickable.qml
index 4ef4605f72..699c214941 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/flickable.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/flickable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/grabber.qml b/tests/auto/quickcontrols/qquickdrawer/data/grabber.qml
index fdcce390d7..20d992cd6a 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/grabber.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/grabber.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/header.qml b/tests/auto/quickcontrols/qquickdrawer/data/header.qml
index c68202ab1d..a36eb3b904 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/header.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/header.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/multiTouch.qml b/tests/auto/quickcontrols/qquickdrawer/data/multiTouch.qml
index e9e9aa7a18..bf2e49f016 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/multiTouch.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/multiTouch.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/multiple.qml b/tests/auto/quickcontrols/qquickdrawer/data/multiple.qml
index 0f9f8ab63a..f6e5eb02af 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/multiple.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/multiple.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/reposition.qml b/tests/auto/quickcontrols/qquickdrawer/data/reposition.qml
index 4c9eea2b67..dc9003e7e2 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/reposition.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/reposition.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/slider.qml b/tests/auto/quickcontrols/qquickdrawer/data/slider.qml
index f1deb12500..b2d4853ff9 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/slider.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/slider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/topEdgeScreenEdge.qml b/tests/auto/quickcontrols/qquickdrawer/data/topEdgeScreenEdge.qml
index 8bf3b2b4fc..6826df8645 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/topEdgeScreenEdge.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/topEdgeScreenEdge.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/window-button.qml b/tests/auto/quickcontrols/qquickdrawer/data/window-button.qml
index 2f0d4af7e6..5c4a40547e 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/window-button.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/window-button.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/window-hover.qml b/tests/auto/quickcontrols/qquickdrawer/data/window-hover.qml
index 81a14dc700..3756873504 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/window-hover.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/window-hover.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/window-wheel.qml b/tests/auto/quickcontrols/qquickdrawer/data/window-wheel.qml
index 802c60bf1c..80a35fc4da 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/window-wheel.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/window-wheel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickdrawer/data/window.qml b/tests/auto/quickcontrols/qquickdrawer/data/window.qml
index fbdc4047d7..a6cf9aab8e 100644
--- a/tests/auto/quickcontrols/qquickdrawer/data/window.qml
+++ b/tests/auto/quickcontrols/qquickdrawer/data/window.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickdrawer/tst_qquickdrawer.cpp b/tests/auto/quickcontrols/qquickdrawer/tst_qquickdrawer.cpp
index 4ec9943135..d16bc7790f 100644
--- a/tests/auto/quickcontrols/qquickdrawer/tst_qquickdrawer.cpp
+++ b/tests/auto/quickcontrols/qquickdrawer/tst_qquickdrawer.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
@@ -63,8 +63,10 @@ private slots:
void hover_data();
void hover();
+#if QT_CONFIG(wheelevent)
void wheel_data();
void wheel();
+#endif
void multiple();
@@ -617,6 +619,7 @@ void tst_QQuickDrawer::hover()
QVERIFY(!drawerItem->isHovered());
}
+#if QT_CONFIG(wheelevent)
void tst_QQuickDrawer::wheel_data()
{
QTest::addColumn<QString>("source");
@@ -703,6 +706,7 @@ void tst_QQuickDrawer::wheel()
QVERIFY(qFuzzyCompare(drawerSlider->value(), oldDrawerValue)); // must not have moved
}
}
+#endif
void tst_QQuickDrawer::multiple()
{
@@ -826,6 +830,13 @@ void tst_QQuickDrawer::multiple()
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() - rightDrawer->width() / 2, window->height() / 2));
QTRY_COMPARE(rightDrawer->position(), 1.0);
QCOMPARE(leftDrawer->position(), 0.0);
+
+ // Hide the window, so it receives no more stray events
+ window->hide();
+ QVERIFY(QTest::qWaitFor([window](){ return !window->isVisible(); }));
+
+ // Remove posted events, before the window goes out of scope
+ QGuiApplication::removePostedEvents(window);
}
void tst_QQuickDrawer::touch_data()
@@ -1044,8 +1055,7 @@ void tst_QQuickDrawer::interactive_data()
void tst_QQuickDrawer::interactive()
{
- if (!(QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)))
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QFETCH(QString, source);
QQuickControlsApplicationHelper helper(this, source);
@@ -1135,14 +1145,16 @@ void tst_QQuickDrawer::flickable()
QTest::touchEvent(window, touchDevice.data()).press(0, from);
static const int steps = 10;
- for (int i = 0; i < steps; ++i) {
- int x = i * qAbs(from.x() - to.x()) / steps;
- int y = i * qAbs(from.y() - to.y()) / steps;
-
+ const QPoint distance(to.x() - from.x(), to.y() - from.y());
+ for (int i = 0; i <= steps; ++i) {
+ const auto pos = from + QPoint(
+ i * distance.x() / steps,
+ i * distance.y() / steps
+ );
if (mouse)
- QTest::mouseMove(window, QPoint(x, y));
+ QTest::mouseMove(window, pos);
else
- QTest::touchEvent(window, touchDevice.data()).move(0, QPoint(x, y));
+ QTest::touchEvent(window, touchDevice.data()).move(0, pos);
QTest::qWait(1); // avoid infinite velocity
}
@@ -1432,14 +1444,24 @@ void tst_QQuickDrawer::touchOutsideOverlay() // QTBUG-103811
void tst_QQuickDrawer::destroyWhileVisible()
{
- QQuickView window;
- QVERIFY(QQuickTest::showView(window, testFileUrl("itemPartialOverlayModal.qml")));
- auto *drawer = window.rootObject()->findChild<QQuickDrawer*>();
+ QScopedPointer<QQuickView> window(new QQuickView());
+ QVERIFY(QQuickTest::showView(*window, testFileUrl("itemPartialOverlayModal.qml")));
+ auto *drawer = window->rootObject()->findChild<QQuickDrawer*>();
QVERIFY(drawer);
drawer->open();
QTRY_VERIFY(drawer->isOpened());
+
+ QQuickItem *dimmer = QQuickPopupPrivate::get(drawer)->dimmer;
+ QSignalSpy dimmerDeletedSpy(dimmer, &QObject::destroyed);
+
// don't crash here when the drawer closes with an exit transition
+ window.reset();
+
+ // make sure the dimmer is deleted
+ QTRY_COMPARE(dimmerDeletedSpy.size(), 1);
+
+
}
QTEST_QUICKCONTROLS_MAIN(tst_QQuickDrawer)
diff --git a/tests/auto/quickcontrols/qquickheaderview/CMakeLists.txt b/tests/auto/quickcontrols/qquickheaderview/CMakeLists.txt
index 1925c85dc8..37220a37f7 100644
--- a/tests/auto/quickcontrols/qquickheaderview/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickheaderview/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickheaderview LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickheaderview/data/DefaultRoles.qml b/tests/auto/quickcontrols/qquickheaderview/data/DefaultRoles.qml
new file mode 100644
index 0000000000..29e7e80d9e
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickheaderview/data/DefaultRoles.qml
@@ -0,0 +1,34 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+import QtQuick
+import QtQuick.Controls
+import TestTableModel
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias headerView: headerView
+
+ Column {
+ HorizontalHeaderView {
+ id: headerView
+
+ width: 200
+ height: 200
+
+ model: TestTableModel {
+ id: tm
+ objectName: "tableModel"
+ rowCount: 1
+ columnCount: 1
+ }
+ textRole: "toolTip"
+ delegate: Rectangle {
+ required property string toolTip
+ implicitWidth: 40
+ implicitHeight: 40
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickheaderview/data/ListModel.qml b/tests/auto/quickcontrols/qquickheaderview/data/ListModel.qml
index de63fc600b..5c6eef831b 100644
--- a/tests/auto/quickcontrols/qquickheaderview/data/ListModel.qml
+++ b/tests/auto/quickcontrols/qquickheaderview/data/ListModel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickheaderview/data/Window.qml b/tests/auto/quickcontrols/qquickheaderview/data/Window.qml
index 6082fab42e..5f910bbd9c 100644
--- a/tests/auto/quickcontrols/qquickheaderview/data/Window.qml
+++ b/tests/auto/quickcontrols/qquickheaderview/data/Window.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickheaderview/data/headerData.qml b/tests/auto/quickcontrols/qquickheaderview/data/headerData.qml
new file mode 100644
index 0000000000..6cc1d8aeb0
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickheaderview/data/headerData.qml
@@ -0,0 +1,37 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+import TestTableModelWithHeader
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias headerView: headerView
+
+ Column {
+ HorizontalHeaderView {
+ id: headerView
+ syncView: tableView
+ textRole: "customRole"
+ }
+ TableView {
+ id: tableView
+ width: 100
+ height: 100
+ model: TestTableModelWithHeader {
+ rowCount: 2
+ columnCount: 2
+ }
+ delegate: Label {
+ text: customRole
+ leftPadding: 10
+ rightPadding: 10
+
+ required property string customRole
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickheaderview/data/resizableHandlerBlockingEvents.qml b/tests/auto/quickcontrols/qquickheaderview/data/resizableHandlerBlockingEvents.qml
new file mode 100644
index 0000000000..0b520c3be3
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickheaderview/data/resizableHandlerBlockingEvents.qml
@@ -0,0 +1,29 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+ApplicationWindow {
+ width: 800
+ height: 600
+
+ ColumnLayout {
+ anchors.fill: parent
+
+ Rectangle {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ color: mouseArea.pressed ? "tomato" : "steelblue"
+
+ MouseArea {
+ id: mouseArea
+ objectName: "mouseArea"
+ anchors.fill: parent
+ }
+ }
+
+ HorizontalHeaderView {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickheaderview/tst_qquickheaderview.cpp b/tests/auto/quickcontrols/qquickheaderview/tst_qquickheaderview.cpp
index 28b92fef71..1d83b56f41 100644
--- a/tests/auto/quickcontrols/qquickheaderview/tst_qquickheaderview.cpp
+++ b/tests/auto/quickcontrols/qquickheaderview/tst_qquickheaderview.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qsignalspy.h>
#include <QtTest/qtest.h>
@@ -8,13 +8,18 @@
#include <QAbstractItemModelTester>
#include <QtQml/QQmlEngine>
#include <QtQml/QQmlComponent>
-#include <QtQuick/private/qquickwindow_p.h>
+#include <QtQuick/private/qquickmousearea_p.h>
#include <QtQuick/private/qquicktext_p.h>
+#include <QtQuick/private/qquickwindow_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
#include <QtQuickTemplates2/private/qquickheaderview_p.h>
+#include <QtQuickTemplates2/private/qquicklabel_p.h>
#include <private/qquickheaderview_p_p.h>
+using namespace QQuickVisualTestUtils;
+
class TestTableModel : public QAbstractTableModel {
Q_OBJECT
Q_PROPERTY(int rowCount READ rowCount WRITE setRowCount NOTIFY rowCountChanged)
@@ -130,6 +135,10 @@ class TestTableModelWithHeader : public TestTableModel {
Q_OBJECT
public:
+ enum Role {
+ CustomRole = Qt::UserRole
+ };
+
void setRowCount(int count) override
{
vData.resize(count);
@@ -141,6 +150,17 @@ public:
hData.resize(count);
TestTableModel::setColumnCount(count);
}
+
+ QVariant data(const QModelIndex &index, int role) const override
+ {
+ switch (role) {
+ case CustomRole:
+ return QString("%1-%2").arg(index.column()).arg(index.row());
+ default:
+ return TestTableModel::data(index, role);
+ }
+ }
+
Q_INVOKABLE QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override
{
@@ -153,6 +173,8 @@ public:
auto &data = orientation == Qt::Horizontal ? hData : vData;
return data[section].toString();
}
+ case CustomRole:
+ return (orientation == Qt::Horizontal ? "c" : "r") + QString::number(section);
default:
return QVariant();
}
@@ -174,6 +196,13 @@ public:
return true;
}
+ Q_INVOKABLE QHash<int, QByteArray> roleNames() const override
+ {
+ auto names = TestTableModel::roleNames();
+ names[CustomRole] = "customRole";
+ return names;
+ }
+
private:
QList<QVariant> hData, vData;
};
@@ -196,6 +225,12 @@ private slots:
void testModel();
void listModel();
+ void resizableHandlerBlockingEvents();
+
+ void headerData();
+
+ void warnMissingDefaultRole();
+
private:
QQmlEngine *engine;
QString errorString;
@@ -212,7 +247,7 @@ private:
};
tst_QQuickHeaderView::tst_QQuickHeaderView()
- : QQmlDataTest(QT_QMLTEST_DATADIR)
+ : QQmlDataTest(QT_QMLTEST_DATADIR, FailOnWarningsPolicy::FailOnWarnings)
{
}
@@ -296,10 +331,14 @@ void tst_QQuickHeaderView::testOrientation()
QVERIFY(vhv);
hhv->setSyncView(&otherView);
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(
+ ".*Setting syncDirection other than Qt::Horizontal is invalid."));
hhv->setSyncDirection(Qt::Vertical);
QVERIFY(QQuickTest::qWaitForPolish(hhv));
vhv->setSyncView(&otherView);
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(
+ ".*Setting syncDirection other than Qt::Vertical is invalid."));
vhv->setSyncDirection(Qt::Horizontal);
QVERIFY(QQuickTest::qWaitForPolish(vhv));
@@ -376,6 +415,50 @@ void tst_QQuickHeaderView::listModel()
QCOMPARE(vhvCell2->property("text"), "222");
}
+// A header shouldn't block events outside of itself.
+void tst_QQuickHeaderView::resizableHandlerBlockingEvents()
+{
+ QQuickApplicationHelper helper(this, QStringLiteral("resizableHandlerBlockingEvents.qml"));
+ QVERIFY2(helper.errorMessage.isEmpty(), helper.errorMessage);
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto mouseArea = window->findChild<QQuickMouseArea *>("mouseArea");
+ QVERIFY(mouseArea);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, mapCenterToWindow(mouseArea));
+ QVERIFY(mouseArea->isPressed());
+}
+
+void tst_QQuickHeaderView::headerData()
+{
+ QQuickApplicationHelper helper(this, QStringLiteral("headerData.qml"));
+ QVERIFY2(helper.errorMessage.isEmpty(), helper.errorMessage);
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto headerView = window->property("headerView").value<QQuickHeaderViewBase *>();
+ QVERIFY(headerView);
+ const auto firstHeaderCell = headerView->itemAtIndex(headerView->index(0, 0));
+ QVERIFY(firstHeaderCell);
+ const auto label = firstHeaderCell->findChild<QQuickLabel *>();
+ QVERIFY(label);
+ QCOMPARE(label->text(), "c0");
+}
+
+void tst_QQuickHeaderView::warnMissingDefaultRole()
+{
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*toolTip.*"));
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*Required property.*"));
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression("TableView.*"));
+ QQuickApplicationHelper helper(this, QStringLiteral("DefaultRoles.qml"));
+ QVERIFY2(helper.errorMessage.isEmpty(), helper.errorMessage);
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+}
+
QTEST_MAIN(tst_QQuickHeaderView)
#include "tst_qquickheaderview.moc"
diff --git a/tests/auto/quickcontrols/qquickiconimage/BLACKLIST b/tests/auto/quickcontrols/qquickiconimage/BLACKLIST
index 70c935375d..dcd5b24391 100644
--- a/tests/auto/quickcontrols/qquickiconimage/BLACKLIST
+++ b/tests/auto/quickcontrols/qquickiconimage/BLACKLIST
@@ -13,3 +13,5 @@ android
android
[translucentColors]
android
+[svgSourceBindingSourceSize]
+android
diff --git a/tests/auto/quickcontrols/qquickiconimage/CMakeLists.txt b/tests/auto/quickcontrols/qquickiconimage/CMakeLists.txt
index 58f8a8f6f5..0eae234d7f 100644
--- a/tests/auto/quickcontrols/qquickiconimage/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickiconimage/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickiconimage LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickiconimage/data/translucentColors.qml b/tests/auto/quickcontrols/qquickiconimage/data/translucentColors.qml
index 61ad329d55..d30be4340a 100644
--- a/tests/auto/quickcontrols/qquickiconimage/data/translucentColors.qml
+++ b/tests/auto/quickcontrols/qquickiconimage/data/translucentColors.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickiconimage/tst_qquickiconimage.cpp b/tests/auto/quickcontrols/qquickiconimage/tst_qquickiconimage.cpp
index 83df118de3..74f3140ebe 100644
--- a/tests/auto/quickcontrols/qquickiconimage/tst_qquickiconimage.cpp
+++ b/tests/auto/quickcontrols/qquickiconimage/tst_qquickiconimage.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtTest/qsignalspy.h>
@@ -49,9 +49,6 @@ private slots:
private:
void setTheme();
-
- qreal dpr;
- int integerDpr;
};
static QImage grabItemToImage(QQuickItem *item)
@@ -62,14 +59,14 @@ static QImage grabItemToImage(QQuickItem *item)
return result->image();
}
-#define SKIP_IF_DPR_TOO_HIGH() \
+#define INIT_DPR(view) \
+ [[maybe_unused]] const qreal dpr = view.devicePixelRatio(); \
+ [[maybe_unused]] const int integerDpr = qCeil(dpr); \
if (dpr > 2) \
QSKIP("Test does not support device pixel ratio greater than 2")
tst_qquickiconimage::tst_qquickiconimage() :
- QQmlDataTest(QT_QMLTEST_DATADIR),
- dpr(qGuiApp->devicePixelRatio()),
- integerDpr(qCeil(dpr))
+ QQmlDataTest(QT_QMLTEST_DATADIR)
{
QQuickStyle::setStyle("Basic");
}
@@ -78,6 +75,7 @@ void tst_qquickiconimage::initTestCase()
{
QQmlDataTest::initTestCase();
QIcon::setThemeName(QStringLiteral("testtheme"));
+
}
void tst_qquickiconimage::defaults()
@@ -91,14 +89,12 @@ void tst_qquickiconimage::defaults()
void tst_qquickiconimage::nameBindingSourceSize()
{
- // We can't have images for every DPR.
- SKIP_IF_DPR_TOO_HIGH();
-
QQuickView view(testFileUrl("nameBindingSourceSize.qml"));
QCOMPARE(view.status(), QQuickView::Ready);
view.show();
view.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&view));
+ INIT_DPR(view);
QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0));
QVERIFY(iconImage);
@@ -132,11 +128,10 @@ void tst_qquickiconimage::nameBindingSourceSize()
void tst_qquickiconimage::nameBindingSourceSizeWidthHeight()
{
- SKIP_IF_DPR_TOO_HIGH();
-
QQuickView view(testFileUrl("nameBindingSourceSizeWidthHeight.qml"));
QCOMPARE(view.status(), QQuickView::Ready);
view.show();
+ INIT_DPR(view);
QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject());
QVERIFY(iconImage);
@@ -150,11 +145,10 @@ void tst_qquickiconimage::nameBindingSourceSizeWidthHeight()
void tst_qquickiconimage::nameBindingNoSizes()
{
- SKIP_IF_DPR_TOO_HIGH();
-
QQuickView view(testFileUrl("nameBindingNoSizes.qml"));
QCOMPARE(view.status(), QQuickView::Ready);
view.show();
+ INIT_DPR(view);
QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject());
QVERIFY(iconImage);
@@ -169,11 +163,11 @@ void tst_qquickiconimage::nameBindingNoSizes()
void tst_qquickiconimage::sourceBindingNoSizes()
{
- SKIP_IF_DPR_TOO_HIGH();
-
QQuickView view(testFileUrl("sourceBindingNoSizes.qml"));
QCOMPARE(view.status(), QQuickView::Ready);
view.show();
+ INIT_DPR(view);
+
view.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&view));
@@ -194,13 +188,12 @@ void tst_qquickiconimage::sourceBindingNoSizes()
void tst_qquickiconimage::sourceBindingSourceSize()
{
- SKIP_IF_DPR_TOO_HIGH();
-
QQuickView view(testFileUrl("sourceBindingSourceSize.qml"));
QCOMPARE(view.status(), QQuickView::Ready);
view.show();
view.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&view));
+ INIT_DPR(view);
QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0));
QVERIFY(iconImage);
@@ -227,13 +220,12 @@ void tst_qquickiconimage::sourceBindingSourceSize()
void tst_qquickiconimage::sourceBindingSourceSizeWidthHeight()
{
- SKIP_IF_DPR_TOO_HIGH();
-
QQuickView view(testFileUrl("sourceBindingSourceSizeWidthHeight.qml"));
QCOMPARE(view.status(), QQuickView::Ready);
view.show();
view.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&view));
+ INIT_DPR(view);
QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject());
QVERIFY(iconImage);
@@ -247,13 +239,12 @@ void tst_qquickiconimage::sourceBindingSourceSizeWidthHeight()
void tst_qquickiconimage::sourceBindingSourceTooLarge()
{
- SKIP_IF_DPR_TOO_HIGH();
-
QQuickView view(testFileUrl("sourceBindingSourceTooLarge.qml"));
QCOMPARE(view.status(), QQuickView::Ready);
view.show();
view.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&view));
+ INIT_DPR(view);
QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject());
QVERIFY(iconImage);
@@ -283,8 +274,6 @@ void tst_qquickiconimage::alignment_data()
void tst_qquickiconimage::alignment()
{
- SKIP_IF_DPR_TOO_HIGH();
-
QFETCH(QQuickImage::HAlignment, horizontalAlignment);
QFETCH(QQuickImage::VAlignment, verticalAlignment);
@@ -293,6 +282,7 @@ void tst_qquickiconimage::alignment()
view.show();
view.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&view));
+ INIT_DPR(view);
QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0));
QVERIFY(iconImage);
@@ -335,6 +325,9 @@ void tst_qquickiconimage::svgNoSizes()
QQuickView view(testFileUrl("svgNoSizes.qml"));
QCOMPARE(view.status(), QQuickView::Ready);
view.show();
+
+ INIT_DPR(view);
+
view.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&view));
@@ -344,8 +337,8 @@ void tst_qquickiconimage::svgNoSizes()
QQuickImage *image = qobject_cast<QQuickImage*>(view.rootObject()->childItems().at(1));
QVERIFY(image);
- QCOMPARE(iconImage->sourceSize().width(), 48);
- QCOMPARE(iconImage->sourceSize().height(), 48);
+ QCOMPARE(iconImage->sourceSize().width(), 48 * integerDpr);
+ QCOMPARE(iconImage->sourceSize().height(), 48 * integerDpr);
QCOMPARE(iconImage->implicitWidth(), 48.0);
QCOMPARE(iconImage->implicitHeight(), 48.0);
QCOMPARE(iconImage->width(), 48.0);
@@ -383,13 +376,12 @@ void tst_qquickiconimage::svgSourceBindingSourceSize()
void tst_qquickiconimage::color()
{
- SKIP_IF_DPR_TOO_HIGH();
-
QQuickView view(testFileUrl("color.qml"));
QCOMPARE(view.status(), QQuickView::Ready);
view.show();
view.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&view));
+ INIT_DPR(view);
QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0));
QVERIFY(iconImage);
@@ -438,8 +430,6 @@ void tst_qquickiconimage::changeSourceSize()
void tst_qquickiconimage::fileSelectors()
{
- SKIP_IF_DPR_TOO_HIGH();
-
QQuickView view;
QScopedPointer<QQmlFileSelector> fileSelector(new QQmlFileSelector(view.engine()));
fileSelector->setExtraSelectors(QStringList() << "testselector");
@@ -448,6 +438,7 @@ void tst_qquickiconimage::fileSelectors()
view.show();
view.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&view));
+ INIT_DPR(view);
QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0));
QVERIFY(iconImage);
diff --git a/tests/auto/quickcontrols/qquickiconlabel/CMakeLists.txt b/tests/auto/quickcontrols/qquickiconlabel/CMakeLists.txt
index 48ede72c13..66add1069d 100644
--- a/tests/auto/quickcontrols/qquickiconlabel/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickiconlabel/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickiconlabel LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickiconlabel/data/colorChanges.qml b/tests/auto/quickcontrols/qquickiconlabel/data/colorChanges.qml
index 35785313db..d28ea1238b 100644
--- a/tests/auto/quickcontrols/qquickiconlabel/data/colorChanges.qml
+++ b/tests/auto/quickcontrols/qquickiconlabel/data/colorChanges.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickiconlabel/data/iconlabel.qml b/tests/auto/quickcontrols/qquickiconlabel/data/iconlabel.qml
index e181526cfd..5b9db97a0d 100644
--- a/tests/auto/quickcontrols/qquickiconlabel/data/iconlabel.qml
+++ b/tests/auto/quickcontrols/qquickiconlabel/data/iconlabel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickiconlabel/data/spacingWithOnlyIcon.qml b/tests/auto/quickcontrols/qquickiconlabel/data/spacingWithOnlyIcon.qml
index a1d90afbf4..bc0d62e867 100644
--- a/tests/auto/quickcontrols/qquickiconlabel/data/spacingWithOnlyIcon.qml
+++ b/tests/auto/quickcontrols/qquickiconlabel/data/spacingWithOnlyIcon.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickiconlabel/data/spacingWithOnlyText.qml b/tests/auto/quickcontrols/qquickiconlabel/data/spacingWithOnlyText.qml
index 5894434b30..c79597a382 100644
--- a/tests/auto/quickcontrols/qquickiconlabel/data/spacingWithOnlyText.qml
+++ b/tests/auto/quickcontrols/qquickiconlabel/data/spacingWithOnlyText.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickiconlabel/tst_qquickiconlabel.cpp b/tests/auto/quickcontrols/qquickiconlabel/tst_qquickiconlabel.cpp
index 8d42cf5faf..c263fbe1bd 100644
--- a/tests/auto/quickcontrols/qquickiconlabel/tst_qquickiconlabel.cpp
+++ b/tests/auto/quickcontrols/qquickiconlabel/tst_qquickiconlabel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qlist.h>
@@ -308,6 +308,7 @@ void tst_qquickiconlabel::colorChanges()
void tst_qquickiconlabel::iconSourceContext()
{
+#if defined(QT_BUILD_INTERNAL)
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("iconSourceContext.qml"));
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
@@ -335,9 +336,9 @@ void tst_qquickiconlabel::iconSourceContext()
QVERIFY(image);
QQuickImagePrivate *imagePrivate
= static_cast<QQuickImagePrivate *>(QQuickItemPrivate::get(image));
- QCOMPARE(imagePrivate->pix.url(), testFileUrl("a.png"));
+ QCOMPARE(imagePrivate->pix1.url(), testFileUrl("a.png"));
}
-
+#endif
}
QTEST_MAIN(tst_qquickiconlabel)
diff --git a/tests/auto/quickcontrols/qquickimaginestyle/CMakeLists.txt b/tests/auto/quickcontrols/qquickimaginestyle/CMakeLists.txt
index 1985784386..91df77c5c9 100644
--- a/tests/auto/quickcontrols/qquickimaginestyle/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickimaginestyle/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickimaginestyle LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickimaginestyle/data/tst_imagine.qml b/tests/auto/quickcontrols/qquickimaginestyle/data/tst_imagine.qml
index c6bb83f72a..26e5f15920 100644
--- a/tests/auto/quickcontrols/qquickimaginestyle/data/tst_imagine.qml
+++ b/tests/auto/quickcontrols/qquickimaginestyle/data/tst_imagine.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickimaginestyle/tst_qquickimaginestyle.cpp b/tests/auto/quickcontrols/qquickimaginestyle/tst_qquickimaginestyle.cpp
index 6cdbbca8e9..aa5d5a0459 100644
--- a/tests/auto/quickcontrols/qquickimaginestyle/tst_qquickimaginestyle.cpp
+++ b/tests/auto/quickcontrols/qquickimaginestyle/tst_qquickimaginestyle.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
QUICK_TEST_MAIN(tst_qquickimaginestyle)
diff --git a/tests/auto/quickcontrols/qquickmaterialstyle/CMakeLists.txt b/tests/auto/quickcontrols/qquickmaterialstyle/CMakeLists.txt
index 784da21614..0fe3fe7b9a 100644
--- a/tests/auto/quickcontrols/qquickmaterialstyle/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickmaterialstyle/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickmaterialstyle LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
@@ -41,7 +41,8 @@ qt_internal_add_resource(tst_qquickmaterialstyle "qmake_immediate"
${qmake_immediate_resource_files}
)
-
-#### Keys ignored in scope 1:.:.:qquickmaterialstyle.pro:<TRUE>:
-# OTHER_FILES = "$$PWD/data/*.qml"
-# TEMPLATE = "app"
+# Make the QML files available to Creator's locator.
+target_sources(tst_qquickmaterialstyle
+ PRIVATE
+ ${test_data}
+)
diff --git a/tests/auto/quickcontrols/qquickmaterialstyle/data/tst_material.qml b/tests/auto/quickcontrols/qquickmaterialstyle/data/tst_material.qml
index bf836b2048..cdd8fb41e6 100644
--- a/tests/auto/quickcontrols/qquickmaterialstyle/data/tst_material.qml
+++ b/tests/auto/quickcontrols/qquickmaterialstyle/data/tst_material.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
@@ -7,6 +7,7 @@ import QtTest
import QtQuick.Templates as T
import QtQuick.Controls
import QtQuick.Controls.Material
+import QtQuick.Controls.Material.impl as MaterialImpl
TestCase {
id: testCase
@@ -23,12 +24,17 @@ TestCase {
}
Component {
- id: button
+ id: signalSpyComponent
+ SignalSpy {}
+ }
+
+ Component {
+ id: buttonComponent
Button { }
}
Component {
- id: styledButton
+ id: styledButtonComponent
Button {
Material.theme: Material.Dark
Material.primary: Material.DeepOrange
@@ -45,17 +51,6 @@ TestCase {
}
Component {
- id: styledWindowComponent
- Window {
- Material.theme: Material.Dark
- Material.primary: Material.Brown
- Material.accent: Material.Green
- Material.background: Material.Yellow
- Material.foreground: Material.Grey
- }
- }
-
- Component {
id: buttonLoaderComponent
Loader {
active: false
@@ -96,6 +91,7 @@ TestCase {
property alias label2: labelInstance2
Popup {
id: popupInstance
+ objectName: "popupQObject"
Label {
id: labelInstance
text: "test"
@@ -151,7 +147,7 @@ TestCase {
}
function test_defaults() {
- let control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(buttonComponent, testCase)
verify(control)
verify(control.Material)
compare(control.Material.primary, Material.color(Material.Indigo))
@@ -165,7 +161,7 @@ TestCase {
}
function test_set() {
- let control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(buttonComponent, testCase)
verify(control)
control.Material.primary = Material.Green
control.Material.accent = Material.Brown
@@ -182,7 +178,7 @@ TestCase {
}
function test_reset() {
- let control = createTemporaryObject(styledButton, testCase)
+ let control = createTemporaryObject(styledButtonComponent, testCase)
verify(control)
compare(control.Material.primary, Material.color(Material.DeepOrange))
compare(control.Material.accent, Material.color(Material.DeepPurple, themeshade(control.Material.theme)))
@@ -218,18 +214,18 @@ TestCase {
function test_inheritance(data) {
let prop = data.tag
- let parent = createTemporaryObject(button, testCase)
+ let parent = createTemporaryObject(buttonComponent, testCase)
parent.Material[prop] = data.value1
compare(parent.Material[prop], data.value1)
- let child1 = button.createObject(parent)
+ let child1 = buttonComponent.createObject(parent)
compare(child1.Material[prop], data.value1)
parent.Material[prop] = data.value2
compare(parent.Material[prop], data.value2)
compare(child1.Material[prop], data.value2)
- let child2 = button.createObject(parent)
+ let child2 = buttonComponent.createObject(parent)
compare(child2.Material[prop], data.value2)
child2.Material[prop] = data.value1
@@ -243,13 +239,13 @@ TestCase {
compare(child1.Material[prop], parent.Material[prop])
verify(child2.Material[prop] !== parent.Material[prop])
- let grandChild1 = button.createObject(child1)
- let grandChild2 = button.createObject(child2)
+ let grandChild1 = buttonComponent.createObject(child1)
+ let grandChild2 = buttonComponent.createObject(child2)
compare(grandChild1.Material[prop], child1.Material[prop])
compare(grandChild2.Material[prop], child2.Material[prop])
- let themelessGrandGrandChild = button.createObject(grandChild1)
- let grandGrandGrandChild1 = button.createObject(themelessGrandGrandChild)
+ let themelessGrandGrandChild = buttonComponent.createObject(grandChild1)
+ let grandGrandGrandChild1 = buttonComponent.createObject(themelessGrandGrandChild)
compare(grandGrandGrandChild1.Material[prop], parent.Material[prop])
child1.Material[prop] = data.value2
@@ -417,7 +413,7 @@ TestCase {
let parentWindow = createTemporaryObject(data.component, null)
verify(parentWindow)
- let control = button.createObject(parentWindow.contentItem)
+ let control = buttonComponent.createObject(parentWindow.contentItem)
verify(control)
compare(control.Material.primary, parentWindow.Material.primary)
compare(control.Material.accent, parentWindow.Material.accent)
@@ -548,14 +544,16 @@ TestCase {
window.combo.forceActiveFocus()
verify(window.combo.activeFocus)
keyClick(Qt.Key_Space)
- verify(window.combo.popup.visible)
- let listView = window.combo.popup.contentItem
+ let comboPopup = window.combo.popup
+ verify(comboPopup.visible)
+ let listView = comboPopup.contentItem
verify(listView)
let child = listView.contentItem.children[0]
verify(child)
compare(window.Material.theme, Material.Light)
compare(window.combo.Material.theme, Material.Dark)
compare(child.Material.theme, Material.Dark)
+ compare(comboPopup.background.color, comboPopup.Material.dialogColor)
compare(window.Material.primary, Material.color(Material.Blue))
compare(window.combo.Material.primary, Material.color(Material.Blue))
compare(child.Material.primary, Material.color(Material.Blue))
@@ -589,7 +587,7 @@ TestCase {
}
function test_colors(data) {
- let control = createTemporaryObject(button, testCase)
+ let control = createTemporaryObject(buttonComponent, testCase)
verify(control)
let prop = data.tag
@@ -635,15 +633,15 @@ TestCase {
return [
{tag: "Button:pixelSize", type: "Button", attribute: "pixelSize", value: 14, window: 20, pane: 10},
{tag: "Button:weight", type: "Button", attribute: "weight", value: Font.Medium, window: Font.Black, pane: Font.Bold},
- {tag: "Button:capitalization", type: "Button", attribute: "capitalization", value: Font.AllUppercase, window: Font.Capitalize, pane: Font.AllLowercase},
+ {tag: "Button:capitalization", type: "Button", attribute: "capitalization", value: Font.MixedCase, window: Font.Capitalize, pane: Font.AllLowercase},
{tag: "TabButton:pixelSize", type: "TabButton", attribute: "pixelSize", value: 14, window: 20, pane: 10},
{tag: "TabButton:weight", type: "TabButton", attribute: "weight", value: Font.Medium, window: Font.Black, pane: Font.Bold},
- {tag: "TabButton:capitalization", type: "TabButton", attribute: "capitalization", value: Font.AllUppercase, window: Font.Capitalize, pane: Font.AllLowercase},
+ {tag: "TabButton:capitalization", type: "TabButton", attribute: "capitalization", value: Font.MixedCase, window: Font.Capitalize, pane: Font.AllLowercase},
{tag: "ToolButton:pixelSize", type: "ToolButton", attribute: "pixelSize", value: 14, window: 20, pane: 10},
{tag: "ToolButton:weight", type: "ToolButton", attribute: "weight", value: Font.Medium, window: Font.Black, pane: Font.Bold},
- {tag: "ToolButton:capitalization", type: "ToolButton", attribute: "capitalization", value: Font.AllUppercase, window: Font.Capitalize, pane: Font.AllLowercase},
+ {tag: "ToolButton:capitalization", type: "ToolButton", attribute: "capitalization", value: Font.MixedCase, window: Font.Capitalize, pane: Font.AllLowercase},
{tag: "ItemDelegate:pixelSize", type: "ItemDelegate", attribute: "pixelSize", value: 14, window: 20, pane: 10},
{tag: "ItemDelegate:weight", type: "ItemDelegate", attribute: "weight", value: Font.Medium, window: Font.Black, pane: Font.Bold},
@@ -746,7 +744,6 @@ TestCase {
function test_background_data() {
return [
{ tag: "button", inherit: false, wait: 400 },
- { tag: "combobox", inherit: false, wait: 400 },
{ tag: "drawer", inherit: true },
{ tag: "groupbox", inherit: true },
{ tag: "frame", inherit: true },
@@ -872,4 +869,500 @@ TestCase {
let item = createTemporaryObject(data.component, testCase)
verify(item)
}
+
+ Component {
+ id: sliderTickMarks
+ Slider {
+ }
+ }
+
+ function test_sliderTickMarks_data() {
+ return [
+ { // 1000 / 100 == 10 tick marks
+ to: 1000,
+ from: 0,
+ stepSize: 100,
+ snapMode: Slider.SnapAlways,
+ expectTickmarks: true
+ },
+ { // 10 / 1 == 10 tick marks
+ to: 10,
+ from: 0,
+ stepSize: 1,
+ snapMode: Slider.SnapAlways,
+ expectTickmarks: true
+ },
+ { // Should still be within the default backgrounds width/height ratio
+ to: 50,
+ from: 10,
+ stepSize: 1,
+ snapMode: Slider.SnapAlways,
+ expectTickmarks: true
+ },
+ { // Math.abs(.0 - 10.0) % 3 != 0 (aka not divisible)
+ to: 10,
+ from: 0,
+ stepSize: 3,
+ snapMode: Slider.SnapAlways,
+ expectTickmarks: false
+ },
+ { // Math.abs(0 - 810.0) % 100 != 0 (aka not divisible)
+ to: 810,
+ from: 0,
+ stepSize: 100,
+ snapMode: Slider.SnapAlways,
+ expectTickmarks: false
+ },
+ { // stepSize isn't positive
+ to: 10,
+ from: 0,
+ stepSize: -1,
+ snapMode: Slider.SnapAlways,
+ expectTickmarks: false
+ },
+ { // stepSize isn't positive
+ to: 10,
+ from: 0,
+ stepSize: 0,
+ snapMode: Slider.SnapAlways,
+ expectTickmarks: false
+ },
+ { // Number of tick marks would exceed the default width/height ratio
+ to: 100,
+ from: 10,
+ stepSize: 1,
+ snapMode: Slider.SnapAlways,
+ expectTickmarks: false
+ },
+ { // snapMode != Slider.SnapAlways
+ to: 10,
+ from: 0,
+ stepSize: 1,
+ snapMode: Slider.NoSnap,
+ expectTickmarks: false
+ }
+ ]
+ }
+
+ function test_sliderTickMarks(data) {
+ let params = {to: data.to, from: data.from, stepSize: data.stepSize, snapMode: data.snapMode}
+ let item = createTemporaryObject(sliderTickMarks, testCase, params)
+ verify(item)
+ compare(item["__isDiscrete"], data.expectTickmarks)
+ }
+
+ Component {
+ id: textFieldComponent
+ TextField {}
+ }
+
+ Component {
+ id: textAreaComponent
+ TextArea {}
+ }
+
+ function test_textFieldPlaceholderTextHorizontalAlignment_data() {
+ return [
+ { tag: "AlignLeft", horizontalAlignment: TextField.AlignLeft },
+ { tag: "AlignHCenter", horizontalAlignment: TextField.AlignHCenter },
+ { tag: "AlignRight", horizontalAlignment: TextField.AlignRight }
+ ]
+ }
+
+ function test_textFieldPlaceholderTextHorizontalAlignment(data) {
+ // The placeholder text should always be near the left side of the TextField, regardless of its horizontalAlignment.
+ let textField = createTemporaryObject(textFieldComponent, testCase, {
+ placeholderText: "TextField",
+ horizontalAlignment: data.horizontalAlignment
+ })
+ verify(textField)
+ let placeholderTextItem = textField.children[0]
+ verify(placeholderTextItem as MaterialImpl.FloatingPlaceholderText)
+ compare(placeholderTextItem.horizontalAlignment, data.horizontalAlignment)
+
+ textField.forceActiveFocus()
+ compare(placeholderTextItem.horizontalAlignment, data.horizontalAlignment)
+ textField.destroy()
+ }
+
+ function test_textAreaPlaceholderTextHorizontalAlignment_data() {
+ return [
+ { tag: "AlignLeft", horizontalAlignment: TextArea.AlignLeft },
+ { tag: "AlignHCenter", horizontalAlignment: TextArea.AlignHCenter },
+ { tag: "AlignRight", horizontalAlignment: TextArea.AlignRight },
+ { tag: "AlignJustify", horizontalAlignment: TextArea.AlignJustify }
+ ]
+ }
+
+ function test_textAreaPlaceholderTextHorizontalAlignment(data) {
+ // The placeholder text should always be near the left side of the TextArea, regardless of its horizontalAlignment.
+ let textArea = createTemporaryObject(textAreaComponent, testCase, {
+ placeholderText: "TextArea",
+ horizontalAlignment: data.horizontalAlignment
+ })
+ verify(textArea)
+ let placeholderTextItem = textArea.children[0]
+ verify(placeholderTextItem as MaterialImpl.FloatingPlaceholderText)
+ compare(placeholderTextItem.horizontalAlignment, data.horizontalAlignment)
+
+ textArea.forceActiveFocus()
+ compare(placeholderTextItem.horizontalAlignment, data.horizontalAlignment)
+ }
+
+ function test_placeholderTextPos() {
+ {
+ // The non-floating placeholder text should be in the middle of TextField regardless of its height.
+ let textField = createTemporaryObject(textFieldComponent, testCase, { placeholderText: "TextField" })
+ verify(textField)
+ let placeholderTextItem = textField.children[0]
+ verify(placeholderTextItem as MaterialImpl.FloatingPlaceholderText)
+ compare(placeholderTextItem.y, (textField.height - placeholderTextItem.height) / 2)
+ textField.height = 10
+ compare(placeholderTextItem.y, (textField.height - placeholderTextItem.height) / 2)
+ textField.destroy()
+ }
+
+ {
+ // The non-floating placeholder text should be near the top of TextArea while it has room...
+ let textArea = createTemporaryObject(textAreaComponent, testCase, { placeholderText: "TextArea" })
+ verify(textArea)
+ let placeholderTextItem = textArea.children[0]
+ verify(placeholderTextItem as MaterialImpl.FloatingPlaceholderText)
+ compare(placeholderTextItem.y, (placeholderTextItem.controlImplicitBackgroundHeight - placeholderTextItem.largestHeight) / 2)
+
+ // ... also when it has a lot of room...
+ textArea.height = 200
+ compare(placeholderTextItem.y, (placeholderTextItem.controlImplicitBackgroundHeight - placeholderTextItem.largestHeight) / 2)
+
+ // ... but when it doesn't have room, it should start behaving like TextField's.
+ textArea.height = 10
+ compare(placeholderTextItem.y, (textArea.height - placeholderTextItem.height) / 2)
+ }
+ }
+
+ function test_outlinedPlaceholderTextPosWithPadding_data() {
+ return [
+ { tag: "TextField, leftPadding=0", component: textFieldComponent, leftPadding: 0 },
+ { tag: "TextField, rightPadding=0", component: textFieldComponent, rightPadding: 0 },
+ { tag: "TextField, leftPadding=20", component: textFieldComponent, leftPadding: 20 },
+ { tag: "TextField, rightPadding=20", component: textFieldComponent, rightPadding: 20 },
+ { tag: "TextArea, leftPadding=0", component: textAreaComponent, leftPadding: 0 },
+ { tag: "TextArea, rightPadding=0", component: textAreaComponent, rightPadding: 0 },
+ { tag: "TextArea, leftPadding=20", component: textAreaComponent, leftPadding: 20 },
+ { tag: "TextArea, rightPadding=20", component: textAreaComponent, rightPadding: 20 },
+ ]
+ }
+
+ function test_outlinedPlaceholderTextPosWithPadding(data) {
+ let control = createTemporaryObject(data.component, testCase, {
+ text: "Text",
+ placeholderText: "Enter text..."
+ })
+ verify(control)
+
+ // Work around QTBUG-99231.
+ if (data.leftPadding !== undefined)
+ control.leftPadding = data.leftPadding
+ if (data.rightPadding !== undefined)
+ control.rightPadding = data.rightPadding
+
+ let placeholderTextItem = control.children[0]
+ verify(placeholderTextItem as MaterialImpl.FloatingPlaceholderText)
+ // This is the default value returned by textFieldHorizontalPadding when using a non-dense variant.
+ compare(placeholderTextItem.x, 16)
+ }
+
+ Component {
+ id: flickableTextAreaComponent
+
+ Flickable {
+ anchors.horizontalCenter: parent.horizontalCenter
+ y: 20
+ width: 180
+ height: 100
+
+ TextArea.flickable: TextArea {
+ placeholderText: "Type something..."
+ text: "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn"
+ }
+ }
+ }
+
+ function test_placeholderTextInFlickable() {
+ let flickable = createTemporaryObject(flickableTextAreaComponent, testCase)
+ verify(flickable)
+
+ let textArea = flickable.TextArea.flickable
+ verify(textArea)
+ let placeholderTextItem = flickable.children[2]
+ verify(placeholderTextItem as MaterialImpl.FloatingPlaceholderText)
+
+ // The placeholder text should always float at a fixed position at the top
+ // when text has been set, even when it's in a Flickable.
+ flickable.contentY = -50
+ compare(placeholderTextItem.y, -placeholderTextItem.largestHeight / 2)
+ flickable.contentY = 0
+
+ // When the text is cleared, it shouldn't float.
+ flickable.height = 160
+ textArea.text = ""
+ compare(placeholderTextItem.y, (placeholderTextItem.controlImplicitBackgroundHeight - placeholderTextItem.largestHeight) / 2)
+ // The background outline gap should be closed.
+ let textContainer = flickable.children[1]
+ verify(textContainer as MaterialImpl.MaterialTextContainer)
+ compare(textContainer.focusAnimationProgress, 0)
+ }
+
+ function test_outlinedTextAreaInFlickablePlaceholderTextClipping() {
+ let flickable = createTemporaryObject(flickableTextAreaComponent, testCase)
+ verify(flickable)
+
+ let textArea = flickable.TextArea.flickable
+ verify(textArea)
+ let placeholderTextItem = flickable.children[2]
+ verify(placeholderTextItem as MaterialImpl.FloatingPlaceholderText)
+ compare(textArea.Material.containerStyle, Material.Outlined)
+ // The Flickable doesn't clip at the moment so topInset should be 0.
+ compare(textArea.topInset, 0)
+ compare(textArea.topPadding, (textArea.implicitBackgroundHeight - placeholderTextItem.largestHeight) / 2)
+
+ // topInset should now be half the placeholder text's height,
+ // and topPadding adjusted accordingly.
+ flickable.clip = true
+ compare(textArea.topInset, placeholderTextItem.largestHeight / 2)
+ compare(textArea.topPadding, ((textArea.implicitBackgroundHeight - placeholderTextItem.largestHeight) / 2) + textArea.topInset)
+
+ // When the text is cleared, the placeholder text shouldn't float, but it should still be accounted for
+ // to avoid it causing jumps in layout sizes, for example.
+ const initialText = textArea.text
+ textArea.text = ""
+ compare(textArea.topPadding, ((textArea.implicitBackgroundHeight - placeholderTextItem.largestHeight) / 2) + textArea.topInset)
+
+ flickable.clip = false
+ compare(textArea.topInset, 0)
+ compare(textArea.topPadding, (textArea.implicitBackgroundHeight - placeholderTextItem.largestHeight) / 2)
+ }
+
+ function test_outlinedTextAreaPlaceholderTextClipping() {
+ let textArea = createTemporaryObject(textAreaComponent, testCase, {
+ placeholderText: "Type something",
+ text: "Text"
+ })
+ verify(textArea)
+ let placeholderTextItem = textArea.children[0]
+ verify(placeholderTextItem as MaterialImpl.FloatingPlaceholderText)
+ compare(textArea.topInset, 0)
+ compare(textArea.topPadding, (textArea.implicitBackgroundHeight - placeholderTextItem.largestHeight) / 2)
+
+ // topInset should now be half the placeholder text's height, and topPadding adjusted accordingly.
+ textArea.clip = true
+ compare(textArea.topInset, placeholderTextItem.largestHeight / 2)
+ compare(textArea.topPadding, ((textArea.implicitBackgroundHeight - placeholderTextItem.largestHeight) / 2) + textArea.topInset)
+ }
+
+ function test_outlinedTextFieldPlaceholderTextClipping() {
+ let textField = createTemporaryObject(textFieldComponent, testCase, {
+ placeholderText: "Type something",
+ text: "Text"
+ })
+ verify(textField)
+ let placeholderTextItem = textField.children[0]
+ verify(placeholderTextItem as MaterialImpl.FloatingPlaceholderText)
+ compare(textField.topInset, 0)
+ compare(textField.topPadding, textField.Material.textFieldVerticalPadding)
+
+ // topInset should now be half the placeholder text's height, and topPadding adjusted accordingly.
+ textField.clip = true
+ compare(textField.topInset, placeholderTextItem.largestHeight / 2)
+ compare(textField.topPadding, textField.Material.textFieldVerticalPadding + textField.topInset)
+ }
+
+ function test_flatButton() {
+ let button = createTemporaryObject(buttonComponent, testCase, { flat: true })
+ verify(button)
+ // A flat button should be transparent by default.
+ compare(button.background.color, "#00000000")
+
+ // However, if a background color is explicitly specified, it should be respected.
+ button.Material.background = "#ff6347"
+ compare(button.background.color, "#ff6347")
+
+ // The text should be legible when it's highlighted.
+ button.Material.background = undefined
+ button.highlighted = true
+ compare(button.background.color.a, 0.25)
+ compare(button.contentItem.color.a, 1)
+ }
+
+ Component {
+ id: itemPropagationToComboBoxPopup
+
+ Rectangle {
+ id: rectangle
+ objectName: "rectangle"
+ anchors.fill: parent
+ color: "#444"
+
+ property alias comboBox: comboBox
+
+ Material.theme: Material.Dark
+
+ ComboBox {
+ id: comboBox
+ objectName: "comboBox"
+ model: 3
+ popup.background.objectName: "comboBoxPopupBackground"
+ popup.contentItem.objectName: "comboBoxPopupContentItem"
+ }
+ }
+ }
+
+ function test_itemPropagationToComboBoxPopup() {
+ let rect = createTemporaryObject(itemPropagationToComboBoxPopup, testCase)
+ verify(rect)
+
+ let comboBox = rect.comboBox
+ mouseClick(comboBox)
+ let comboBoxPopup = comboBox.popup
+ tryCompare(comboBoxPopup, "opened", true)
+ compare(comboBoxPopup.background.color, comboBoxPopup.Material.dialogColor)
+ }
+
+ function test_nullTextAreaBackground() {
+ let textArea = createTemporaryObject(textAreaComponent, testCase)
+ verify(textArea)
+ // Store the placeholder text item before we set the background to null,
+ // because it will be unparented at that point.
+ let placeholderTextItem = textArea.children[0]
+ verify(placeholderTextItem as MaterialImpl.FloatingPlaceholderText)
+ // Assigning null to the background shouldn't cause any warnings,
+ // it should just hide the placeholder text item, since it has nothing to anchor to.
+ // Note that we can't use the properties argument of createTemporaryObject due to QTBUG-117201.
+ textArea.background = null
+ verify(!placeholderTextItem.visible)
+ }
+
+ Component {
+ id: textFieldAndButtonComponent
+
+ FocusScope {
+ focus: true
+ anchors.fill: parent
+
+ property alias textField: textField
+ property alias button: button
+
+ Keys.onEscapePressed: function (event) {
+ event.accepted = true
+ button.forceActiveFocus()
+ textField.forceActiveFocus()
+ }
+
+ TextField {
+ id: textField
+ focus: true
+ placeholderText: "placeholderText"
+ anchors.fill: parent
+ }
+
+ Button {
+ id: button
+ anchors.right: parent.right
+ text: focus ? "focus" : "no focus"
+ }
+ }
+ }
+
+ // QTBUG-118889
+ function test_focusChanges() {
+ let focusScope = createTemporaryObject(textFieldAndButtonComponent, testCase)
+ verify(focusScope)
+ testCase.Window.window.requestActivate()
+ tryCompare(testCase.Window.window, "active", true)
+
+ let textField = focusScope.textField
+ verify(textField.activeFocus)
+ let textFieldActiveFocusSpy = signalSpyComponent.createObject(textField,
+ { target: textField, signalName: "activeFocusChanged" })
+ verify(textFieldActiveFocusSpy.valid)
+
+ let button = focusScope.button
+ let buttonActiveFocusSpy = signalSpyComponent.createObject(button,
+ { target: button, signalName: "activeFocusChanged" })
+ verify(buttonActiveFocusSpy.valid)
+
+ // Shouldn't assert after quickly switching focus.
+ keyClick(Qt.Key_Escape)
+ // true => false => true.
+ compare(textFieldActiveFocusSpy.count, 2)
+ // false => true => false.
+ compare(buttonActiveFocusSpy.count, 2)
+ }
+
+ Component {
+ id: childWindowComponent
+
+ ApplicationWindow {
+ objectName: "parentWindow"
+ property alias childWindow: childWindow
+
+ Material.theme: Material.Dark
+ Material.primary: Material.Brown
+ Material.accent: Material.Green
+ Material.background: Material.Yellow
+ Material.foreground: Material.Grey
+
+ ApplicationWindow {
+ id: childWindow
+ objectName: "childWindow"
+ }
+ }
+ }
+
+ function test_windowBackgroundColorPropagation() {
+ let parentWindow = createTemporaryObject(childWindowComponent, testCase)
+ verify(parentWindow)
+
+ let childWindow = parentWindow.childWindow
+ compare(childWindow.Material.theme, Material.Dark)
+ }
+
+ Component {
+ id: themePropagationWithBehaviorComponent
+
+ ApplicationWindow {
+ width: 200
+ height: 200
+ visible: true
+
+ Material.theme: Material.Dark
+
+ property alias listView: listView
+
+ ListView {
+ id: listView
+ anchors.fill: parent
+ header: Text {
+ text: `Material.theme for header is ${Material.theme} - should be 1`
+
+ Rectangle {
+ anchors.fill: parent
+ z: -1
+ }
+
+ Material.elevation: 6
+ // Having this would break the theme (QTBUG-122783)
+ Behavior on Material.elevation {}
+ }
+ }
+ }
+ }
+
+ function test_themePropagationWithBehavior() {
+ let window = createTemporaryObject(themePropagationWithBehaviorComponent, testCase)
+ verify(window)
+
+ let headerItem = window.listView.headerItem
+ compare(headerItem.Material.theme, Material.Dark)
+ }
}
diff --git a/tests/auto/quickcontrols/qquickmaterialstyle/tst_qquickmaterialstyle.cpp b/tests/auto/quickcontrols/qquickmaterialstyle/tst_qquickmaterialstyle.cpp
index 3594f4b1b0..48a3e2138a 100644
--- a/tests/auto/quickcontrols/qquickmaterialstyle/tst_qquickmaterialstyle.cpp
+++ b/tests/auto/quickcontrols/qquickmaterialstyle/tst_qquickmaterialstyle.cpp
@@ -1,5 +1,19 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
-QUICK_TEST_MAIN(tst_qquickmaterialstyle)
+
+class Setup : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void applicationAvailable()
+ {
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
+ }
+};
+
+QUICK_TEST_MAIN_WITH_SETUP(tst_qquickmaterialstyle, Setup)
+
+#include "tst_qquickmaterialstyle.moc"
diff --git a/tests/auto/quickcontrols/qquickmaterialstyleconf/CMakeLists.txt b/tests/auto/quickcontrols/qquickmaterialstyleconf/CMakeLists.txt
index 36c518aa9c..21765b854d 100644
--- a/tests/auto/quickcontrols/qquickmaterialstyleconf/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickmaterialstyleconf/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickmaterialstyleconf LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickmaterialstyleconf/data/applicationwindow.qml b/tests/auto/quickcontrols/qquickmaterialstyleconf/data/applicationwindow.qml
index 40a384c42f..cfd6ccf682 100644
--- a/tests/auto/quickcontrols/qquickmaterialstyleconf/data/applicationwindow.qml
+++ b/tests/auto/quickcontrols/qquickmaterialstyleconf/data/applicationwindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmaterialstyleconf/qtquickcontrols2.conf b/tests/auto/quickcontrols/qquickmaterialstyleconf/qtquickcontrols2.conf
index 30cee878be..af51b66f05 100644
--- a/tests/auto/quickcontrols/qquickmaterialstyleconf/qtquickcontrols2.conf
+++ b/tests/auto/quickcontrols/qquickmaterialstyleconf/qtquickcontrols2.conf
@@ -4,7 +4,5 @@ Style=Material
[Material]
Background=#444444
Foreground=Red
+Font\Family=Courier
Font\PixelSize=22
-
-[Material\Font]
-Family=Courier
diff --git a/tests/auto/quickcontrols/qquickmaterialstyleconf/tst_qquickmaterialstyleconf.cpp b/tests/auto/quickcontrols/qquickmaterialstyleconf/tst_qquickmaterialstyleconf.cpp
index cec4149149..fa4de03e51 100644
--- a/tests/auto/quickcontrols/qquickmaterialstyleconf/tst_qquickmaterialstyleconf.cpp
+++ b/tests/auto/quickcontrols/qquickmaterialstyleconf/tst_qquickmaterialstyleconf.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQuick/private/qquickitem_p.h>
diff --git a/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt b/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt
index 0277c88446..92bb70af07 100644
--- a/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickmenu LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickmenu/data/actionShortcuts.qml b/tests/auto/quickcontrols/qquickmenu/data/actionShortcuts.qml
index 3d839b98d4..0fbc813250 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/actionShortcuts.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/actionShortcuts.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/actions.qml b/tests/auto/quickcontrols/qquickmenu/data/actions.qml
index 0c4449d888..6420531c12 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/actions.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/actions.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/addItem.qml b/tests/auto/quickcontrols/qquickmenu/data/addItem.qml
index 5678210e25..db9fdccd36 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/addItem.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/addItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/applicationWindowScrollable.qml b/tests/auto/quickcontrols/qquickmenu/data/applicationWindowScrollable.qml
index eb8140eea5..3c95846d21 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/applicationWindowScrollable.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/applicationWindowScrollable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/applicationwindow.qml b/tests/auto/quickcontrols/qquickmenu/data/applicationwindow.qml
index 1b42ee6965..253e265a81 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/applicationwindow.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/applicationwindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/delegateFromSeparateComponent.qml b/tests/auto/quickcontrols/qquickmenu/data/delegateFromSeparateComponent.qml
index 44a7d8d54a..e0009bf94e 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/delegateFromSeparateComponent.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/delegateFromSeparateComponent.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/disableWhenTriggered.qml b/tests/auto/quickcontrols/qquickmenu/data/disableWhenTriggered.qml
index e59026677a..b745bcea11 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/disableWhenTriggered.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/disableWhenTriggered.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/disabledMenuItemKeyNavigation.qml b/tests/auto/quickcontrols/qquickmenu/data/disabledMenuItemKeyNavigation.qml
index c9c893bb9c..827729370f 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/disabledMenuItemKeyNavigation.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/disabledMenuItemKeyNavigation.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/giveMenuItemFocusOnButtonPress.qml b/tests/auto/quickcontrols/qquickmenu/data/giveMenuItemFocusOnButtonPress.qml
index 1db3e351bc..c4e8df236a 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/giveMenuItemFocusOnButtonPress.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/giveMenuItemFocusOnButtonPress.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/invalidUrlInImgTag.qml b/tests/auto/quickcontrols/qquickmenu/data/invalidUrlInImgTag.qml
new file mode 100644
index 0000000000..0bc6c92fd6
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenu/data/invalidUrlInImgTag.qml
@@ -0,0 +1,14 @@
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 100
+ height: 100
+ property alias menu: menu
+ Menu {
+ id: menu
+ MenuItem{
+ text: "<img />"
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenu/data/menuItemWidths.qml b/tests/auto/quickcontrols/qquickmenu/data/menuItemWidths.qml
index ff99abd399..ab8cce3833 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/menuItemWidths.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/menuItemWidths.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/menuSeparator.qml b/tests/auto/quickcontrols/qquickmenu/data/menuSeparator.qml
index b13cd534fd..570dcb3f4d 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/menuSeparator.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/menuSeparator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/mnemonics.qml b/tests/auto/quickcontrols/qquickmenu/data/mnemonics.qml
index 8929b00275..3e072e130f 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/mnemonics.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/mnemonics.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeDynamicSubmenus.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeDynamicSubmenus.qml
new file mode 100644
index 0000000000..951cb7cb6c
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenu/data/nativeDynamicSubmenus.qml
@@ -0,0 +1,53 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias contextMenu: contextMenu
+
+ function addSubMenu(title: string) {
+ contextMenu.addMenu(subMenuComponent.createObject(null, { title: title }))
+ }
+
+ function addAction(menu: T.Menu, text: string) {
+ menu.addAction(actionComponent.createObject(null, { text: text }))
+ }
+
+ function insertAction(menu: T.Menu, index: int, text: string) {
+ menu.insertAction(index, actionComponent.createObject(null, { text: text }))
+ }
+
+ Component {
+ id: actionComponent
+
+ Action {
+ objectName: text
+ }
+ }
+
+ Component {
+ id: subMenuComponent
+
+ Menu {
+ id: subMenu
+ objectName: title
+ popupType: Popup.Native
+
+ Action {
+ text: subMenu.objectName + "Action1"
+ }
+ }
+ }
+
+ Menu {
+ id: contextMenu
+ objectName: "menu"
+ popupType: Popup.Native
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeEmptyMenu.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeEmptyMenu.qml
new file mode 100644
index 0000000000..0ae2c5dc66
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenu/data/nativeEmptyMenu.qml
@@ -0,0 +1,51 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias contextMenu: contextMenu
+
+ function addAction(menu: T.Menu, text: string) {
+ menu.addAction(actionComponent.createObject(null, { text: text }))
+ }
+
+ function insertAction(menu: T.Menu, index: int, text: string) {
+ menu.insertAction(index, actionComponent.createObject(null, { text: text }))
+ }
+
+ function removeAction(menu: T.Menu, index: int) {
+ menu.removeAction(menu.actionAt(index))
+ }
+
+ function addMenu(menu: T.Menu, title: string) {
+ menu.addMenu(menuComponent.createObject(null, { title: title }))
+ }
+
+ Component {
+ id: actionComponent
+
+ Action {
+ objectName: text
+ }
+ }
+
+ Component {
+ id: menuComponent
+
+ Menu {
+ objectName: title
+ }
+ }
+
+ Menu {
+ id: contextMenu
+ objectName: "menu"
+ popupType: Popup.Native
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeMenuSeparator.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeMenuSeparator.qml
new file mode 100644
index 0000000000..54195af349
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenu/data/nativeMenuSeparator.qml
@@ -0,0 +1,43 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias contextMenu: contextMenu
+
+ Menu {
+ id: contextMenu
+ objectName: "menu"
+ popupType: Popup.Native
+
+ Action {
+ objectName: text
+ text: "action1"
+ }
+
+ MenuSeparator {}
+
+ Menu {
+ id: subMenu
+ objectName: "subMenu"
+ popupType: Popup.Native
+
+ Action {
+ objectName: text
+ text: "subAction1"
+ }
+
+ MenuSeparator {}
+
+ Action {
+ objectName: text
+ text: "subAction2"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeMixedItems.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeMixedItems.qml
new file mode 100644
index 0000000000..119d8debec
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenu/data/nativeMixedItems.qml
@@ -0,0 +1,69 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias contextMenu: contextMenu
+
+ function insertRectangle(menu: T.Menu, index: int, color: color) {
+ menu.insertItem(index, rectangleComponent.createObject(null, { color: color }))
+ }
+
+ Component {
+ id: rectangleComponent
+
+ Rectangle {
+ objectName: "rectangle"
+ width: 32
+ height: 32
+ }
+ }
+
+ Component {
+ id: menuComponent
+
+ Menu {
+ objectName: title
+ popupType: contextMenu.popupType
+ }
+ }
+
+ Menu {
+ id: contextMenu
+ objectName: "menu"
+ popupType: contextMenu.popupType
+
+ Action {
+ objectName: text
+ text: "action"
+ }
+
+ MenuItem {
+ text: "menuItem"
+ objectName: text
+ }
+
+ Menu {
+ id: subMenu
+ title: "subMenu"
+ objectName: title
+ popupType: contextMenu.popupType
+
+ Action {
+ objectName: text
+ text: "subAction1"
+ }
+
+ Action {
+ objectName: text
+ text: "subAction2"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeStatic.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeStatic.qml
new file mode 100644
index 0000000000..32ba1f1829
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenu/data/nativeStatic.qml
@@ -0,0 +1,53 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias contextMenu: contextMenu
+
+ Menu {
+ id: contextMenu
+ objectName: "menu"
+ popupType: Popup.Native
+
+ Action {
+ objectName: text
+ text: "action1"
+ shortcut: "A"
+ }
+
+ MenuItem {
+ objectName: text
+ action: Action {
+ text: "menuItemAction"
+ objectName: text
+ shortcut: "B"
+ }
+ }
+
+ Menu {
+ id: subMenu
+ title: "subMenu"
+ objectName: title
+ popupType: Popup.Native
+ // TODO: remove me when the defaults are true
+
+ Action {
+ objectName: text
+ text: "subAction1"
+ shortcut: "1"
+ }
+ }
+ }
+
+ TapHandler {
+ acceptedButtons: Qt.RightButton
+ onTapped: contextMenu.popup()
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenu/data/order.qml b/tests/auto/quickcontrols/qquickmenu/data/order.qml
index 185c9e45c3..4e3ecb7b46 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/order.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/order.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/popup.qml b/tests/auto/quickcontrols/qquickmenu/data/popup.qml
index 8201c9e03f..b9e0fd136b 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/popup.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/popup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/pressAndHold.qml b/tests/auto/quickcontrols/qquickmenu/data/pressAndHold.qml
index ac0f394604..5dde687181 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/pressAndHold.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/pressAndHold.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/removeTakeItem.qml b/tests/auto/quickcontrols/qquickmenu/data/removeTakeItem.qml
index aa321cb3a9..8d19f9df99 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/removeTakeItem.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/removeTakeItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/repeater.qml b/tests/auto/quickcontrols/qquickmenu/data/repeater.qml
index 3c056a1d38..0eddd9f868 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/repeater.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/repeater.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml b/tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml
new file mode 100644
index 0000000000..c4f4906123
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml
@@ -0,0 +1,27 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Window
+
+Window {
+ width: 300
+ height: 300
+
+ property alias menu: menu
+
+ Menu {
+ id: menu
+ anchors.centerIn: parent
+ height: 100
+ visible: true
+ Repeater {
+ model: 10
+ delegate: MenuItem {
+ objectName: text
+ text: (index + 1)
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenu/data/scrollableWithPadding.qml b/tests/auto/quickcontrols/qquickmenu/data/scrollableWithPadding.qml
index 842cb33bfd..9945ee8128 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/scrollableWithPadding.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/scrollableWithPadding.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/subMenuDisabled.qml b/tests/auto/quickcontrols/qquickmenu/data/subMenuDisabled.qml
index 4d5db0bd67..abb29579a9 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/subMenuDisabled.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/subMenuDisabled.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/subMenus.qml b/tests/auto/quickcontrols/qquickmenu/data/subMenus.qml
index 280fd404e8..24d6d9396e 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/subMenus.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/subMenus.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/windowScrollable.qml b/tests/auto/quickcontrols/qquickmenu/data/windowScrollable.qml
index 97a06da63d..b927896741 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/windowScrollable.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/windowScrollable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp b/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp
index ee7ec2c4d3..2ec82fcfeb 100644
--- a/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp
+++ b/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
@@ -9,12 +9,14 @@
#endif
#include <QtGui/qstylehints.h>
#include <QtGui/qpa/qplatformintegration.h>
+#include <QtGui/qpa/qplatformtheme.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlcontext.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
@@ -26,12 +28,16 @@
#include <QtQuickTemplates2/private/qquickbutton_p.h>
#include <QtQuickTemplates2/private/qquickicon_p.h>
#include <QtQuickTemplates2/private/qquickmenu_p.h>
+#include <QtQuickTemplates2/private/qquickmenu_p_p.h>
#include <QtQuickTemplates2/private/qquickmenuitem_p.h>
#include <QtQuickTemplates2/private/qquickmenuseparator_p.h>
+#include <QtQuickTemplates2/private/qquicknativemenuitem_p.h>
using namespace QQuickVisualTestUtils;
using namespace QQuickControlsTestUtils;
+// Native menu tests are in "nativemenus".
+
class tst_QQuickMenu : public QQmlDataTest
{
Q_OBJECT
@@ -40,6 +46,8 @@ public:
tst_QQuickMenu();
private slots:
+ void init() final;
+
void defaults();
void count();
void mouse();
@@ -55,6 +63,7 @@ private slots:
#if QT_CONFIG(cursor)
void popup();
#endif
+ void openParentlessMenu();
void actions();
#if QT_CONFIG(shortcut)
void actionShortcuts();
@@ -72,6 +81,7 @@ private slots:
void subMenuPosition();
void subMenuWithIcon();
void addRemoveSubMenus();
+ void subMenuPopupType();
void scrollable_data();
void scrollable();
void disableWhenTriggered_data();
@@ -86,19 +96,49 @@ private slots:
void giveMenuItemFocusOnButtonPress();
void customMenuCullItems();
void customMenuUseRepeaterAsTheContentItem();
+ void invalidUrlInImgTag();
+ void nativeStatic();
+ void nativeDynamicActions();
+ void nativeDynamicSubmenus();
+ void nativeMenuSeparator();
+ void dontUseNativeMenuWindowsChanges();
+ void nativeMixedItems();
+ void effectivePosition_data();
+ void effectivePosition();
+ void textPadding();
+ void resetCurrentIndexUponPopup_data();
+ void resetCurrentIndexUponPopup();
private:
- static bool hasWindowActivation();
+ bool nativeMenuSupported = false;
+ bool popupWindowsSupported = false;
};
+// This allows us to use QQuickMenuItem's more descriptive operator<< output
+// for the QCOMPARE failure message. It doesn't seem possible to use toString
+// overloads or template specialization when types declared in QML are involved,
+// as is the case for the MenuItems created from Menu's delegate.
+#define COMPARE_MENUITEMS(actualMenuItem, expectedMenuItem) \
+QVERIFY2(actualMenuItem == expectedMenuItem, \
+ qPrintable(QString::fromLatin1("\n Actual: %1\n Expected: %2") \
+ .arg(QDebug::toString(actualMenuItem), QDebug::toString(expectedMenuItem))));
+
tst_QQuickMenu::tst_QQuickMenu()
: QQmlDataTest(QT_QMLTEST_DATADIR)
{
+ std::unique_ptr<QPlatformMenu> platformMenu(QGuiApplicationPrivate::platformTheme()->createPlatformMenu());
+ nativeMenuSupported = platformMenu != nullptr;
+ popupWindowsSupported = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::Capability::MultipleWindows);
}
-bool tst_QQuickMenu::hasWindowActivation()
+void tst_QQuickMenu::init()
{
- return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation));
+ QQmlDataTest::init();
+
+ // By default we don't want to use native menus, as the majority of the tests
+ // were written before they were a thing. We instead explicitly set it where necessary.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
}
void tst_QQuickMenu::defaults()
@@ -145,8 +185,7 @@ void tst_QQuickMenu::count()
void tst_QQuickMenu::mouse()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
@@ -159,6 +198,7 @@ void tst_QQuickMenu::mouse()
centerOnScreen(window);
moveMouseAway(window);
window->show();
+ window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
QQuickMenu *menu = window->property("menu").value<QQuickMenu*>();
@@ -277,8 +317,7 @@ void tst_QQuickMenu::pressAndHold()
void tst_QQuickMenu::contextMenuKeyboard()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls)
QSKIP("This platform only allows tab focus for text controls");
@@ -467,8 +506,7 @@ void tst_QQuickMenu::contextMenuKeyboard()
// QTBUG-70181
void tst_QQuickMenu::disabledMenuItemKeyNavigation()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls)
QSKIP("This platform only allows tab focus for text controls");
@@ -534,8 +572,7 @@ void tst_QQuickMenu::disabledMenuItemKeyNavigation()
void tst_QQuickMenu::mnemonics()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
#ifdef Q_OS_MACOS
QSKIP("Mnemonics are not used on macOS");
@@ -592,8 +629,7 @@ void tst_QQuickMenu::mnemonics()
void tst_QQuickMenu::menuButton()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls)
QSKIP("This platform only allows tab focus for text controls");
@@ -647,8 +683,7 @@ void tst_QQuickMenu::addItem()
void tst_QQuickMenu::menuSeparator()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QQuickControlsApplicationHelper helper(this, QLatin1String("menuSeparator.qml"));
QVERIFY2(helper.ready, helper.failureMessage());
@@ -656,6 +691,7 @@ void tst_QQuickMenu::menuSeparator()
centerOnScreen(window);
moveMouseAway(window);
window->show();
+ window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
QQuickMenu *menu = window->property("menu").value<QQuickMenu*>();
@@ -964,6 +1000,29 @@ void tst_QQuickMenu::popup()
}
#endif // QT_CONFIG(cursor)
+void tst_QQuickMenu::openParentlessMenu()
+{
+ // Check that we don't get a crash if the application sets a menu's parentItem
+ // to null. This will also result in the menu not showing at all, since it's
+ // no longer a part of the scene. Even if this limitiation is technically only
+ // relevant for non-native menus, we enforce it also for native menus to ensure
+ // that an application works the same on all platforms.
+ QQuickControlsApplicationHelper helper(this, QLatin1String("popup.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ centerOnScreen(window);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression("cannot show menu: parent is null"));
+
+ QQuickMenu *menu = window->property("menu").value<QQuickMenu *>();
+ QVERIFY(menu);
+ menu->setParentItem(nullptr);
+ menu->popup();
+ QVERIFY(!menu->isVisible());
+}
+
void tst_QQuickMenu::actions()
{
QQuickControlsApplicationHelper helper(this, QLatin1String("actions.qml"));
@@ -1036,13 +1095,13 @@ void tst_QQuickMenu::actions()
#if QT_CONFIG(shortcut)
void tst_QQuickMenu::actionShortcuts()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QQuickControlsApplicationHelper helper(this, QLatin1String("actionShortcuts.qml"));
QVERIFY2(helper.ready, helper.failureMessage());
QQuickWindow *window = helper.window;
window->show();
+ window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
// Try the menu's shortcut.
@@ -1331,8 +1390,7 @@ void tst_QQuickMenu::subMenuKeyboard_data()
void tst_QQuickMenu::subMenuKeyboard()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QFETCH(bool, cascade);
QFETCH(bool, mirrored);
@@ -1343,6 +1401,7 @@ void tst_QQuickMenu::subMenuKeyboard()
centerOnScreen(window);
moveMouseAway(window);
window->show();
+ window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
if (mirrored) {
@@ -1460,8 +1519,7 @@ void tst_QQuickMenu::subMenuDisabledKeyboard_data()
// QTBUG-69540
void tst_QQuickMenu::subMenuDisabledKeyboard()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QFETCH(bool, cascade);
QFETCH(bool, mirrored);
@@ -1472,6 +1530,7 @@ void tst_QQuickMenu::subMenuDisabledKeyboard()
centerOnScreen(window);
moveMouseAway(window);
window->show();
+ window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
if (mirrored) {
@@ -1780,6 +1839,92 @@ void tst_QQuickMenu::addRemoveSubMenus()
QVERIFY(subSubMenu1Item.isNull());
}
+void tst_QQuickMenu::subMenuPopupType()
+{
+ // Check that all sub-menus will end up with an effective popup
+ // type equal to the root menu.
+ QQuickControlsApplicationHelper helper(this, QLatin1String("subMenus.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *mainMenu = window->property("mainMenu").value<QQuickMenu *>();
+ auto *subMenu1 = window->property("subMenu1").value<QQuickMenu *>();
+ auto *subSubMenu1 = window->property("subSubMenu1").value<QQuickMenu *>();
+ QVERIFY(mainMenu);
+ QVERIFY(subMenu1);
+ QVERIFY(subSubMenu1);
+ auto *mainMenu_d = QQuickMenuPrivate::get(mainMenu);
+ auto *subMenu1_d = QQuickMenuPrivate::get(subMenu1);
+ auto *subSubMenu1_d = QQuickMenuPrivate::get(subSubMenu1);
+
+ mainMenu->setPopupType(QQuickPopup::Item);
+ QCOMPARE(mainMenu->popupType(), QQuickPopup::Item);
+ mainMenu->open();
+ QTRY_VERIFY(mainMenu->isOpened());
+ QCOMPARE(mainMenu_d->resolvedPopupType(), QQuickPopup::Item);
+ QCOMPARE(subMenu1_d->resolvedPopupType(), QQuickPopup::Item);
+ QCOMPARE(subSubMenu1_d->resolvedPopupType(), QQuickPopup::Item);
+ mainMenu->close();
+ QTRY_VERIFY(!mainMenu->isVisible());
+
+ // Even if we set QQuickPopup::Window as preferred popup type for
+ // subMenu1, the the effective type will still be the same as the
+ // parent menu: QQuickPopup::Item
+ subMenu1->setPopupType(QQuickPopup::Window);
+ QCOMPARE(subMenu1->popupType(), QQuickPopup::Window);
+ QCOMPARE(mainMenu->popupType(), QQuickPopup::Item);
+ mainMenu->open();
+ QTRY_VERIFY(mainMenu->isOpened());
+ QCOMPARE(mainMenu_d->resolvedPopupType(), QQuickPopup::Item);
+ QCOMPARE(subMenu1_d->resolvedPopupType(), QQuickPopup::Item);
+ QCOMPARE(subSubMenu1_d->resolvedPopupType(), QQuickPopup::Item);
+ mainMenu->close();
+ QTRY_VERIFY(!mainMenu->isVisible());
+
+ // Setting QQuickPopup::Window on the root menu will force all sub-menus
+ // to use QQuickPopup::Window as well, if it's supported on the platform
+ // where the test runs. Otherwise it will fall back to QQuickPopup::Item.
+ const QQuickPopup::PopupType windowIfSupportedElseItem =
+ popupWindowsSupported ? QQuickPopup::Window : QQuickPopup::Item;
+ mainMenu->setPopupType(QQuickPopup::Window);
+ QCOMPARE(mainMenu->popupType(), QQuickPopup::Window);
+ QCOMPARE(subMenu1->popupType(), QQuickPopup::Window);
+ mainMenu->open();
+ QTRY_VERIFY(mainMenu->isOpened());
+ QCOMPARE(mainMenu_d->resolvedPopupType(), windowIfSupportedElseItem);
+ QCOMPARE(subMenu1_d->resolvedPopupType(), windowIfSupportedElseItem);
+ QCOMPARE(subSubMenu1_d->resolvedPopupType(), windowIfSupportedElseItem);
+ mainMenu->close();
+ QTRY_VERIFY(!mainMenu->isVisible());
+
+ // Setting QQuickPopup::Native on the root menu will force all sub-menus
+ // to use QQuickPopup::Native as well, if it's supported on the platform
+ // where the test runs. Otherwise it will fall back to either
+ // QQuickPopup::Window or QQuickPopup::Item.
+ mainMenu->setPopupType(QQuickPopup::Native);
+ QCOMPARE(mainMenu->popupType(), QQuickPopup::Native);
+ QCOMPARE(subMenu1->popupType(), QQuickPopup::Window);
+ if (nativeMenuSupported) {
+ // Note that we cannot actually show a native popup while testing, since
+ // that will be a blocking call. Instead we just verify that we
+ // intend to use a native menu.
+ QVERIFY(mainMenu_d->useNativeMenu());
+ QVERIFY(subMenu1_d->useNativeMenu());
+ QVERIFY(subSubMenu1_d->useNativeMenu());
+ } else {
+ // When Native is not supported, we fall back to either Window or Item
+ mainMenu->open();
+ QTRY_VERIFY(mainMenu->isOpened());
+ QCOMPARE(mainMenu_d->resolvedPopupType(), windowIfSupportedElseItem);
+ QCOMPARE(subMenu1_d->resolvedPopupType(), windowIfSupportedElseItem);
+ QCOMPARE(subSubMenu1_d->resolvedPopupType(), windowIfSupportedElseItem);
+ mainMenu->close();
+ QTRY_VERIFY(!mainMenu->isVisible());
+ }
+}
+
void tst_QQuickMenu::scrollable_data()
{
QTest::addColumn<QString>("qmlFilePath");
@@ -1787,6 +1932,7 @@ void tst_QQuickMenu::scrollable_data()
QTest::addRow("Window") << QString::fromLatin1("windowScrollable.qml");
QTest::addRow("ApplicationWindow") << QString::fromLatin1("applicationWindowScrollable.qml");
QTest::addRow("WithPadding") << QString::fromLatin1("scrollableWithPadding.qml");
+ QTest::addRow("FixedHeight") << QString::fromLatin1("scrollableWithFixedHeight.qml");
}
void tst_QQuickMenu::scrollable()
@@ -2048,13 +2194,13 @@ void tst_QQuickMenu::menuItemWidthAfterRetranslate()
void tst_QQuickMenu::giveMenuItemFocusOnButtonPress()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QQuickControlsApplicationHelper helper(this, QLatin1String("giveMenuItemFocusOnButtonPress.qml"));
QVERIFY2(helper.ready, helper.failureMessage());
QQuickApplicationWindow *window = helper.appWindow;
window->show();
+ window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
// Press enter on the button to open the menu.
@@ -2115,6 +2261,636 @@ void tst_QQuickMenu::customMenuUseRepeaterAsTheContentItem()
QTRY_VERIFY(!QQuickItemPrivate::get(menuItemLast)->culled);
}
+// QTBUG-116672 - Application loads menu containing invalid styled text
+// (img tag) without crash
+void tst_QQuickMenu::invalidUrlInImgTag()
+{
+ QTest::ignoreMessage(QtWarningMsg, "StyledText - Invalid base url in img tag");
+
+ QQuickControlsApplicationHelper helper(this, QLatin1String("invalidUrlInImgTag.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenu *menu = window->property("menu").value<QQuickMenu*>();
+ QVERIFY(menu);
+ menu->open();
+ QTRY_VERIFY(menu->isVisible());
+
+ QQuickMenuItem *menuItemFirst = qobject_cast<QQuickMenuItem *>(menu->itemAt(0));
+ QVERIFY(menuItemFirst);
+}
+
+void tst_QQuickMenu::nativeStatic()
+{
+ QQuickControlsApplicationHelper helper(this, QLatin1String("nativeStatic.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(contextMenu);
+ auto *contextMenuPrivate = QQuickMenuPrivate::get(contextMenu);
+ QVERIFY(contextMenuPrivate->useNativeMenu());
+
+ // Check that the actions of the parent menu can be accessed
+ // and are in the appropriate places in contentModel and contentData.
+ auto *action1 = contextMenu->actionAt(0);
+ QVERIFY(action1);
+ auto *action1MenuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(0));
+ QVERIFY(action1MenuItem);
+ QCOMPARE(action1MenuItem->action(), action1);
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(contextMenuPrivate->contentData.at(0)),
+ action1MenuItem);
+
+ auto *menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(1));
+ QVERIFY(menuItem);
+ QVERIFY(menuItem->action());
+ QCOMPARE(menuItem->action()->text(), "menuItemAction");
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(contextMenuPrivate->contentData.at(1)), menuItem);
+
+ // Check that the sub-menu can be accessed and is in the
+ // appropriate place in contentData.
+ auto *subMenu = contextMenu->menuAt(2);
+ QVERIFY(subMenu);
+ auto *subMenuPrivate = QQuickMenuPrivate::get(subMenu);
+ auto *subMenuAction1 = subMenu->actionAt(0);
+ QVERIFY(subMenuAction1);
+ auto *subMenuAction1MenuItem = qobject_cast<QQuickMenuItem *>(subMenu->itemAt(0));
+ QVERIFY(subMenuAction1MenuItem);
+ QCOMPARE(subMenuAction1MenuItem->action(), subMenuAction1);
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(subMenuPrivate->contentData.at(0)),
+ subMenuAction1MenuItem);
+}
+
+void tst_QQuickMenu::nativeDynamicActions()
+{
+ QQuickControlsApplicationHelper helper(this, QLatin1String("nativeEmptyMenu.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(contextMenu);
+ auto *contextMenuPrivate = QQuickMenuPrivate::get(contextMenu);
+
+ // Check that items can be appended to an empty menu.
+ QCOMPARE(contextMenu->actionAt(0), nullptr);
+ QVERIFY(QMetaObject::invokeMethod(window, "addAction",
+ Q_ARG(QQuickMenu *, contextMenu), Q_ARG(QString, "action1")));
+ {
+ auto action1 = contextMenu->actionAt(0);
+ QVERIFY(action1);
+ QCOMPARE(action1->text(), "action1");
+ auto *action1MenuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(0));
+ QVERIFY(action1MenuItem);
+ QCOMPARE(action1MenuItem->action(), action1);
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(contextMenuPrivate->contentData.at(0)),
+ action1MenuItem);
+ }
+
+ // Check that actions can be appended after existing items in the parent menu.
+ QCOMPARE(contextMenu->actionAt(1), nullptr);
+ QVERIFY(QMetaObject::invokeMethod(window, "addAction",
+ Q_ARG(QQuickMenu *, contextMenu), Q_ARG(QString, "action2")));
+ {
+ auto action2 = contextMenu->actionAt(1);
+ QVERIFY(action2);
+ QCOMPARE(action2->text(), "action2");
+ auto *action2MenuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(1));
+ QVERIFY(action2MenuItem);
+ QCOMPARE(action2MenuItem->action(), action2);
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(contextMenuPrivate->contentData.at(1)),
+ action2MenuItem);
+ }
+
+ // Check that actions can be inserted before existing items in the parent menu.
+ QVERIFY(QMetaObject::invokeMethod(window, "insertAction",
+ Q_ARG(QQuickMenu *, contextMenu), Q_ARG(int, 0), Q_ARG(QString, "action0")));
+ {
+ auto action0 = contextMenu->actionAt(0);
+ QVERIFY(action0);
+ QCOMPARE(action0->text(), "action0");
+ auto *action0MenuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(0));
+ QVERIFY(action0MenuItem);
+ QCOMPARE(action0MenuItem->action(), action0);
+ // New items are always appended to contentData, regardless of the actual insertion index
+ // in contentModel.
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(contextMenuPrivate->contentData.at(2)),
+ action0MenuItem);
+ }
+}
+
+void tst_QQuickMenu::nativeDynamicSubmenus()
+{
+ QQuickControlsApplicationHelper helper(this, QLatin1String("nativeDynamicSubmenus.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(contextMenu);
+ auto *contextMenuPrivate = QQuickMenuPrivate::get(contextMenu);
+
+ // We construct the sub-menu first in QML. At least on Windows, menu items
+ // added to an empty sub-menu won't show up (tested with Widgets): QTBUG-120494.
+ // So, this adds an already-populated menu as a sub-menu.
+ QVERIFY(QMetaObject::invokeMethod(window, "addSubMenu", Q_ARG(QString, "subMenu1")));
+ auto subMenu1 = contextMenu->menuAt(0);
+ QVERIFY(subMenu1);
+ QCOMPARE(subMenu1->title(), "subMenu1");
+ auto *subMenu1Private = QQuickMenuPrivate::get(subMenu1);
+ if (nativeMenuSupported) {
+ QVERIFY(subMenu1Private->handle);
+ QCOMPARE(subMenu1Private->nativeItems.size(), 1);
+ }
+ auto *subMenu1MenuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(0));
+ QVERIFY(subMenu1MenuItem);
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(contextMenuPrivate->contentData.at(0)),
+ subMenu1MenuItem);
+ QCOMPARE(contextMenuPrivate->contentData.size(), 1);
+ {
+ auto subMenuAction1 = subMenu1->actionAt(0);
+ QVERIFY(subMenuAction1);
+ QCOMPARE(subMenuAction1->text(), "subMenu1Action1");
+ auto *subMenuAction1MenuItem = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(0));
+ QVERIFY(subMenuAction1MenuItem);
+ QCOMPARE(subMenuAction1MenuItem->action(), subMenuAction1);
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(subMenu1Private->contentData.at(0)),
+ subMenuAction1MenuItem);
+ if (nativeMenuSupported)
+ QCOMPARE(subMenu1Private->nativeItems.size(), 1);
+ }
+
+ // Check that actions can be appended after existing items in the sub-menu.
+ QCOMPARE(subMenu1->actionAt(1), nullptr);
+ QVERIFY(QMetaObject::invokeMethod(window, "addAction",
+ Q_ARG(QQuickMenu *, subMenu1), Q_ARG(QString, "subMenu1Action2")));
+ {
+ auto subMenu1Action2 = subMenu1->actionAt(1);
+ QVERIFY(subMenu1Action2);
+ QCOMPARE(subMenu1Action2->text(), "subMenu1Action2");
+ auto *subMenu1Action2MenuItem = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(1));
+ QVERIFY(subMenu1Action2MenuItem);
+ QCOMPARE(subMenu1Action2MenuItem->action(), subMenu1Action2);
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(subMenu1Private->contentData.at(1)),
+ subMenu1Action2MenuItem);
+ QCOMPARE(subMenu1Private->contentData.size(), 2);
+ }
+
+ // Check that actions can be inserted before existing items in the sub-menu.
+ QVERIFY(QMetaObject::invokeMethod(window, "insertAction",
+ Q_ARG(QQuickMenu *, subMenu1), Q_ARG(int, 0), Q_ARG(QString, "subMenu1Action0")));
+ {
+ auto subMenu1Action0 = subMenu1->actionAt(0);
+ QVERIFY(subMenu1Action0);
+ QCOMPARE(subMenu1Action0->text(), "subMenu1Action0");
+ auto *subMenu1Action0MenuItem = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(0));
+ QVERIFY(subMenu1Action0MenuItem);
+ QCOMPARE(subMenu1Action0MenuItem->action(), subMenu1Action0);
+ // New items are always appended to contentData, regardless of the actual insertion index
+ // in contentModel.
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(subMenu1Private->contentData.at(2)),
+ subMenu1Action0MenuItem);
+ QCOMPARE(subMenu1Private->contentData.size(), 3);
+ }
+
+ {
+ // Check that takeMenu works.
+ auto *takenSubMenu = contextMenu->takeMenu(0);
+ QCOMPARE(takenSubMenu, subMenu1);
+ QCOMPARE(contextMenuPrivate->contentData.size(), 0);
+ if (nativeMenuSupported) {
+ QVERIFY(!subMenu1Private->handle);
+ QCOMPARE(subMenu1Private->nativeItems.size(), 0);
+ }
+
+ // Check that the sub-menu can be added back in to the menu.
+ contextMenu->addMenu(takenSubMenu);
+ QCOMPARE(contextMenuPrivate->contentData.size(), 1);
+ auto *subMenu1MenuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(0));
+ QVERIFY(subMenu1MenuItem);
+ QCOMPARE(subMenu1MenuItem->text(), "subMenu1");
+ if (nativeMenuSupported) {
+ QVERIFY(subMenu1Private->handle);
+ QCOMPARE(subMenu1Private->nativeItems.size(), 3);
+ }
+ QCOMPARE(subMenu1Private->contentData.size(), 3);
+
+ auto *subMenu1Action0MenuItem = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(0));
+ QVERIFY(subMenu1Action0MenuItem);
+ }
+
+ // Check that removeMenu works.
+ QVERIFY(contextMenu->menuAt(0));
+ contextMenu->removeMenu(contextMenu->menuAt(0));
+ QCOMPARE(contextMenuPrivate->contentData.size(), 0);
+}
+
+void tst_QQuickMenu::nativeMenuSeparator()
+{
+ QQuickControlsApplicationHelper helper(this, QLatin1String("nativeMenuSeparator.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ // Check that separators in menus are where we expect them to be.
+ QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(contextMenu);
+ auto *contextMenuSeparatorAsItem = contextMenu->itemAt(1);
+ QVERIFY(contextMenuSeparatorAsItem);
+ auto *contextMenuSeparator = qobject_cast<QQuickMenuSeparator *>(contextMenuSeparatorAsItem);
+ QVERIFY(contextMenuSeparator);
+ if (nativeMenuSupported) {
+ auto *contextMenuPrivate = QQuickMenuPrivate::get(contextMenu);
+ QCOMPARE(contextMenuPrivate->nativeItems.size(), 3);
+ auto *contextMenuSeparatorNativeItem = contextMenuPrivate->nativeItems.at(1);
+ QVERIFY(contextMenuSeparatorNativeItem);
+ QVERIFY(contextMenuSeparatorNativeItem->separator());
+ }
+
+ // Check that separators in sub-menus are where we expect them to be.
+ QQuickMenu *subMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(subMenu);
+ auto *subMenuSeparatorAsItem = subMenu->itemAt(1);
+ QVERIFY(subMenuSeparatorAsItem);
+ auto *subMenuSeparator = qobject_cast<QQuickMenuSeparator *>(subMenuSeparatorAsItem);
+ QVERIFY(subMenuSeparator);
+ if (nativeMenuSupported) {
+ auto *subMenuPrivate = QQuickMenuPrivate::get(subMenu);
+ QCOMPARE(subMenuPrivate->nativeItems.size(), 3);
+ auto *subMenuSeparatorNativeItem = subMenuPrivate->nativeItems.at(1);
+ QVERIFY(subMenuSeparatorNativeItem);
+ QVERIFY(subMenuSeparatorNativeItem->separator());
+ }
+}
+
+void tst_QQuickMenu::dontUseNativeMenuWindowsChanges()
+{
+ QSKIP("QTBUG-125967 This test will need to be fixed, by using popupType: Popup.Native instead of AA_DontUseNativeMenuWindows.");
+
+ if (QSysInfo::productType() == QLatin1String("b2qt"))
+ QSKIP("b2qt doesn't support native menus");
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, false);
+ QQuickControlsApplicationHelper helper(this, QLatin1String("nativeStatic.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(contextMenu);
+ QCOMPARE(contextMenu->count(), 3);
+ // Sub-menus should respect the native-ness of their parents.
+ auto *subMenu = contextMenu->menuAt(2);
+ auto *subMenuPrivate = QQuickMenuPrivate::get(subMenu);
+ QVERIFY(subMenuPrivate->useNativeMenu());
+ if (nativeMenuSupported)
+ QVERIFY(subMenuPrivate->handle);
+ else
+ QVERIFY(!subMenuPrivate->handle);
+
+ // Ensure that the menu and its sub-menu have enough room to open.
+ if (window->width() / 2 <= contextMenu->width())
+ window->setWidth(contextMenu->width() * 2 + 1);
+ if (window->height() <= contextMenu->height())
+ window->setHeight(contextMenu->height() + 1);
+ QTRY_COMPARE(window->contentItem()->size(), window->size());
+
+ // We can't test that aboutToShow/aboutToHide is emitted for native menus
+ // because when they are shown, the event loop is blocked until they are closed.
+ // So we just check that a native menu is actually in use before going on to test
+ // non-native menus.
+ auto *contextMenuPrivate = QQuickMenuPrivate::get(contextMenu);
+ if (nativeMenuSupported)
+ QVERIFY(contextMenuPrivate->handle);
+ else
+ QVERIFY(!contextMenuPrivate->handle);
+
+ // We need to wait until the menu is opened before it picks up the changes,
+ // which is why we don't check the native handle here yet.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
+ QVERIFY(!contextMenuPrivate->useNativeMenu());
+ QVERIFY(!subMenuPrivate->useNativeMenu());
+
+ // Check that we can open the menu by right-clicking (or just open it manually
+ // if the platform doesn't support (moving) QCursor).
+ QSignalSpy aboutToShowSpy(contextMenu, &QQuickMenu::aboutToShow);
+ QVERIFY(aboutToShowSpy.isValid());
+ bool couldMoveCursorPos = false;
+ const QPoint cursorPos(1, 1);
+#if QT_CONFIG(cursor)
+ // Try moving the cursor from the current position to test if the platform
+ // supports moving the cursor.
+ const QPoint point = QCursor::pos() + QPoint(1, 1);
+ QCursor::setPos(point);
+ if (QTest::qWaitFor([point]{ return QCursor::pos() == point; })) {
+ couldMoveCursorPos = true;
+ const QPoint globalCursorPos = window->mapToGlobal(cursorPos);
+ QCursor::setPos(globalCursorPos);
+ QTest::mouseClick(window, Qt::RightButton, Qt::NoModifier, cursorPos);
+ }
+#endif
+ if (!couldMoveCursorPos) {
+ contextMenu->setX(cursorPos.x());
+ contextMenu->setY(cursorPos.y());
+ contextMenu->open();
+ }
+ QVERIFY(contextMenu->isVisible());
+ QTRY_VERIFY(contextMenu->isOpened());
+ QCOMPARE(aboutToShowSpy.size(), 1);
+ // Now that it's open and has picked up the changes to Qt::AA_DontUseNativeMenuWindows, we can check it.
+ QVERIFY(!contextMenuPrivate->handle);
+ QVERIFY(!subMenuPrivate->handle);
+ // Check that it opened at the mouse cursor and actually has menu items.
+ QCOMPARE(contextMenu->x(), cursorPos.x());
+ QCOMPARE(contextMenu->y(), cursorPos.y());
+ auto *action1MenuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(0));
+ QVERIFY(action1MenuItem);
+ QCOMPARE(action1MenuItem->text(), "action1");
+
+ // Test setting Qt::AA_DontUseNativeMenuWindows while visible has no effect
+ // (until it's re-opened, which we can't test because we can't test opening native menus).
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, false);
+ QVERIFY(contextMenuPrivate->useNativeMenu());
+ QVERIFY(!contextMenuPrivate->handle);
+ QVERIFY(!subMenuPrivate->handle);
+
+ // Also check the submenu.
+ auto *subAction1MenuItem = qobject_cast<QQuickMenuItem *>(subMenu->itemAt(0));
+ QVERIFY(subAction1MenuItem);
+ QCOMPARE(subAction1MenuItem->text(), "subAction1");
+
+ // Test closing the non-native menu by clicking on an item.
+ QSignalSpy aboutToHideSpy(contextMenu, &QQuickMenu::aboutToHide);
+ QVERIFY(aboutToHideSpy.isValid());
+ QVERIFY(clickButton(action1MenuItem));
+ QVERIFY(!contextMenu->isOpened());
+ QTRY_VERIFY(!contextMenu->isVisible());
+ QCOMPARE(aboutToShowSpy.size(), 1);
+
+ // Although we can't open the native menu, we can at least check that
+ // attempting (the changes won't come into effect until it's re-opened)
+ // to make the menu native again doesn't e.g. crash.
+ QVERIFY(contextMenuPrivate->useNativeMenu());
+ QVERIFY(subMenuPrivate->useNativeMenu());
+ QVERIFY(!contextMenuPrivate->handle);
+ QVERIFY(!subMenuPrivate->handle);
+}
+
+// Check that non-menu items (e.g. Rectangles) can be inserted between menu items without issues.
+void tst_QQuickMenu::nativeMixedItems()
+{
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, false);
+ QQuickControlsApplicationHelper helper(this, QLatin1String("nativeMixedItems.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(contextMenu);
+
+ // Insert a Rectangle between the Action and MenuItem in the top-level menu.
+ QVERIFY(QMetaObject::invokeMethod(window, "insertRectangle",
+ Q_ARG(QQuickMenu *, contextMenu), Q_ARG(int, 1), Q_ARG(QColor, QColorConstants::Red)));
+ {
+ auto *action = contextMenu->actionAt(0);
+ QVERIFY(action);
+ QCOMPARE(action->text(), "action");
+ auto *rectangle = qobject_cast<QQuickRectangle *>(contextMenu->itemAt(1));
+ QVERIFY(rectangle);
+ QCOMPARE(rectangle->color(), QColorConstants::Red);
+ auto *menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(2));
+ QVERIFY(menuItem);
+ QCOMPARE(menuItem->text(), "menuItem");
+ auto *subMenu = contextMenu->menuAt(3);
+ QVERIFY(subMenu);
+ QCOMPARE(subMenu->title(), "subMenu");
+ }
+
+ // Insert a Rectangle at the end of all of the items (which were: {Action, Rectangle, MenuItem, Menu}).
+ QVERIFY(QMetaObject::invokeMethod(window, "insertRectangle",
+ Q_ARG(QQuickMenu *, contextMenu), Q_ARG(int, 4), Q_ARG(QColor, QColorConstants::Blue)));
+ {
+ auto *action = contextMenu->actionAt(0);
+ QVERIFY(action);
+ QCOMPARE(action->text(), "action");
+ auto *rectangle1 = qobject_cast<QQuickRectangle *>(contextMenu->itemAt(1));
+ QVERIFY(rectangle1);
+ QCOMPARE(rectangle1->color(), QColorConstants::Red);
+ auto *menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(2));
+ QVERIFY(menuItem);
+ QCOMPARE(menuItem->text(), "menuItem");
+ auto *subMenu = contextMenu->menuAt(3);
+ QVERIFY(subMenu);
+ QCOMPARE(subMenu->title(), "subMenu");
+ auto *rectangle2 = qobject_cast<QQuickRectangle *>(contextMenu->itemAt(4));
+ QVERIFY(rectangle2);
+ QCOMPARE(rectangle2->color(), QColorConstants::Blue);
+ }
+
+ // Check that the sub-menu can be accessed and is in the
+ // appropriate place in contentData.
+ auto *subMenu = contextMenu->menuAt(3);
+ QVERIFY(subMenu);
+ // Insert a Rectangle between the Action and MenuItem in the top-level menu.
+ QVERIFY(QMetaObject::invokeMethod(window, "insertRectangle",
+ Q_ARG(QQuickMenu *, subMenu), Q_ARG(int, 1), Q_ARG(QColor, QColorConstants::Green)));
+ {
+ auto *action1 = subMenu->actionAt(0);
+ QVERIFY(action1);
+ QCOMPARE(action1->text(), "subAction1");
+ auto *rectangle = qobject_cast<QQuickRectangle *>(subMenu->itemAt(1));
+ QVERIFY(rectangle);
+ QCOMPARE(rectangle->color(), QColorConstants::Green);
+ auto *action2 = subMenu->actionAt(2);
+ QVERIFY(action2);
+ QCOMPARE(action2->text(), "subAction2");
+ }
+}
+void tst_QQuickMenu::effectivePosition_data()
+{
+ QTest::addColumn<QQuickPopup::PopupType>("popupType");
+
+ QTest::newRow("Item") << QQuickPopup::Item;
+ QTest::newRow("Window") << QQuickPopup::Window;
+}
+
+void tst_QQuickMenu::effectivePosition()
+{
+ // Check that the top-left corner of the background delegate
+ // is placed at the requested menu position. For this test to make
+ // sense, the background delegate needs to be responsible for drawing
+ // the window frame (if any), which Qt::FramelessWindowHint implies.
+ QFETCH(QQuickPopup::PopupType, popupType);
+ SKIP_IF_NO_WINDOW_ACTIVATION
+
+ QQuickControlsApplicationHelper helper(this, QLatin1String("applicationwindow.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ QQuickApplicationWindow *window = helper.appWindow;
+ centerOnScreen(window);
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+
+ QQuickMenu *menu = window->property("menu").value<QQuickMenu*>();
+ QVERIFY(menu);
+
+ // This test only makes sense when QQuickMenu is supposed to draw the
+ // window frame. If that changes, then this test will no longer be needed.
+ QVERIFY(QQuickMenuPrivate::get(menu)->popupWindowType() & Qt::FramelessWindowHint);
+
+ menu->setPopupType(popupType);
+
+ // Move the background delegate a bit into the popup, to simulate using a drop-shadow.
+ const QPointF insets = QPointF{20, 10};
+ menu->setLeftInset(insets.x());
+ menu->setTopInset(insets.y());
+
+ const QPointF requestedPos{100, 100};
+ menu->popup(requestedPos);
+ QTRY_VERIFY(menu->isOpened());
+
+ // Unless the popup was moved to fit inside the window (which should not
+ // be the case in this test), we report back to the application that it's
+ // placed at the requested position.
+ QTRY_COMPARE(menu->position(), requestedPos);
+ QCOMPARE(menu->x(), requestedPos.x());
+ QCOMPARE(menu->y(), requestedPos.y());
+
+ // But in reality, it's the background delegate that is placed at the
+ // requested position.
+ const auto background = menu->background();
+ QVERIFY(background);
+ const QPointF actualBgPos = background->mapToItem(menu->parentItem(), {0, 0});
+ QCOMPARE(actualBgPos, requestedPos);
+}
+
+void tst_QQuickMenu::textPadding()
+{
+ // Check that you can set implicitTextPadding on each MenuItem, and that
+ // textPadding will end up as the maximum implicitTextPadding among all the
+ // MenuItems in the same Menu.
+
+ QQuickControlsApplicationHelper helper(this, QLatin1String("nativeMixedItems.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(contextMenu);
+ contextMenu->setPopupType(QQuickPopup::Item);
+
+ contextMenu->setVisible(true);
+
+ // Go through all MenuItems, and give them an implicitTextPadding of 0
+ for (int i = 0; i < contextMenu->count(); ++i) {
+ auto menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(i));
+ QVERIFY(menuItem);
+ menuItem->setImplicitTextPadding(0);
+ QCOMPARE(menuItem->implicitTextPadding(), 0);
+ }
+
+ // Check that all MenuItems now has a textPadding of 0
+ for (int i = 0; i < contextMenu->count(); ++i) {
+ auto menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(i));
+ QCOMPARE(menuItem->textPadding(), 0);
+ }
+
+ // Let the first MenuItem get a implicitTextPadding of 100. This will
+ // make all MenuItems get a textPadding of 100.
+ auto firstItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(0));
+ firstItem->setImplicitTextPadding(100);
+ QCOMPARE(firstItem->implicitTextPadding(), 100);
+ QCOMPARE(firstItem->textPadding(), 100);
+ for (int i = 1; i < contextMenu->count(); ++i) {
+ auto menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(i));
+ QCOMPARE(menuItem->implicitTextPadding(), 0);
+ QCOMPARE(menuItem->textPadding(), 100);
+ }
+
+ // Hide the MenuItem with implicitTextPadding set to 100. This
+ // should make all the MenuItems get a textPadding of 0 again.
+ firstItem->setVisible(false);
+ QCOMPARE(firstItem->implicitTextPadding(), 100);
+ for (int i = 0; i < contextMenu->count(); ++i) {
+ auto menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(i));
+ QCOMPARE(menuItem->textPadding(), 0);
+ }
+
+ // Show it again
+ firstItem->setVisible(true);
+ for (int i = 0; i < contextMenu->count(); ++i) {
+ auto menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(i));
+ QCOMPARE(menuItem->textPadding(), 100);
+ }
+}
+
+void tst_QQuickMenu::resetCurrentIndexUponPopup_data()
+{
+ QTest::addColumn<QQuickPopup::PopupType>("popupType");
+
+ QTest::newRow("Item") << QQuickPopup::Item;
+ QTest::newRow("Window") << QQuickPopup::Window;
+
+ // Note: a call to Menu.popup() will be a blocking call on many platforms
+ // when using native menus (e.g macOS and Windows). We can therefore not
+ // check a Menus internal state, nor make a MenuItem current, while it's visible.
+ // QTest::newRow("Native") << QQuickPopup::Native;
+}
+
+void tst_QQuickMenu::resetCurrentIndexUponPopup()
+{
+ // Check that currentIndex is reset back to -1 when
+ // a menu is repopened using the popup() function without
+ // providing a MenuItem as argument.
+ QFETCH(QQuickPopup::PopupType, popupType);
+ SKIP_IF_NO_WINDOW_ACTIVATION
+
+ QQuickControlsApplicationHelper helper(this, QLatin1String("applicationwindow.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ QQuickApplicationWindow *window = helper.appWindow;
+ centerOnScreen(window);
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+
+ QQuickMenu *menu = window->property("menu").value<QQuickMenu*>();
+ QVERIFY(menu);
+
+ menu->setPopupType(popupType);
+
+ QCOMPARE(menu->currentIndex(), -1);
+ QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1));
+
+ menu->popup();
+ QTRY_VERIFY(menu->isOpened());
+ QCOMPARE(menu->currentIndex(), -1);
+ QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1));
+
+ menu->setCurrentIndex(1);
+ QCOMPARE(menu->currentIndex(), 1);
+ QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(1));
+
+ menu->close();
+ QTRY_VERIFY(!menu->isVisible());
+
+ menu->popup();
+ QTRY_VERIFY(menu->isOpened());
+ QCOMPARE(menu->currentIndex(), -1);
+ QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1));
+}
+
QTEST_QUICKCONTROLS_MAIN(tst_QQuickMenu)
#include "tst_qquickmenu.moc"
diff --git a/tests/auto/quickcontrols/qquickmenubar/CMakeLists.txt b/tests/auto/quickcontrols/qquickmenubar/CMakeLists.txt
index cee75be2f9..0a1c1ccddd 100644
--- a/tests/auto/quickcontrols/qquickmenubar/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickmenubar/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickmenubar LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickmenubar/data/checkHighlightWhenDismissed.qml b/tests/auto/quickcontrols/qquickmenubar/data/checkHighlightWhenDismissed.qml
index 2f8132e2fc..92eae3ef4a 100644
--- a/tests/auto/quickcontrols/qquickmenubar/data/checkHighlightWhenDismissed.qml
+++ b/tests/auto/quickcontrols/qquickmenubar/data/checkHighlightWhenDismissed.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenubar/data/delegateFromSeparateComponent.qml b/tests/auto/quickcontrols/qquickmenubar/data/delegateFromSeparateComponent.qml
index ac03210fa0..bff2d40410 100644
--- a/tests/auto/quickcontrols/qquickmenubar/data/delegateFromSeparateComponent.qml
+++ b/tests/auto/quickcontrols/qquickmenubar/data/delegateFromSeparateComponent.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenubar/data/empty.qml b/tests/auto/quickcontrols/qquickmenubar/data/empty.qml
index 870c3a0bc4..34c0cbc9d8 100644
--- a/tests/auto/quickcontrols/qquickmenubar/data/empty.qml
+++ b/tests/auto/quickcontrols/qquickmenubar/data/empty.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenubar/data/hoverAfterClosingWithEscape.qml b/tests/auto/quickcontrols/qquickmenubar/data/hoverAfterClosingWithEscape.qml
new file mode 100644
index 0000000000..998a6387dd
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenubar/data/hoverAfterClosingWithEscape.qml
@@ -0,0 +1,46 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 300
+ height: 300
+
+ MenuBar {
+ objectName: "menuBar"
+
+ Menu {
+ title: qsTr("File")
+
+ MenuItem {
+ text: qsTr("New")
+ }
+ }
+
+ Menu {
+ title: qsTr("Edit")
+
+ MenuItem {
+ text: qsTr("Undo")
+ }
+ }
+
+ Menu {
+ title: qsTr("View")
+
+ MenuItem {
+ text: qsTr("Center")
+ }
+ }
+
+ Menu {
+ title: qsTr("Tools")
+
+ MenuItem {
+ text: qsTr("Options")
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenubar/data/invaliddelegate.qml b/tests/auto/quickcontrols/qquickmenubar/data/invaliddelegate.qml
new file mode 100644
index 0000000000..4a6272bc47
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenubar/data/invaliddelegate.qml
@@ -0,0 +1,40 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ id: root
+
+ width: 400
+ height: 400
+ visible: true
+
+ menuBar: MenuBar {
+ delegate: Item { /* unsupported since it's not a MenuBarItem */ }
+ Menu {
+ id: fileMenu
+ title: "&File"
+ MenuItem { text: "&Open..." }
+ MenuItem { text: "&Save" }
+ MenuItem { text: "Save &As..." }
+ MenuSeparator { }
+ MenuItem { text: "&Quit" }
+ }
+
+ Menu {
+ title: "&Edit"
+ MenuItem { text: "&Cut" }
+ MenuItem { text: "&Copy" }
+ MenuItem { text: "&Paste" }
+ }
+
+ MenuBarItem {
+ menu: Menu {
+ title: "&Help"
+ MenuItem { text: "&About" }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenubar/data/menubarAsHeader.qml b/tests/auto/quickcontrols/qquickmenubar/data/menubarAsHeader.qml
new file mode 100644
index 0000000000..3261ca4b59
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenubar/data/menubarAsHeader.qml
@@ -0,0 +1,64 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ id: root
+ property bool menuBarVisible: true
+ property alias fileMenu: fileMenu
+ property alias contents: contents
+
+ width: 400
+ height: 400
+ visible: true
+
+ header: MenuBar {
+ visible: root.menuBarVisible
+ Menu {
+ id: fileMenu
+ title: "&File"
+ MenuItem { text: "&Open..." }
+ MenuItem { text: "&Save" }
+ MenuItem { text: "Save &As..." }
+ MenuSeparator { }
+ MenuItem { text: "&Quit" }
+ }
+ Menu {
+ title: "&Edit"
+ MenuItem { text: "&Cut" }
+ MenuItem { text: "&Copy" }
+ MenuItem { text: "&Paste" }
+ }
+ Menu {
+ title: "&View"
+ Menu {
+ title: "&Alignment"
+ Menu {
+ title: "&Horizontal"
+ MenuItem { text: "&Left" }
+ MenuItem { text: "&Center" }
+ MenuItem { text: "&Right" }
+ }
+ Menu {
+ title: "&Vertical"
+ MenuItem { text: "&Top" }
+ MenuItem { text: "&Center" }
+ MenuItem { text: "&Bottom" }
+ }
+ }
+ }
+
+ Menu {
+ title: "&Help"
+ MenuItem { text: "&About" }
+ }
+ }
+
+ Rectangle {
+ id: contents
+ anchors.fill: parent
+ color: "green"
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenubar/data/menubar.qml b/tests/auto/quickcontrols/qquickmenubar/data/menubaritems.qml
index 9edb7606ba..d7b628afea 100644
--- a/tests/auto/quickcontrols/qquickmenubar/data/menubar.qml
+++ b/tests/auto/quickcontrols/qquickmenubar/data/menubaritems.qml
@@ -1,20 +1,24 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
ApplicationWindow {
+ id: root
readonly property Button oopsButton: oopsButton
+ property alias fileMenu: fileMenu
width: 400
height: 400
visible: true
- header: MenuBar {
+ menuBar: MenuBar {
MenuBarItem {
menu: Menu {
+ id: fileMenu
title: "&File"
+ objectName: title
MenuItem { text: "&Open..." }
MenuItem { text: "&Save" }
MenuItem { text: "Save &As..." }
@@ -25,6 +29,7 @@ ApplicationWindow {
MenuBarItem {
menu: Menu {
title: "&Edit"
+ objectName: title
MenuItem { text: "&Cut" }
MenuItem { text: "&Copy" }
MenuItem { text: "&Paste" }
@@ -35,14 +40,17 @@ ApplicationWindow {
title: "&View"
Menu {
title: "&Alignment"
+ objectName: title
Menu {
title: "&Horizontal"
+ objectName: title
MenuItem { text: "&Left" }
MenuItem { text: "&Center" }
MenuItem { text: "&Right" }
}
Menu {
title: "&Vertical"
+ objectName: title
MenuItem { text: "&Top" }
MenuItem { text: "&Center" }
MenuItem { text: "&Bottom" }
@@ -54,6 +62,7 @@ ApplicationWindow {
MenuBarItem {
menu: Menu {
title: "&Help"
+ objectName: title
MenuItem { text: "&About" }
}
}
diff --git a/tests/auto/quickcontrols/qquickmenubar/data/menus.qml b/tests/auto/quickcontrols/qquickmenubar/data/menus.qml
new file mode 100644
index 0000000000..947beb50fb
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenubar/data/menus.qml
@@ -0,0 +1,85 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ id: root
+ property bool menuBarVisible: true
+ property alias fileMenu: fileMenu
+ property alias contents: contents
+
+ width: 400
+ height: 400
+ visible: true
+
+ menuBar: MenuBar {
+ visible: root.menuBarVisible
+ Menu {
+ id: fileMenu
+ title: "&File"
+ MenuItem { text: "&Open..." }
+ MenuItem { text: "&Save" }
+ MenuItem { text: "Save &As..." }
+ MenuSeparator { }
+ MenuItem { text: "&Quit" }
+ }
+ Menu {
+ title: "&Edit"
+ MenuItem { text: "&Cut" }
+ MenuItem { text: "&Copy" }
+ MenuItem { text: "&Paste" }
+ }
+ Menu {
+ title: "&View"
+ Menu {
+ title: "&Alignment"
+ Menu {
+ title: "&Horizontal"
+ MenuItem { text: "&Left" }
+ MenuItem { text: "&Center" }
+ MenuItem { text: "&Right" }
+ }
+ Menu {
+ title: "&Vertical"
+ MenuItem { text: "&Top" }
+ MenuItem { text: "&Center" }
+ MenuItem { text: "&Bottom" }
+ }
+ }
+ }
+
+ Menu {
+ title: "&Help"
+ MenuItem { text: "&About" }
+ }
+ }
+
+ Rectangle {
+ id: contents
+ anchors.fill: parent
+ color: "green"
+ }
+
+ Text {
+ // dummy binding to test that fileMenu will be kept alive
+ // after a call to menuBar.removeMenu(fileMenu) followed
+ // by running the garbage collector.
+ text: fileMenu.title
+ }
+
+ Component {
+ id: menuComp
+ Menu {
+ objectName: "Extra"
+ title: "extra"
+ }
+ }
+
+ function addTestMenu()
+ {
+ let menu = menuComp.createObject(null)
+ menuBar.addMenu(menu)
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenubar/data/mixed.qml b/tests/auto/quickcontrols/qquickmenubar/data/mixed.qml
new file mode 100644
index 0000000000..25dbf01e15
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenubar/data/mixed.qml
@@ -0,0 +1,55 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ id: root
+ property bool menuBarVisible: true
+ property alias fileMenu: fileMenu
+ property alias contents: contents
+
+ width: 400
+ height: 400
+ visible: true
+
+ menuBar: MenuBar {
+ visible: root.menuBarVisible
+ Menu {
+ id: fileMenu
+ title: "&File"
+ MenuItem { text: "&Open..." }
+ MenuItem { text: "&Save" }
+ MenuItem { text: "Save &As..." }
+ MenuSeparator { }
+ MenuItem { text: "&Quit" }
+ }
+
+ Rectangle {
+ color: "red"
+ width: 100
+ height: 20
+ }
+
+ Menu {
+ title: "&Edit"
+ MenuItem { text: "&Cut" }
+ MenuItem { text: "&Copy" }
+ MenuItem { text: "&Paste" }
+ }
+
+ MenuBarItem {
+ menu: Menu {
+ title: "&Help"
+ MenuItem { text: "&About" }
+ }
+ }
+ }
+
+ Rectangle {
+ id: contents
+ anchors.fill: parent
+ color: "green"
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenubar/data/nodelegate.qml b/tests/auto/quickcontrols/qquickmenubar/data/nodelegate.qml
new file mode 100644
index 0000000000..552aea8400
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenubar/data/nodelegate.qml
@@ -0,0 +1,40 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ id: root
+
+ width: 400
+ height: 400
+ visible: true
+
+ menuBar: MenuBar {
+ delegate: null
+ Menu {
+ id: fileMenu
+ title: "&File"
+ MenuItem { text: "&Open..." }
+ MenuItem { text: "&Save" }
+ MenuItem { text: "Save &As..." }
+ MenuSeparator { }
+ MenuItem { text: "&Quit" }
+ }
+
+ Menu {
+ title: "&Edit"
+ MenuItem { text: "&Cut" }
+ MenuItem { text: "&Copy" }
+ MenuItem { text: "&Paste" }
+ }
+
+ MenuBarItem {
+ menu: Menu {
+ title: "&Help"
+ MenuItem { text: "&About" }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenubar/data/showandhide.qml b/tests/auto/quickcontrols/qquickmenubar/data/showandhide.qml
new file mode 100644
index 0000000000..fe887c3f99
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenubar/data/showandhide.qml
@@ -0,0 +1,40 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ id: root
+
+ width: 400
+ height: 400
+ visible: true
+
+ menuBar: MenuBar {
+ Menu {
+ title: "Menu1"
+ Action { text: qsTr("Action") }
+ }
+
+ Menu {
+ title: "Menu2"
+ Action { text: qsTr("Action") }
+ }
+
+ MenuBarItem {
+ menu: Menu {
+ title: "Menu3"
+ Action { text: qsTr("Action") }
+ }
+ }
+
+ MenuBarItem {
+ visible: false
+ menu: Menu {
+ title: "Menu4"
+ Action { text: qsTr("Action") }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenubar/data/touch.qml b/tests/auto/quickcontrols/qquickmenubar/data/touch.qml
new file mode 100644
index 0000000000..5d54553307
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenubar/data/touch.qml
@@ -0,0 +1,20 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ header: MenuBar {
+ Menu {
+ title: "&File"
+
+ MenuItem {
+ text: "&Open..."
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp b/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp
index 95006ba77c..d56a48f2a7 100644
--- a/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp
+++ b/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtGui/qpa/qplatformintegration.h>
#include <QtGui/qpa/qplatformtheme.h>
@@ -11,12 +11,16 @@
#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
#include <QtQuickTemplates2/private/qquickbutton_p.h>
#include <QtQuickTemplates2/private/qquickmenu_p.h>
+#include <QtQuickTemplates2/private/qquickmenu_p_p.h>
#include <QtQuickTemplates2/private/qquickmenubar_p.h>
+#include <QtQuickTemplates2/private/qquickmenubar_p_p.h>
#include <QtQuickTemplates2/private/qquickmenubaritem_p.h>
#include <QtQuickTemplates2/private/qquickmenuitem_p.h>
+#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
#include <QtQuickControlsTestUtils/private/qtest_quickcontrols_p.h>
using namespace QQuickVisualTestUtils;
+using namespace QQuickControlsTestUtils;
class tst_qquickmenubar : public QQmlDataTest
{
@@ -26,26 +30,75 @@ public:
tst_qquickmenubar();
private slots:
+ void init() override;
void delegate();
+ void mouse_data();
void mouse();
+ void touch();
+ void keys_data();
void keys();
void mnemonics();
void altNavigation();
+ void addRemove_data();
void addRemove();
+ void addRemoveInlineMenus_data();
+ void addRemoveInlineMenus();
+ void addRemoveMenuFromQml_data();
+ void addRemoveMenuFromQml();
+ void insert_data();
+ void insert();
+ void showAndHideMenuBarItems_data();
+ void showAndHideMenuBarItems();
+ void removeMenuThatIsOpen();
+ void addRemoveExistingMenus_data();
+ void addRemoveExistingMenus();
+ void checkHighlightWhenMenuDismissed_data();
void checkHighlightWhenMenuDismissed();
+ void hoverAfterClosingWithEscape_data();
+ void hoverAfterClosingWithEscape();
+ void AA_DontUseNativeMenuBar();
+ void containerItems_data();
+ void containerItems();
+ void mixedContainerItems_data();
+ void mixedContainerItems();
+ void applicationWindow_data();
+ void applicationWindow();
+ void menubarAsHeader_data();
+ void menubarAsHeader();
+ void menuPosition();
+ void changeDelegate_data();
+ void changeDelegate();
+ void invalidDelegate_data();
+ void invalidDelegate();
+ void panMenuBar_data();
+ void panMenuBar();
private:
- static bool hasWindowActivation();
+ bool nativeMenuBarSupported = false;
+ bool popupWindowsSupported = false;
+ QScopedPointer<QPointingDevice> touchScreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
};
+QPoint itemSceneCenter(const QQuickItem *item)
+{
+ return item->mapToScene(QPointF(item->width() / 2, item->height() / 2)).toPoint();
+}
+
tst_qquickmenubar::tst_qquickmenubar()
: QQmlDataTest(QT_QMLTEST_DATADIR)
{
+ qputenv("QML_NO_TOUCH_COMPRESSION", "1");
+ QQuickMenuBar mb;
+ nativeMenuBarSupported = QQuickMenuBarPrivate::get(&mb)->useNativeMenuBar();
+ popupWindowsSupported = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::Capability::MultipleWindows);
}
-bool tst_qquickmenubar::hasWindowActivation()
+void tst_qquickmenubar::init()
{
- return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation));
+ // Enable non-native menubars by default.
+ // Note that some tests will set this property to 'true', which
+ // is why we need to set it back to 'false' here.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, false);
}
void tst_qquickmenubar::delegate()
@@ -61,16 +114,27 @@ void tst_qquickmenubar::delegate()
QVERIFY(item);
}
+void tst_qquickmenubar::mouse_data()
+{
+ QTest::addColumn<bool>("usePopupWindow");
+ QTest::newRow("in-scene popup") << false;
+ // Uncomment when popup windows work 100%
+ // if (popupWindowsSupported)
+ // QTest::newRow("popup window") << true;
+}
+
void tst_qquickmenubar::mouse()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
+
+ SKIP_IF_NO_WINDOW_ACTIVATION
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
QSKIP("Mouse highlight not functional on offscreen/minimal platforms");
- QQmlApplicationEngine engine(testFileUrl("menubar.qml"));
+ QQmlApplicationEngine engine(testFileUrl("menubaritems.qml"));
QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
QVERIFY(window);
@@ -79,7 +143,7 @@ void tst_qquickmenubar::mouse()
moveMouseAway(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QQuickMenuBar *menuBar = window->property("header").value<QQuickMenuBar *>();
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
QVERIFY(menuBar);
QQuickMenu *fileMenuBarMenu = menuBar->menuAt(0);
@@ -95,7 +159,7 @@ void tst_qquickmenubar::mouse()
QVERIFY(fileMenuBarItem && editMenuBarItem && viewMenuBarItem && helpMenuBarItem);
// highlight a menubar item
- QTest::mouseMove(window.data(), fileMenuBarItem->mapToScene(QPointF(fileMenuBarItem->width() / 2, fileMenuBarItem->height() / 2)).toPoint());
+ QTest::mouseMove(window.data(), itemSceneCenter(fileMenuBarItem));
#ifndef Q_OS_ANDROID
// Android theme does not use hover effects, so moving the mouse would not
// highlight an item
@@ -104,7 +168,7 @@ void tst_qquickmenubar::mouse()
QVERIFY(!fileMenuBarMenu->isVisible());
// highlight another menubar item
- QTest::mouseMove(window.data(), editMenuBarItem->mapToScene(QPointF(editMenuBarItem->width() / 2, editMenuBarItem->height() / 2)).toPoint());
+ QTest::mouseMove(window.data(), itemSceneCenter(editMenuBarItem));
#ifndef Q_OS_ANDROID
// Android theme does not use hover effects, so moving the mouse would not
// highlight an item
@@ -114,26 +178,28 @@ void tst_qquickmenubar::mouse()
QVERIFY(!fileMenuBarMenu->isVisible());
QVERIFY(!editMenuBarMenu->isVisible());
- // trigger a menubar item to open a menu
- QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, editMenuBarItem->mapToScene(QPointF(editMenuBarItem->width() / 2, editMenuBarItem->height() / 2)).toPoint());
+ // trigger a menubar item to open a menu - it should open on press
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, itemSceneCenter(editMenuBarItem));
QVERIFY(editMenuBarItem->isHighlighted());
QVERIFY(editMenuBarMenu->isVisible());
QTRY_VERIFY(editMenuBarMenu->isOpened());
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, itemSceneCenter(editMenuBarItem));
- // re-trigger a menubar item to hide the menu
- QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, editMenuBarItem->mapToScene(QPointF(editMenuBarItem->width() / 2, editMenuBarItem->height() / 2)).toPoint());
+ // re-trigger a menubar item to hide the menu - it should close on press
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, itemSceneCenter(editMenuBarItem));
QVERIFY(editMenuBarItem->isHighlighted());
QVERIFY(editMenuBarItem->hasActiveFocus());
QTRY_VERIFY(!editMenuBarMenu->isVisible());
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, itemSceneCenter(editMenuBarItem));
// re-trigger a menubar item to show the menu again
- QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, editMenuBarItem->mapToScene(QPointF(editMenuBarItem->width() / 2, editMenuBarItem->height() / 2)).toPoint());
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, itemSceneCenter(editMenuBarItem));
QVERIFY(editMenuBarItem->isHighlighted());
QVERIFY(editMenuBarMenu->isVisible());
QTRY_VERIFY(editMenuBarMenu->isOpened());
// highlight another menubar item to open another menu
- QTest::mouseMove(window.data(), helpMenuBarItem->mapToScene(QPointF(helpMenuBarItem->width() / 2, helpMenuBarItem->height() / 2)).toPoint());
+ QTest::mouseMove(window.data(), itemSceneCenter(helpMenuBarItem));
#ifdef Q_OS_ANDROID
// Android theme does not use hover effects, so moving the mouse would not
// highlight an item. Add a mouse click to change menubar item selection.
@@ -159,7 +225,7 @@ void tst_qquickmenubar::mouse()
QTRY_VERIFY(!helpMenuBarMenu->isVisible());
// highlight a menubar item
- QTest::mouseMove(window.data(), editMenuBarItem->mapToScene(QPointF(editMenuBarItem->width() / 2, editMenuBarItem->height() / 2)).toPoint());
+ QTest::mouseMove(window.data(), itemSceneCenter(editMenuBarItem));
#ifndef Q_OS_ANDROID
// Android theme does not use hover effects, so moving the mouse would not
// highlight an item
@@ -170,7 +236,7 @@ void tst_qquickmenubar::mouse()
QVERIFY(!helpMenuBarMenu->isVisible());
// trigger a menubar item to open a menu
- QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, viewMenuBarItem->mapToScene(QPointF(viewMenuBarItem->width() / 2, viewMenuBarItem->height() / 2)).toPoint());
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, itemSceneCenter(viewMenuBarItem));
QVERIFY(!editMenuBarItem->isHighlighted());
QVERIFY(viewMenuBarItem->isHighlighted());
QVERIFY(viewMenuBarMenu->isVisible());
@@ -181,7 +247,7 @@ void tst_qquickmenubar::mouse()
QVERIFY(alignmentSubMenuItem);
QQuickMenu *alignmentSubMenu = alignmentSubMenuItem->subMenu();
QVERIFY(alignmentSubMenu);
- QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, alignmentSubMenuItem->mapToScene(QPointF(alignmentSubMenuItem->width() / 2, alignmentSubMenuItem->height() / 2)).toPoint());
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, itemSceneCenter(alignmentSubMenuItem));
#if !defined(Q_OS_ANDROID) and !defined(Q_OS_WEBOS)
// The screen on Android is too small to fit the whole hierarchy, so the
// Alignment sub-menu is shown on top of View menu.
@@ -196,7 +262,7 @@ void tst_qquickmenubar::mouse()
QVERIFY(verticalSubMenuItem);
QQuickMenu *verticalSubMenu = verticalSubMenuItem->subMenu();
QVERIFY(verticalSubMenu);
- QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, verticalSubMenuItem->mapToScene(QPointF(verticalSubMenuItem->width() / 2, verticalSubMenuItem->height() / 2)).toPoint());
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, itemSceneCenter(verticalSubMenuItem));
#if !defined(Q_OS_ANDROID) and !defined(Q_OS_WEBOS)
// The screen on Android is too small to fit the whole hierarchy, so the
// Vertical sub-menu is shown on top of View menu and Alignment sub-menu.
@@ -210,7 +276,7 @@ void tst_qquickmenubar::mouse()
// trigger a menu item to close the whole chain of menus
QQuickMenuItem *centerMenuItem = qobject_cast<QQuickMenuItem *>(verticalSubMenu->itemAt(1));
QVERIFY(centerMenuItem);
- QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, centerMenuItem->mapToScene(QPointF(centerMenuItem->width() / 2, centerMenuItem->height() / 2)).toPoint());
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, itemSceneCenter(centerMenuItem));
QVERIFY(!viewMenuBarItem->isHighlighted());
QTRY_VERIFY(!viewMenuBarMenu->isVisible());
QTRY_VERIFY(!alignmentSubMenu->isVisible());
@@ -225,11 +291,11 @@ void tst_qquickmenubar::mouse()
#endif
// re-open the chain of menus
- QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, viewMenuBarItem->mapToScene(QPointF(viewMenuBarItem->width() / 2, viewMenuBarItem->height() / 2)).toPoint());
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, itemSceneCenter(viewMenuBarItem));
QTRY_VERIFY(viewMenuBarMenu->isOpened());
- QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, alignmentSubMenuItem->mapToScene(QPointF(alignmentSubMenuItem->width() / 2, alignmentSubMenuItem->height() / 2)).toPoint());
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, itemSceneCenter(alignmentSubMenuItem));
QTRY_VERIFY(alignmentSubMenu->isOpened());
- QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, verticalSubMenuItem->mapToScene(QPointF(verticalSubMenuItem->width() / 2, verticalSubMenuItem->height() / 2)).toPoint());
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, itemSceneCenter(verticalSubMenuItem));
QTRY_VERIFY(verticalSubMenu->isOpened());
// click outside to close the whole chain of menus
@@ -240,12 +306,56 @@ void tst_qquickmenubar::mouse()
QTRY_VERIFY(!verticalSubMenu->isVisible());
}
+// Not sure how relevant MenuBar is for touch, but this test is here to make
+// sure that only release events cause the menu to open, as:
+// - That is how it has always behaved, so maintain that behavior.
+// - It's what happens with e.g. overflow menus on Android.
+void tst_qquickmenubar::touch()
+{
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
+ QQuickControlsApplicationHelper helper(this, QLatin1String("touch.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ centerOnScreen(helper.window);
+ helper.window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(helper.window));
+
+ QQuickMenuBar *menuBar = helper.window->property("header").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+
+ QQuickMenu *fileMenuBarMenu = menuBar->menuAt(0);
+ QVERIFY(fileMenuBarMenu);
+
+ QQuickMenuBarItem *fileMenuBarItem = qobject_cast<QQuickMenuBarItem *>(fileMenuBarMenu->parentItem());
+ QVERIFY(fileMenuBarItem);
+
+ // Trigger a menubar item to open a menu - it should only open on release.
+ QTest::touchEvent(helper.window, touchScreen.data()).press(0, itemSceneCenter(fileMenuBarItem));
+ QVERIFY(!fileMenuBarItem->isHighlighted());
+ QVERIFY(!fileMenuBarMenu->isVisible());
+ QTest::touchEvent(helper.window, touchScreen.data()).release(0, itemSceneCenter(fileMenuBarItem));
+ QVERIFY(fileMenuBarItem->isHighlighted());
+ QVERIFY(fileMenuBarMenu->isVisible());
+ QTRY_VERIFY(fileMenuBarMenu->isOpened());
+}
+
+void tst_qquickmenubar::keys_data()
+{
+ QTest::addColumn<bool>("usePopupWindow");
+ QTest::newRow("in-scene popup") << false;
+ // Uncomment when popup windows work 100%
+ // if (popupWindowsSupported)
+ // QTest::newRow("popup window") << true;
+}
+
void tst_qquickmenubar::keys()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
+
+ SKIP_IF_NO_WINDOW_ACTIVATION
- QQmlApplicationEngine engine(testFileUrl("menubar.qml"));
+ QQmlApplicationEngine engine(testFileUrl("menubaritems.qml"));
QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
QVERIFY(window);
@@ -254,7 +364,7 @@ void tst_qquickmenubar::keys()
moveMouseAway(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QQuickMenuBar *menuBar = window->property("header").value<QQuickMenuBar *>();
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
QVERIFY(menuBar);
QQuickMenu *fileMenuBarMenu = menuBar->menuAt(0);
@@ -434,14 +544,16 @@ void tst_qquickmenubar::keys()
void tst_qquickmenubar::mnemonics()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
+
+ SKIP_IF_NO_WINDOW_ACTIVATION
#if defined(Q_OS_MACOS) or defined(Q_OS_WEBOS)
QSKIP("Mnemonics are not used on this platform");
#endif
- QQmlApplicationEngine engine(testFileUrl("menubar.qml"));
+ QQmlApplicationEngine engine(testFileUrl("menubaritems.qml"));
QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
QVERIFY(window);
@@ -452,7 +564,7 @@ void tst_qquickmenubar::mnemonics()
MnemonicKeySimulator keySim(window.data());
- QQuickMenuBar *menuBar = window->property("header").value<QQuickMenuBar *>();
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
QVERIFY(menuBar);
QQuickMenu *fileMenuBarMenu = menuBar->menuAt(0);
@@ -587,10 +699,12 @@ void tst_qquickmenubar::mnemonics()
void tst_qquickmenubar::altNavigation()
{
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
if (!QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::MenuBarFocusOnAltPressRelease).toBool())
QSKIP("Menu doesn't get focus via Alt press&release on this platform");
- QQmlApplicationEngine engine(testFileUrl("menubar.qml"));
+ QQmlApplicationEngine engine(testFileUrl("menubaritems.qml"));
QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
QVERIFY(window);
@@ -599,7 +713,7 @@ void tst_qquickmenubar::altNavigation()
moveMouseAway(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QQuickMenuBar *menuBar = window->property("header").value<QQuickMenuBar *>();
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
QVERIFY(menuBar);
QQuickMenu *fileMenuBarMenu = menuBar->menuAt(0);
@@ -624,12 +738,30 @@ void tst_qquickmenubar::altNavigation()
QVERIFY(editMenuBarMenu->hasActiveFocus());
}
+void tst_qquickmenubar::addRemove_data()
+{
+ QTest::addColumn<QString>("testUrl");
+ QTest::addColumn<bool>("native");
+ QTest::newRow("menuitems, not native") << QStringLiteral("empty.qml") << false;
+ if (nativeMenuBarSupported)
+ QTest::newRow("menuitems, native") << QStringLiteral("empty.qml") << true;
+}
+
void tst_qquickmenubar::addRemove()
{
- QQmlApplicationEngine engine(testFileUrl("empty.qml"));
+ QFETCH(QString, testUrl);
+ QFETCH(bool, native);
- QScopedPointer<QQuickMenuBar> menuBar(qobject_cast<QQuickMenuBar *>(engine.rootObjects().value(0)));
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native);
+ QQmlApplicationEngine engine;
+ engine.load(testFileUrl(testUrl));
+
+ QQuickMenuBar *menuBar = qobject_cast<QQuickMenuBar *>(engine.rootObjects().value(0));
QVERIFY(menuBar);
+ QQuickMenuBarPrivate *menuBarPrivate = QQuickMenuBarPrivate::get(menuBar);
+ QCOMPARE(menuBarPrivate->useNativeMenuBar(), native);
+ if (native)
+ QVERIFY(menuBarPrivate->nativeHandle());
QQmlComponent component(&engine);
component.setData("import QtQuick.Controls; Menu { }", QUrl());
@@ -645,7 +777,7 @@ void tst_qquickmenubar::addRemove()
QCOMPARE(menuBarItem1->menu(), menu1.data());
QCOMPARE(menuBar->itemAt(0), menuBarItem1.data());
- QScopedPointer<QQuickMenu> menu2(qobject_cast<QQuickMenu *>(component.create()));
+ QPointer<QQuickMenu> menu2(qobject_cast<QQuickMenu *>(component.create()));
QVERIFY(!menu2.isNull());
menuBar->insertMenu(0, menu2.data());
QCOMPARE(menuBar->count(), 2);
@@ -658,15 +790,26 @@ void tst_qquickmenubar::addRemove()
QCOMPARE(menuBar->itemAt(0), menuBarItem2.data());
QCOMPARE(menuBar->itemAt(1), menuBarItem1.data());
- // takeMenu(int) does not destroy the menu, but does destroy the respective item in the menubar
+ // takeMenu(int) does not explicitly destroy the menu, but leave
+ // this to the garbage collector. The MenuBarItem, OTOH, is currently
+ // being destroyed from c++, but this might change in the future.
QCOMPARE(menuBar->takeMenu(1), menu1.data());
QCOMPARE(menuBar->count(), 1);
QVERIFY(!menuBar->menuAt(1));
QVERIFY(!menuBar->itemAt(1));
- QCoreApplication::sendPostedEvents(menu1.data(), QEvent::DeferredDelete);
+ QTRY_VERIFY(menuBarItem1.isNull());
+ QVERIFY(!menu1.isNull());
+ gc(engine);
QVERIFY(!menu1.isNull());
- QCoreApplication::sendPostedEvents(menuBarItem1, QEvent::DeferredDelete);
- QVERIFY(menuBarItem1.isNull());
+
+ // check that it's safe to call takeMenu(int) with
+ // an index that is out of range.
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*out of range"));
+ QCOMPARE(menuBar->takeMenu(-1), nullptr);
+ QCOMPARE(menuBar->count(), 1);
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*out of range"));
+ QCOMPARE(menuBar->takeMenu(10), nullptr);
+ QCOMPARE(menuBar->count(), 1);
// addMenu(Menu) re-creates the respective item in the menubar
menuBar->addMenu(menu1.data());
@@ -674,18 +817,295 @@ void tst_qquickmenubar::addRemove()
menuBarItem1 = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(1));
QVERIFY(!menuBarItem1.isNull());
- // removeMenu(Menu) destroys both the menu and the respective item in the menubar
+ // removeMenu(menu) does not explicitly destroy the menu, but leave
+ // this to the garbage collector. The MenuBarItem, OTOH, is currently
+ // being destroyed from c++, but this might change in the future.
menuBar->removeMenu(menu1.data());
QCOMPARE(menuBar->count(), 1);
QVERIFY(!menuBar->itemAt(1));
- QCoreApplication::sendPostedEvents(menu1.data(), QEvent::DeferredDelete);
- QVERIFY(menu1.isNull());
- QCoreApplication::sendPostedEvents(menuBarItem1, QEvent::DeferredDelete);
- QVERIFY(menuBarItem1.isNull());
+ QTRY_VERIFY(menuBarItem1.isNull());
+ QVERIFY(!menu1.isNull());
+ gc(engine);
+ QVERIFY(!menu1.isNull());
+}
+
+void tst_qquickmenubar::addRemoveInlineMenus_data()
+{
+ QTest::addColumn<bool>("native");
+ QTest::newRow("not native") << false;
+ if (nativeMenuBarSupported)
+ QTest::newRow("native") << true;
+}
+
+void tst_qquickmenubar::addRemoveInlineMenus()
+{
+ // Check that it's safe to remove a menu from the menubar, that
+ // is an inline child from QML (fileMenu). Since it's owned by
+ // JavaScript, it should be deleted by the gc when appropriate, and
+ // not upon a call to removeMenu.
+ QFETCH(bool, native);
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native);
+ QQmlApplicationEngine engine;
+ engine.load(testFileUrl("menus.qml"));
+
+ auto window = qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0));
+ QVERIFY(window);
+ auto menuBar = window->property("menuBar").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+
+ QPointer<QQuickMenu> fileMenu = window->property("fileMenu").value<QQuickMenu *>();
+ QVERIFY(fileMenu);
+ QCOMPARE(menuBar->menuAt(0), fileMenu);
+
+ QPointer<QQuickItem> menuBarItem = menuBar->itemAt(0);
+ QVERIFY(menuBarItem);
+
+ menuBar->removeMenu(fileMenu);
+ QVERIFY(menuBar->menuAt(0) != fileMenu);
+ QTRY_VERIFY(!menuBarItem);
+ QVERIFY(fileMenu);
+ gc(engine);
+ QVERIFY(fileMenu);
+
+ // Add it back again, but to the end. This should also be fine, even
+ // if it no longer matches the initial order in the QML file.
+ menuBar->addMenu(fileMenu);
+ QVERIFY(fileMenu);
+ QCOMPARE(menuBar->menuAt(menuBar->count() - 1), fileMenu);
+}
+
+void tst_qquickmenubar::addRemoveMenuFromQml_data()
+{
+ QTest::addColumn<bool>("native");
+ QTest::newRow("not native") << false;
+ if (nativeMenuBarSupported)
+ QTest::newRow("native") << true;
+}
+
+void tst_qquickmenubar::addRemoveMenuFromQml()
+{
+ // Create a menu dynamically from QML, and add it to
+ // the menubar. Remove it again. Check that the
+ // garbage collector will then destruct it.
+ QFETCH(bool, native);
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native);
+ QQmlApplicationEngine engine;
+ engine.load(testFileUrl("menus.qml"));
+
+ auto window = qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0));
+ QVERIFY(window);
+ auto menuBar = window->property("menuBar").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+
+ const int initialMenuCount = menuBar->count();
+ QVERIFY(initialMenuCount > 0);
+
+ QMetaObject::invokeMethod(window, "addTestMenu");
+
+ QCOMPARE(menuBar->count(), initialMenuCount + 1);
+
+ // The "extra" menu should have been added to
+ // the end of the menu bar. Verify this.
+ QQuickItem *item = menuBar->itemAt(menuBar->count() - 1);
+ QPointer<QQuickMenuBarItem> menuBarItem = qobject_cast<QQuickMenuBarItem *>(item);
+ QVERIFY(menuBarItem);
+ QPointer<QQuickMenu> menu = menuBar->menuAt(menuBar->count() - 1);
+ QVERIFY(menu);
+ QCOMPARE(menu->title(), "extra");
+ QCOMPARE(menuBarItem->menu(), menu);
+
+ // Remove the menu again. Since we have no other references to
+ // it from QML, it should be collected by the gc.
+ menuBar->removeMenu(menu);
+ QCOMPARE(menuBar->count(), initialMenuCount);
+ QTRY_VERIFY(!menuBarItem);
+ QVERIFY(menu);
+ gc(engine);
+ QVERIFY(!menu);
+}
+
+void tst_qquickmenubar::insert_data()
+{
+ QTest::addColumn<bool>("native");
+ QTest::newRow("not native") << false;
+ if (nativeMenuBarSupported)
+ QTest::newRow("native") << true;
+}
+
+void tst_qquickmenubar::insert()
+{
+ QFETCH(bool, native);
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native);
+ QQmlApplicationEngine engine;
+ engine.load(testFileUrl("menus.qml"));
+
+ QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
+ QVERIFY(window);
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+
+ const int initialMenuCount = menuBar->count();
+ QVERIFY(initialMenuCount > 0);
+
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick.Controls; Menu { }", QUrl());
+
+ QPointer<QQuickMenu> menu1(qobject_cast<QQuickMenu *>(component.create()));
+ QVERIFY(!menu1.isNull());
+ menuBar->insertMenu(0, menu1.data());
+ QCOMPARE(menuBar->count(), initialMenuCount + 1);
+ QCOMPARE(menuBar->menuAt(0), menu1.data());
+
+ QPointer<QQuickMenu> menu2(qobject_cast<QQuickMenu *>(component.create()));
+ QVERIFY(!menu2.isNull());
+ menuBar->insertMenu(2, menu2.data());
+ QCOMPARE(menuBar->count(), initialMenuCount + 2);
+ QCOMPARE(menuBar->menuAt(2), menu2.data());
+}
+
+void tst_qquickmenubar::showAndHideMenuBarItems_data()
+{
+ QTest::addColumn<bool>("native");
+ QTest::newRow("not native") << false;
+ if (nativeMenuBarSupported)
+ QTest::newRow("native") << true;
+}
+
+void tst_qquickmenubar::showAndHideMenuBarItems()
+{
+ // Check that you can toggle MenuBarItem.visible to show and hide menus in the
+ // menu bar. Note that this is not the same as setting Menu.visible, which will
+ // instead open or close the menus.
+ QFETCH(bool, native);
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native);
+ QQmlApplicationEngine engine;
+ engine.load(testFileUrl("showandhide.qml"));
+
+ QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
+ QVERIFY(window);
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+ QCOMPARE(menuBar->count(), 4);
+
+ auto menuBarItem0 = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(0));
+ auto menuBarItem1 = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(1));
+ auto menuBarItem2 = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(2));
+ auto menuBarItem3 = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(3));
+
+ // Initially, the three first MenuBarItems are visible, but the 4th is hidden
+ QVERIFY(menuBarItem0->isVisible());
+ QVERIFY(menuBarItem1->isVisible());
+ QVERIFY(menuBarItem2->isVisible());
+ QVERIFY(!menuBarItem3->isVisible());
+
+ // Native and visible QQuickMenus should be backed by
+ // QPlatformMenus. Otherwise the handle should be nullptr.
+ QCOMPARE(bool(QQuickMenuPrivate::get(menuBarItem0->menu())->maybeNativeHandle()), native);
+ QCOMPARE(bool(QQuickMenuPrivate::get(menuBarItem1->menu())->maybeNativeHandle()), native);
+ QCOMPARE(bool(QQuickMenuPrivate::get(menuBarItem2->menu())->maybeNativeHandle()), native);
+ QVERIFY(!QQuickMenuPrivate::get(menuBarItem3->menu())->maybeNativeHandle());
+
+ // Make the hidden MenuBarItem visible
+ menuBarItem3->setVisible(true);
+ QCOMPARE(bool(QQuickMenuPrivate::get(menuBarItem3->menu())->maybeNativeHandle()), native);
+ QCOMPARE(menuBar->count(), 4);
+ // Hide it again
+ menuBarItem3->setVisible(false);
+ QVERIFY(!QQuickMenuPrivate::get(menuBarItem3->menu())->maybeNativeHandle());
+ QCOMPARE(menuBar->count(), 4);
+
+ // Toggle the visibility of a MenuBarItem created from the
+ // delegate, which is also initially visible.
+ menuBarItem0->setVisible(false);
+ QVERIFY(!QQuickMenuPrivate::get(menuBarItem0->menu())->maybeNativeHandle());
+ QCOMPARE(menuBar->count(), 4);
+ // Hide it again
+ menuBarItem0->setVisible(true);
+ QCOMPARE(bool(QQuickMenuPrivate::get(menuBarItem0->menu())->maybeNativeHandle()), native);
+ QCOMPARE(menuBar->count(), 4);
+}
+
+void tst_qquickmenubar::removeMenuThatIsOpen()
+{
+ // Check that if we remove a menu that is open, it ends
+ // up being hidden / closed. This is mostly important for
+ // non-native menubars.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
+ QQmlApplicationEngine engine;
+ engine.load(testFileUrl("menus.qml"));
+
+ QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
+ QVERIFY(window);
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+
+ QQuickMenu *fileMenu = window->property("fileMenu").value<QQuickMenu *>();
+ QVERIFY(fileMenu);
+ fileMenu->open();
+ QVERIFY(fileMenu->isVisible());
+ menuBar->removeMenu(fileMenu);
+ QVERIFY(fileMenu);
+ QTRY_VERIFY(!fileMenu->isVisible());
+}
+
+void tst_qquickmenubar::addRemoveExistingMenus_data()
+{
+ QTest::addColumn<bool>("native");
+ QTest::addColumn<bool>("usePopupWindow");
+ QTest::newRow("non-native, in-scene") << false << false;
+ if (nativeMenuBarSupported)
+ QTest::newRow("native, native") << true << true;
+ // Uncomment when popup windows work 100%
+ // if (popupWindowsSupported)
+ // QTest::newRow("non-native, popup window") << false << true;
+}
+
+void tst_qquickmenubar::addRemoveExistingMenus()
+{
+ // Check that you get warnings if trying to add menus that
+ // are already in the menubar, or remove menus that are not.
+ QFETCH(bool, native);
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native);
+ QQmlApplicationEngine engine;
+ engine.load(testFileUrl("menus.qml"));
+
+ auto window = qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0));
+ QVERIFY(window);
+ auto menuBar = window->property("menuBar").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+
+ QPointer<QQuickMenu> fileMenu = window->property("fileMenu").value<QQuickMenu *>();
+ QVERIFY(fileMenu);
+ QCOMPARE(menuBar->menuAt(0), fileMenu);
+
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression("cannot add menu.*"));
+ menuBar->addMenu(fileMenu);
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression("cannot insert menu.*"));
+ menuBar->insertMenu(0, fileMenu);
+ menuBar->removeMenu(fileMenu);
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression("cannot remove menu.*"));
+ menuBar->removeMenu(fileMenu);
+}
+
+void tst_qquickmenubar::checkHighlightWhenMenuDismissed_data()
+{
+ QTest::addColumn<bool>("usePopupWindow");
+ QTest::newRow("in-scene popup") << false;
+ // Uncomment when popup windows work 100%
+ // if (popupWindowsSupported)
+ // QTest::newRow("popup window") << true;
}
void tst_qquickmenubar::checkHighlightWhenMenuDismissed()
{
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
QSKIP("Mouse highlight not functional on offscreen/minimal platforms");
@@ -713,32 +1133,599 @@ void tst_qquickmenubar::checkHighlightWhenMenuDismissed()
QPointF(staticMenuBarItem->width() / 2, staticMenuBarItem->height() / 2)).toPoint());
QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier,
staticMenuBarItem->mapToScene(QPointF(staticMenuBarItem->width() / 2, staticMenuBarItem->height() / 2)).toPoint());
- QCOMPARE(staticMenuBarItem->isHighlighted(), true);
- QCOMPARE(staticMenu->isVisible(), true);
- QTRY_COMPARE(staticMenu->isOpened(), true);
-
+ QVERIFY(staticMenuBarItem->isHighlighted());
+ QVERIFY(staticMenu->isVisible());
+ QTRY_VERIFY(staticMenu->isOpened());
// click a menu item to dismiss the menu and unhighlight the static MenuBarItem
QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(staticMenu->itemAt(0));
QVERIFY(menuItem);
QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier,
menuItem->mapToScene(QPointF(menuItem->width() / 2, menuItem->height() / 2)).toPoint());
- QCOMPARE(staticMenuBarItem->isHighlighted(), false);
+ QVERIFY(!staticMenuBarItem->isHighlighted());
+ // wait for the menu to be fully gone so that it doesn't interfere with the next test
+ QTRY_VERIFY(!staticMenu->isVisible());
// highlight the dynamic MenuBarItem and open the menu
QTest::mouseMove(window.data(), dynamicMenuBarItem->mapToScene(
QPointF(dynamicMenuBarItem->width() / 2, dynamicMenuBarItem->height() / 2)).toPoint());
QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier,
dynamicMenuBarItem->mapToScene(QPointF(dynamicMenuBarItem->width() / 2, dynamicMenuBarItem->height() / 2)).toPoint());
- QCOMPARE(dynamicMenuBarItem->isHighlighted(), true);
- QCOMPARE(dynamicMenu->isVisible(), true);
- QTRY_COMPARE(dynamicMenu->isOpened(), true);
+ QVERIFY(dynamicMenuBarItem->isHighlighted());
+ QVERIFY(dynamicMenu->isVisible());
+ QTRY_VERIFY(dynamicMenu->isOpened());
// click a menu item to dismiss the menu and unhighlight the dynamic MenuBarItem
menuItem = qobject_cast<QQuickMenuItem *>(dynamicMenu->itemAt(0));
QVERIFY(menuItem);
QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier,
menuItem->mapToScene(QPointF(menuItem->width() / 2, menuItem->height() / 2)).toPoint());
- QCOMPARE(dynamicMenuBarItem->isHighlighted(), false);
+ QVERIFY(!dynamicMenuBarItem->isHighlighted());
+}
+
+void tst_qquickmenubar::hoverAfterClosingWithEscape_data()
+{
+ QTest::addColumn<bool>("usePopupWindow");
+ QTest::newRow("in-scene popup") << false;
+ // Uncomment when popup windows work 100%
+ // if (popupWindowsSupported)
+ // QTest::newRow("popup window") << true;
+}
+
+void tst_qquickmenubar::hoverAfterClosingWithEscape()
+{
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Mouse highlight not functional on offscreen/minimal platforms");
+
+ QQuickControlsApplicationHelper helper(this, QLatin1String("hoverAfterClosingWithEscape.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenuBar *menuBar = window->findChild<QQuickMenuBar *>("menuBar");
+ QVERIFY(menuBar);
+
+ // Open the first menu by clicking on the first menu bar item.
+ auto *firstMenuBarItem(qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(0)));
+ QVERIFY(clickButton(firstMenuBarItem));
+ QQuickMenu *firstMenu = menuBar->menuAt(0);
+ QVERIFY(firstMenu);
+ QTRY_VERIFY(firstMenu->isOpened());
+
+ // Close it with the escape key.
+ QTest::keyClick(window, Qt::Key_Escape);
+ QTRY_VERIFY(!firstMenu->isVisible());
+
+ // Hover over the second menu bar item; it shouldn't cause its menu to open.
+ auto *secondMenuBarItem(qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(1)));
+ QTest::mouseMove(window, mapCenterToWindow(secondMenuBarItem));
+ QQuickMenu *secondMenu = menuBar->menuAt(1);
+ QVERIFY(secondMenu);
+ QVERIFY(!secondMenu->isVisible());
+}
+
+void tst_qquickmenubar::AA_DontUseNativeMenuBar()
+{
+ // Check that we end up with a non-native menu bar when AA_DontUseNativeMenuBar is set.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
+ QQmlApplicationEngine engine;
+ engine.load(testFileUrl("menus.qml"));
+
+ QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
+ QVERIFY(window);
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+ auto menuBarPrivate = QQuickMenuBarPrivate::get(menuBar);
+ QQuickItem *contents = window->property("contents").value<QQuickItem *>();
+ QVERIFY(contents);
+
+ QVERIFY(!menuBarPrivate->nativeHandle());
+ QVERIFY(menuBar->isVisible());
+ QVERIFY(menuBar->count() > 0);
+ QVERIFY(menuBar->height() > 0);
+ QCOMPARE(contents->height(), window->height() - menuBar->height());
+
+ // If the menu bar is not native, the menus should not be native either.
+ // The main reason for this limitation is that a native menu typically
+ // run in separate native event loop which will not forward mouse events
+ // to Qt. And this is needed for a non-native menu bar to work (e.g to
+ // support hovering over the menu bar items to open and close menus).
+ const auto firstMenu = menuBar->menuAt(0);
+ QVERIFY(firstMenu);
+ QVERIFY(!QQuickMenuPrivate::get(firstMenu)->maybeNativeHandle());
+}
+
+void tst_qquickmenubar::containerItems_data()
+{
+ QTest::addColumn<QString>("testUrl");
+ QTest::addColumn<bool>("native");
+ QTest::newRow("menuitems, not native") << QStringLiteral("menubaritems.qml") << false;
+ QTest::newRow("menus, not native") << QStringLiteral("menus.qml") << false;
+ if (nativeMenuBarSupported) {
+ QTest::newRow("menuitems, native") << QStringLiteral("menubaritems.qml") << true;
+ QTest::newRow("menus, native") << QStringLiteral("menus.qml") << true;
+ }
+}
+
+void tst_qquickmenubar::containerItems()
+{
+ // Check that the MenuBar ends up containing a MenuBarItem
+ // for each Menu added. This should be the case regardless of
+ // if the MenuBar is native or not. There are several ways
+ // of accessing those MenuBarItems and menus in the MenuBar
+ // API, so check that all end up in sync.
+ QFETCH(QString, testUrl);
+ QFETCH(bool, native);
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native);
+ QQmlApplicationEngine engine;
+ engine.load(testFileUrl(testUrl));
+
+ QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
+ QVERIFY(window);
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+ auto *menuBarPrivate = QQuickMenuBarPrivate::get(menuBar);
+ QCOMPARE(menuBarPrivate->useNativeMenuBar(), native);
+
+ QCOMPARE(menuBar->count(), 4);
+ for (int i = 0; i < menuBar->count(); ++i) {
+ QQuickMenu *menu = menuBar->menuAt(i);
+ QVERIFY(menu);
+
+ // Test the itemAt() API
+ QQuickItem *item = menuBar->itemAt(i);
+ QVERIFY(item);
+ auto menuBarItem = qobject_cast<QQuickMenuBarItem *>(item);
+ QVERIFY(menuBarItem);
+ QCOMPARE(menuBarItem->menu(), menu);
+
+ // Test the "contentData" list property API
+ auto cd = menuBarPrivate->contentData();
+ QCOMPARE(cd.count(&cd), menuBar->count());
+ auto cdItem = static_cast<QQuickItem *>(cd.at(&cd, i));
+ QVERIFY(cdItem);
+ auto cdMenuBarItem = qobject_cast<QQuickMenuBarItem *>(cdItem);
+ QVERIFY(cdMenuBarItem);
+ QCOMPARE(cdMenuBarItem->menu(), menu);
+
+ // Test the "menus" list property API
+ auto menus = QQuickMenuBarPrivate::get(menuBar)->menus();
+ QCOMPARE(menus.count(&menus), menuBar->count());
+ auto menusMenu = menus.at(&menus, i);
+ QVERIFY(menusMenu);
+ QCOMPARE(menusMenu, menu);
+ }
+}
+
+void tst_qquickmenubar::mixedContainerItems_data()
+{
+ QTest::addColumn<bool>("native");
+ QTest::newRow("not native") << false;
+ if (nativeMenuBarSupported)
+ QTest::newRow("native") << true;
+}
+
+void tst_qquickmenubar::mixedContainerItems()
+{
+ // The application is allowed to add items other
+ // than MenuBarItems and Menus as children. But those
+ // should just be ignored by the MenuBar (and the Container).
+ QFETCH(bool, native);
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native);
+ QQmlApplicationEngine engine;
+ engine.load(testFileUrl("mixed.qml"));
+
+ QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
+ QVERIFY(window);
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+
+ // The menubar has four children, but only three of them are
+ // Menus and MenuBarItems. So we should therefore only end up
+ // with three menus in the MenuBar, and three items in the Container.
+ QCOMPARE(menuBar->count(), 3);
+ for (int i = 0; i < 3; ++i) {
+ auto item = menuBar->itemAt(i);
+ QVERIFY(item);
+ auto menuBarItem = qobject_cast<QQuickMenuBarItem *>(item);
+ QVERIFY(menuBarItem);
+ QCOMPARE(menuBarItem->menu(), menuBar->menuAt(i));
+ }
+
+ // Try to add an unsupported item dynamically. It should
+ // have no impact on the MenuBar/Container API.
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick; Item { }", QUrl());
+ QPointer<QQuickItem> plainItem(qobject_cast<QQuickItem *>(component.create()));
+ QVERIFY(plainItem);
+
+ menuBar->addItem(plainItem);
+ QCOMPARE(menuBar->count(), 3);
+ for (int i = 0; i < 3; ++i) {
+ auto item = menuBar->itemAt(i);
+ QVERIFY(item);
+ auto menuBarItem = qobject_cast<QQuickMenuBarItem *>(item);
+ QVERIFY(menuBarItem);
+ QCOMPARE(menuBarItem->menu(), menuBar->menuAt(i));
+ }
+
+ // Remove it again. It should have no impact on
+ // the MenuBar/Container API.
+ menuBar->removeItem(plainItem);
+ QCOMPARE(menuBar->count(), 3);
+ for (int i = 0; i < 3; ++i) {
+ auto item = menuBar->itemAt(i);
+ QVERIFY(item);
+ auto menuBarItem = qobject_cast<QQuickMenuBarItem *>(item);
+ QVERIFY(menuBarItem);
+ QCOMPARE(menuBarItem->menu(), menuBar->menuAt(i));
+ }
+}
+
+void tst_qquickmenubar::applicationWindow_data()
+{
+ QTest::addColumn<bool>("initiallyNative");
+ QTest::addColumn<bool>("initiallyVisible");
+ QTest::newRow("initially not native, visible") << false << true;
+ QTest::newRow("initially not native, hidden") << false << false;
+ if (nativeMenuBarSupported) {
+ QTest::newRow("initially native, visible") << true << true;
+ QTest::newRow("initially native, hidden") << true << false;
+ }
+}
+
+void tst_qquickmenubar::applicationWindow()
+{
+ // Check that ApplicationWindow adds or removes the non-native
+ // menubar in response to toggling Qt::AA_DontUseNativeMenuBar and
+ // MenuBar.visible.
+ QFETCH(bool, initiallyNative);
+ QFETCH(bool, initiallyVisible);
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !initiallyNative);
+ QQmlApplicationEngine engine;
+ engine.setInitialProperties({{ "visible", initiallyVisible }});
+ engine.load(testFileUrl("menus.qml"));
+
+ QPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
+ QVERIFY(window);
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+ auto menuBarPrivate = QQuickMenuBarPrivate::get(menuBar);
+ QQuickItem *contents = window->property("contents").value<QQuickItem *>();
+ QVERIFY(contents);
+
+ for (const bool visible : {initiallyVisible, !initiallyVisible, initiallyVisible}) {
+ menuBar->setVisible(visible);
+
+ const bool nativeMenuBarVisible = bool(menuBarPrivate->nativeHandle());
+ QCOMPARE(nativeMenuBarVisible, initiallyNative && visible);
+
+ if (!visible) {
+ QVERIFY(!menuBar->isVisible());
+ QVERIFY(!nativeMenuBarVisible);
+ QCOMPARE(contents->height(), window->height());
+ } else if (nativeMenuBarVisible) {
+ QVERIFY(menuBar->isVisible());
+ QCOMPARE(contents->height(), window->height());
+ } else {
+ QVERIFY(menuBar->isVisible());
+ QVERIFY(menuBar->height() > 0);
+ QCOMPARE(contents->height(), window->height() - menuBar->height());
+ }
+ }
+}
+
+void tst_qquickmenubar::menubarAsHeader_data()
+{
+ QTest::addColumn<bool>("native");
+ QTest::newRow("not native") << false;
+ if (nativeMenuBarSupported)
+ QTest::newRow("native") << true;
+}
+
+void tst_qquickmenubar::menubarAsHeader()
+{
+ // ApplicationWindow.menuBar was added in Qt 5.10. Before that
+ // the menuBar was supposed to be assigned to ApplicationWindow.header.
+ // For backwards compatibility, check that you can still do that.
+ QFETCH(bool, native);
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native);
+ QQmlApplicationEngine engine;
+ engine.load(testFileUrl("menubarAsHeader.qml"));
+
+ QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
+ QVERIFY(window);
+ QQuickMenuBar *menuBar = window->property("header").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+ auto menuBarPrivate = QQuickMenuBarPrivate::get(menuBar);
+ QQuickItem *contents = window->property("contents").value<QQuickItem *>();
+ QVERIFY(contents);
+ QVERIFY(menuBar->count() > 0);
+ QCOMPARE(menuBarPrivate->nativeHandle() != nullptr, native);
+
+ if (menuBarPrivate->nativeHandle()) {
+ // Using native menubar
+ QCOMPARE(contents->height(), window->height());
+ } else {
+ // Not using native menubar
+ QCOMPARE(contents->height(), window->height() - menuBar->height());
+ }
+}
+
+void tst_qquickmenubar::menuPosition()
+{
+ // A Menu.qml will typically have a background with a drop-shadow. And to make
+ // room for this shadow, the Menu itself is made bigger by using Control.insets.
+ // This will make room for both the background and its shadow.
+ // To make sure that the corner of the background (rather than the shadow) ends up
+ // at the requested menu position, the effective position of the menu will be
+ // shifted a bit up and left. This test will therefore check that the corner of the
+ // background ends up that the requested position.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, true);
+ // Use in-scene popups for this test, since we have no guarantee where a window
+ // manager might end up placing a menu.
+ QQmlApplicationEngine engine;
+ engine.load(testFileUrl("menus.qml"));
+
+ QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
+ QVERIFY(window);
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+
+ QPointF requestedPos{50, 50};
+
+ QQuickMenu *editMenu = menuBar->menuAt(1);
+ QVERIFY(editMenu);
+ editMenu->setX(requestedPos.x());
+ editMenu->setY(requestedPos.y());
+ editMenu->setVisible(true);
+ QTRY_VERIFY(editMenu->isOpened());
+ QCOMPARE(editMenu->x(), requestedPos.x());
+ QCOMPARE(editMenu->y(), requestedPos.y());
+
+ QQuickItem *background = editMenu->background();
+ QVERIFY(background);
+
+ QPointF bgPos = background->mapToItem(editMenu->parentItem(), {0, 0});
+ QCOMPARE(bgPos, requestedPos);
+}
+
+void tst_qquickmenubar::changeDelegate_data()
+{
+ QTest::addColumn<bool>("native");
+ QTest::newRow("not native") << false;
+ if (nativeMenuBarSupported)
+ QTest::newRow("native") << true;
+}
+
+void tst_qquickmenubar::changeDelegate()
+{
+ // Check that you can change the delegate, and that this
+ // will produce new delegate items, except for the MenuBarItem
+ // that is created inline in the QML code, and hence doesn't use the delegate.
+ QFETCH(bool, native);
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native);
+ QQmlApplicationEngine engine;
+ engine.load(testFileUrl("nodelegate.qml"));
+
+ QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
+ QVERIFY(window);
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+ QCOMPARE(menuBar->count(), 3);
+
+ QQmlComponent delegate1(&engine);
+ delegate1.setData("import QtQuick.Controls; MenuBarItem {}", QUrl());
+ menuBar->setDelegate(&delegate1);
+
+ auto menuBarItem0_v1 = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(0));
+ auto menuBarItem1_v1 = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(1));
+ auto menuBarItem2_v1 = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(2));
+ QVERIFY(menuBarItem0_v1);
+ QVERIFY(menuBarItem1_v1);
+ QVERIFY(menuBarItem2_v1);
+ QVERIFY(menuBarItem0_v1->isVisible());
+ QVERIFY(menuBarItem1_v1->isVisible());
+ QVERIFY(menuBarItem2_v1->isVisible());
+ QVERIFY(menuBarItem0_v1->menu());
+ QVERIFY(menuBarItem1_v1->menu());
+ QVERIFY(menuBarItem2_v1->menu());
+ QCOMPARE(menuBar->menuAt(0), menuBarItem0_v1->menu());
+ QCOMPARE(menuBar->menuAt(1), menuBarItem1_v1->menu());
+ QCOMPARE(menuBar->menuAt(2), menuBarItem2_v1->menu());
+
+ // Change the delegate
+ QQmlComponent delegate2(&engine);
+ delegate2.setData("import QtQuick.Controls; MenuBarItem {}", QUrl());
+ menuBar->setDelegate(&delegate2);
+
+ auto menuBarItem0_v2 = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(0));
+ auto menuBarItem1_v2 = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(1));
+ auto menuBarItem2_v2 = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(2));
+ QVERIFY(menuBarItem0_v2);
+ QVERIFY(menuBarItem1_v2);
+ QVERIFY(menuBarItem2_v2);
+
+ // The delegate items should now have changed, except for
+ // menuBarItem2, which is not created from the delegate.
+ QVERIFY(menuBarItem0_v2 != menuBarItem0_v1);
+ QVERIFY(menuBarItem1_v2 != menuBarItem1_v1);
+ QCOMPARE(menuBarItem2_v2, menuBarItem2_v1);
+
+ QVERIFY(menuBarItem0_v2->isVisible());
+ QVERIFY(menuBarItem1_v2->isVisible());
+ QVERIFY(menuBarItem2_v2->isVisible());
+ QVERIFY(menuBarItem0_v2->menu());
+ QVERIFY(menuBarItem1_v2->menu());
+ QVERIFY(menuBarItem2_v2->menu());
+ QCOMPARE(menuBar->menuAt(0), menuBarItem0_v2->menu());
+ QCOMPARE(menuBar->menuAt(1), menuBarItem1_v2->menu());
+ QCOMPARE(menuBar->menuAt(2), menuBarItem2_v2->menu());
+}
+
+void tst_qquickmenubar::invalidDelegate_data()
+{
+ QTest::addColumn<bool>("native");
+ QTest::addColumn<bool>("useInvalidDelegate");
+ QTest::newRow("not native, no delegate") << false << false;
+ QTest::newRow("not native, invalid delegate") << false << true;
+ if (nativeMenuBarSupported) {
+ QTest::newRow("native, no delegate") << true << false;
+ QTest::newRow("native, invalid delegate") << true << true;
+ }
+}
+
+void tst_qquickmenubar::invalidDelegate()
+{
+ // Check that QQuickMenuBar can handle a delegate that is either null, or not a
+ // MenuBarItem. The former won't produce any warnings, but the latter should.
+ // In either case, this will not produce visible menus in the menu bar, except
+ // for the menus that are wrapped inside inline MenuBarItems, and therefore
+ // not using the delegate.
+ // To ensure that we still bookkeep the menus for the failing delegates, in case
+ // the delegate changes later, and that functions such as menuAt(index) continues
+ // to work, hidden placeholder MenuBarItems will be used instead.
+ QFETCH(bool, native);
+ QFETCH(bool, useInvalidDelegate);
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native);
+ QQmlApplicationEngine engine;
+
+ if (useInvalidDelegate) {
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression("cannot insert menu.*"));
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression("cannot insert menu.*"));
+ }
+
+ if (useInvalidDelegate)
+ engine.load(testFileUrl("invaliddelegate.qml"));
+ else
+ engine.load(testFileUrl("nodelegate.qml"));
+
+ QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
+ QVERIFY(window);
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+ QCOMPARE(menuBar->count(), 3);
+
+ // Menu 2 is an inline MenuBarItem, and is unaffected by the delegate
+ auto inlineMenuBarItem = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(2));
+
+ for (int i = 0; i <= 2; ++i) {
+ auto menuBarItem = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(i));
+ QVERIFY(menuBarItem);
+ auto menu = menuBarItem->menu();
+ QVERIFY(menu);
+ QCOMPARE(menu, menuBar->menuAt(i));
+ if (menuBarItem == inlineMenuBarItem) {
+ QVERIFY(menuBarItem->isVisible());
+ QCOMPARE(bool(QQuickMenuPrivate::get(menu)->maybeNativeHandle()), native);
+ } else {
+ // Menus created from the invalid delegate should be hidden. They should also
+ // not have a native handle, since they should not be in a native menu bar.
+ QVERIFY(!menuBarItem->isVisible());
+ QVERIFY(!bool(QQuickMenuPrivate::get(menu)->maybeNativeHandle()));
+ }
+ }
+
+ // Add a new menu. This one should also be inserted into a placeholder MenuBarItem
+ if (useInvalidDelegate)
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression("cannot insert menu.*"));
+
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick.Controls; Menu { }", QUrl());
+ auto menu = qobject_cast<QQuickMenu *>(component.create());
+ QVERIFY(menu);
+
+ menuBar->addMenu(menu);
+ QCOMPARE(menuBar->count(), 4);
+ auto menuBarItem3 = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(3));
+ QVERIFY(menuBarItem3);
+ QVERIFY(!menuBarItem3->isVisible());
+ QCOMPARE(menuBar->menuAt(3), menu);
+ QCOMPARE(menuBar->menuAt(3), menuBarItem3->menu());
+ QVERIFY(!QQuickMenuPrivate::get(menu)->maybeNativeHandle());
+
+ // Finally, set a valid delegate. This will make all MenuBarItems visible.
+ QQmlComponent delegate(&engine);
+ delegate.setData("import QtQuick.Controls; MenuBarItem { }", QUrl());
+ menuBar->setDelegate(&delegate);
+
+ for (int i = 0; i <= 3; ++i) {
+ auto menuBarItem = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(i));
+ QVERIFY(menuBarItem);
+ QVERIFY(menuBarItem->isVisible());
+ auto menu = menuBarItem->menu();
+ QVERIFY(menu);
+ QCOMPARE(menu, menuBar->menuAt(i));
+ QCOMPARE(bool(QQuickMenuPrivate::get(menu)->maybeNativeHandle()), native);
+ }
+
+ // inlineMenuBarItem was not created from a delegate, and shouldn't change
+ QCOMPARE(qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(2)), inlineMenuBarItem);
+}
+
+void tst_qquickmenubar::panMenuBar_data()
+{
+ QTest::addColumn<bool>("usePopupWindow");
+ QTest::newRow("in-scene popup") << false;
+ // Uncomment when popup windows work 100%
+ // if (popupWindowsSupported)
+ // QTest::newRow("popup window") << true;
+}
+
+void tst_qquickmenubar::panMenuBar()
+{
+ // Check that a MenuBarItem's menu opens when you click it. And then check that
+ // if you hover the next MenuBarItem in the MenuBar, that the first one will
+ // close, and the second one will open.
+
+#if !defined(Q_OS_MACOS) || !defined(Q_OS_WINDOWS)
+ QSKIP("This test doesn't pass on e.g QNX. It needs more investigation before it can be enabled");
+#endif
+
+#ifdef Q_OS_ANDROID
+ // Android theme does not use hover effects, so moving the mouse would not
+ // highlight an item
+ QSKIP("Panning of MenuBar not supported");
+#endif
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, true);
+ QQmlApplicationEngine engine;
+ engine.load(testFileUrl("menus.qml"));
+
+ QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)));
+ QVERIFY(window);
+ QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>();
+ QVERIFY(menuBar);
+ QQuickMenuBarPrivate *menuBar_d = QQuickMenuBarPrivate::get(menuBar);
+
+ auto menuBarItem0 = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(0));
+ auto menuBarItem1 = qobject_cast<QQuickMenuBarItem *>(menuBar->itemAt(1));
+ QVERIFY(menuBarItem0);
+ QVERIFY(menuBarItem1);
+
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, itemSceneCenter(menuBarItem0));
+ QVERIFY(menuBarItem0->isHighlighted());
+ QVERIFY(!menuBarItem1->isHighlighted());
+ QCOMPARE(menuBar_d->currentItem, menuBarItem0);
+ QVERIFY(menuBar_d->currentMenuOpen);
+ QTRY_VERIFY(menuBarItem0->menu()->isOpened());
+
+ QTest::mouseMove(window.data(), itemSceneCenter(menuBarItem1));
+ QVERIFY(!menuBarItem0->isHighlighted());
+ QVERIFY(menuBarItem1->isHighlighted());
+ QCOMPARE(menuBar_d->currentItem, menuBarItem1);
+ QVERIFY(menuBar_d->currentMenuOpen);
+ QTRY_VERIFY(menuBarItem1->menu()->isOpened());
+ QTRY_VERIFY(!menuBarItem0->menu()->isOpened());
}
QTEST_QUICKCONTROLS_MAIN(tst_qquickmenubar)
diff --git a/tests/auto/quickcontrols/qquickninepatchimage/CMakeLists.txt b/tests/auto/quickcontrols/qquickninepatchimage/CMakeLists.txt
index 0523912506..003bdd7725 100644
--- a/tests/auto/quickcontrols/qquickninepatchimage/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickninepatchimage/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickninepatchimage LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
@@ -16,11 +16,7 @@ endif()
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}/data/*.qml)
-list(APPEND test_data ${test_data_glob})
-file(GLOB_RECURSE test_data_glob
- RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}/data/*.png)
+ ${CMAKE_CURRENT_SOURCE_DIR}/data/*)
list(APPEND test_data ${test_data_glob})
qt_internal_add_test(tst_qquickninepatchimage
diff --git a/tests/auto/quickcontrols/qquickninepatchimage/data/logo.pkm b/tests/auto/quickcontrols/qquickninepatchimage/data/logo.pkm
new file mode 100644
index 0000000000..c0987c5c36
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickninepatchimage/data/logo.pkm
Binary files differ
diff --git a/tests/auto/quickcontrols/qquickninepatchimage/data/o1_bc1.ktx b/tests/auto/quickcontrols/qquickninepatchimage/data/o1_bc1.ktx
new file mode 100644
index 0000000000..d61194a745
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickninepatchimage/data/o1_bc1.ktx
Binary files differ
diff --git a/tests/auto/quickcontrols/qquickninepatchimage/data/qt4.astc b/tests/auto/quickcontrols/qquickninepatchimage/data/qt4.astc
new file mode 100644
index 0000000000..7f7a3f4739
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickninepatchimage/data/qt4.astc
Binary files differ
diff --git a/tests/auto/quickcontrols/qquickninepatchimage/tst_qquickninepatchimage.cpp b/tests/auto/quickcontrols/qquickninepatchimage/tst_qquickninepatchimage.cpp
index c1fb1f7264..7e0e974f23 100644
--- a/tests/auto/quickcontrols/qquickninepatchimage/tst_qquickninepatchimage.cpp
+++ b/tests/auto/quickcontrols/qquickninepatchimage/tst_qquickninepatchimage.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtTest/qsignalspy.h>
@@ -11,8 +11,10 @@
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitemgrabresult.h>
#include <QtQuick/private/qquickimage_p.h>
+#include <QtQuick/private/qquickimage_p_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
+#include <QtGui/private/qrhi_p.h>
using namespace QQuickVisualTestUtils;
@@ -32,6 +34,8 @@ private slots:
void inset();
void implicitSize_data();
void implicitSize();
+ void hwCompressedImages_data();
+ void hwCompressedImages();
};
static QImage grabItemToImage(QQuickItem *item)
@@ -91,20 +95,25 @@ void tst_qquickninepatchimage::ninePatch()
// Generate an image to compare against the actual 9-patch image.
QImage generatedImage(size * dpr, ninePatchImageGrab.format());
+ generatedImage.setDevicePixelRatio(dpr);
generatedImage.fill(Qt::red);
QImage blueRect(4 * dpr, 4 * dpr, ninePatchImageGrab.format());
+ blueRect.setDevicePixelRatio(dpr);
blueRect.fill(Qt::blue);
+ const QSizeF generatedPaintedSize = generatedImage.deviceIndependentSize();
+ const QSizeF blueRectPaintedSize = blueRect.deviceIndependentSize();
+
QPainter painter(&generatedImage);
// Top-left
painter.drawImage(0, 0, blueRect);
// Top-right
- painter.drawImage(generatedImage.width() - blueRect.width(), 0, blueRect);
+ painter.drawImage(generatedPaintedSize.width() - blueRectPaintedSize.width(), 0, blueRect);
// Bottom-right
- painter.drawImage(generatedImage.width() - blueRect.width(), generatedImage.height() - blueRect.height(), blueRect);
+ painter.drawImage(generatedPaintedSize.width() - blueRectPaintedSize.width(), generatedPaintedSize.height() - blueRectPaintedSize.height(), blueRect);
// Bottom-left
- painter.drawImage(0, generatedImage.height() - blueRect.height(), blueRect);
+ painter.drawImage(0, generatedPaintedSize.height() - blueRectPaintedSize.height(), blueRect);
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
@@ -230,6 +239,61 @@ void tst_qquickninepatchimage::implicitSize()
QCOMPARE(ninePatchImage->implicitHeight(), implicitSize.height());
}
+void tst_qquickninepatchimage::hwCompressedImages_data()
+{
+ QTest::addColumn<int>("dpr");
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QRhiTexture::Format>("format");
+
+ const struct TestFile {
+ QString name;
+ QSize size;
+ QRhiTexture::Format format;
+ } testFiles [] = {
+ { "o1_bc1.ktx", QSize(64, 64), QRhiTexture::BC1 },
+ { "logo.pkm", QSize(256, 256), QRhiTexture::ETC2_RGB8 },
+ { "qt4.astc", QSize(250, 200), QRhiTexture::ASTC_8x8 }
+ };
+
+ for (const TestFile &file : testFiles) {
+ for (int dpr = 1; dpr <= 4; ++dpr)
+ QTest::newRow(qPrintable(QString::fromLatin1("%1 DPR=%2").arg(file.name).arg(dpr))) << dpr << file.name << file.size << file.format;
+ }
+}
+
+void tst_qquickninepatchimage::hwCompressedImages()
+{
+ QFETCH(int, dpr);
+ QFETCH(QString, file);
+ QFETCH(QSize, size);
+ QFETCH(QRhiTexture::Format, format);
+
+ QHighDpiScaling::setGlobalFactor(dpr);
+
+ QQuickView view(testFileUrl("ninepatchimage.qml"));
+ QCOMPARE(view.status(), QQuickView::Ready);
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ if (!QSGRendererInterface::isApiRhiBased(view.rendererInterface()->graphicsApi()))
+ QSKIP("Skipping due to using software backend");
+
+ QRhi *rhi = static_cast<QRhi *>(view.rendererInterface()->getResource(&view, QSGRendererInterface::RhiResource));
+ if (!rhi->isTextureFormatSupported(format))
+ QSKIP(qPrintable(QString::fromLatin1("%1 not supported, skip").arg(format)));
+
+ QQuickImage *ninePatchImage = qobject_cast<QQuickImage *>(view.rootObject());
+ QVERIFY(ninePatchImage);
+ ninePatchImage->setSource(testFileUrl(file));
+ ninePatchImage->setSize(size);
+ QSignalSpy spy(&view, SIGNAL(afterSynchronizing()));
+ QTRY_VERIFY(spy.size() >= 1);
+
+ QQuickImagePrivate *ninePatchImagePrivate = static_cast<QQuickImagePrivate *>(QQuickItemPrivate::get(ninePatchImage));
+ QVERIFY(ninePatchImagePrivate->paintNode);
+}
+
QTEST_MAIN(tst_qquickninepatchimage)
#include "tst_qquickninepatchimage.moc"
diff --git a/tests/auto/quickcontrols/qquickoverlay/CMakeLists.txt b/tests/auto/quickcontrols/qquickoverlay/CMakeLists.txt
new file mode 100644
index 0000000000..e5d9da4dc9
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickoverlay/CMakeLists.txt
@@ -0,0 +1,43 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpopup LANGUAGES C CXX ASM)
+ find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+endif()
+
+#####################################################################
+## tst_qquickoverlay Test:
+#####################################################################
+
+file(GLOB_RECURSE test_data_glob
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ data/*)
+list(APPEND test_data ${test_data_glob})
+
+qt_internal_add_test(tst_qquickoverlay
+ SOURCES
+ tst_qquickoverlay.cpp
+ DEFINES
+ QQC2_IMPORT_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/quickcontrols"
+ LIBRARIES
+ Qt::Core
+ Qt::Gui
+ Qt::Quick
+ Qt::QuickPrivate
+ Qt::QuickTemplates2
+ Qt::QuickTemplates2Private
+ Qt::TestPrivate
+ TESTDATA ${test_data}
+)
+
+qt_internal_extend_target(tst_qquickoverlay CONDITION ANDROID OR IOS
+ DEFINES
+ QT_QMLTEST_DATADIR=":/data"
+)
+
+qt_internal_extend_target(tst_qquickoverlay CONDITION NOT ANDROID AND NOT IOS
+ DEFINES
+ QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+)
diff --git a/tests/auto/quickcontrols/qquickoverlay/tst_qquickoverlay.cpp b/tests/auto/quickcontrols/qquickoverlay/tst_qquickoverlay.cpp
new file mode 100644
index 0000000000..a2ab819a7a
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickoverlay/tst_qquickoverlay.cpp
@@ -0,0 +1,223 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtTest/qtest.h>
+#include <QtTest/qsignalspy.h>
+
+#include <QtQuick/qquickwindow.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/private/qquickpointerdevicehandler_p.h>
+#include <QtQuickTemplates2/private/qquickoverlay_p.h>
+
+class tst_QQuickOverlay : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QQuickOverlay();
+
+private slots:
+ void clearGrabbers();
+ void retainOrientation();
+};
+
+class TestInputHandler : public QQuickPointerDeviceHandler
+{
+public:
+ TestInputHandler(QQuickItem * parent)
+ : QQuickPointerDeviceHandler(parent)
+ {
+ setGrabPermissions(GrabPermission::TakeOverForbidden);
+ }
+
+ bool wantsPointerEvent(QPointerEvent * event) override
+ {
+ return QQuickPointerDeviceHandler::wantsPointerEvent(event)
+ && !eligiblePoints(event).isEmpty();
+ }
+
+ bool wantsEventPoint(const QPointerEvent * event, const QEventPoint & point) override
+ {
+ bool ret = QQuickPointerDeviceHandler::wantsEventPoint(event, point);
+ return ret || (ret && event->exclusiveGrabber(point) != this);
+ }
+
+ bool grabPoints(QPointerEvent * event, const QVector<QEventPoint> & points)
+ {
+ if (points.isEmpty())
+ return false;
+
+ bool allowed = true;
+
+ for (const auto & point : points) {
+ if (event->exclusiveGrabber(point) != this && !canGrab(event, point)) {
+ allowed = false;
+ break;
+ }
+ }
+
+ if (allowed) {
+ for (auto point : points) {
+ if (event->exclusiveGrabber(point) != this)
+ event->setExclusiveGrabber(point, this);
+ point.setAccepted(true);
+ }
+ }
+
+ return allowed;
+ }
+
+ bool grabEligiblePoints(QPointerEvent * event)
+ {
+ return grabPoints(event, eligiblePoints(event));
+ }
+
+ QList<QEventPoint> eligiblePoints(QPointerEvent * event)
+ {
+ QList<QEventPoint> ret;
+
+ // elligible points should return all points which either
+ // 1. have no owner
+ // 2. are owned by us
+ // 3. we can steal
+
+ for (int i = 0; i < event->pointCount(); ++i) {
+ auto p = event->point(i);
+ auto * exclusiveGrabber = event->exclusiveGrabber(p);
+
+ if (exclusiveGrabber && exclusiveGrabber != this && !canGrab(event, p))
+ continue;
+
+ if (p.state() != QEventPoint::Released && wantsEventPoint(event, p))
+ ret << p;
+ }
+
+ return ret;
+ }
+
+ void handlePointerEventImpl(QPointerEvent * event) override
+ {
+ QQuickPointerDeviceHandler::handlePointerEventImpl(event);
+ auto grabbed = grabEligiblePoints(event);
+
+ if (!active()) {
+ setActive(grabbed);
+ return;
+ }
+
+ for (int i = 0; i < event->pointCount(); ++i) {
+ auto point = event->point(i);
+
+ if (event->exclusiveGrabber(point) == this)
+ Q_ASSERT(m_points.contains(point.id()));
+ }
+ }
+
+ void onGrabChanged(QQuickPointerHandler * grabber,
+ QPointingDevice::GrabTransition transition,
+ QPointerEvent * event,
+ QEventPoint & point) override
+ {
+ if (grabber == this) {
+ switch (transition) {
+ case QPointingDevice::GrabTransition::GrabExclusive:
+ Q_ASSERT(!m_points.contains(point.id()));
+ m_points.append(point.id());
+ break;
+
+ case QPointingDevice::GrabTransition::UngrabExclusive:
+ case QPointingDevice::GrabTransition::CancelGrabExclusive:
+ if (m_points.contains(point.id()))
+ m_points.removeOne(point.id());
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ QQuickPointerDeviceHandler::onGrabChanged(grabber, transition, event, point);
+ }
+
+ QList<int> m_points;
+};
+
+tst_QQuickOverlay::tst_QQuickOverlay() = default;
+
+void tst_QQuickOverlay::clearGrabbers()
+{
+ QQuickWindow window;
+
+ auto *overlay = QQuickOverlay::overlay(&window);
+ auto *overlayItem = new QQuickItem(overlay);
+ QVERIFY(overlayItem);
+
+ const auto size = QSize(640, 480);
+ window.resize(size);
+
+ auto *item = new QQuickItem(window.contentItem());
+ item->setSize(size);
+
+ auto testPointerhandler = TestInputHandler(item);
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ auto *dev = QTest::createTouchDevice();
+
+ QTest::touchEvent(&window, dev)
+ .press(0, QPoint(10, 10));
+
+ QCOMPARE(testPointerhandler.m_points.size(), 1);
+ QCOMPARE(testPointerhandler.m_points[0], 0);
+
+ QTest::touchEvent(&window, dev)
+ .stationary(0)
+ .press(1, QPoint(20, 20));
+
+ QCOMPARE(testPointerhandler.m_points.size(), 2);
+ QCOMPARE(testPointerhandler.m_points[0], 0);
+ QCOMPARE(testPointerhandler.m_points[1], 1);
+
+ QTest::touchEvent(&window, dev)
+ .move(0, QPoint(20, 20))
+ .move(1, QPoint(30, 30));
+
+ QCOMPARE(testPointerhandler.m_points.size(), 2);
+ QCOMPARE(testPointerhandler.m_points[0], 0);
+ QCOMPARE(testPointerhandler.m_points[1], 1);
+
+ QTest::touchEvent(&window, dev)
+ .release(0, QPoint(30, 30))
+ .stationary(1);
+
+ QCOMPARE(testPointerhandler.m_points.size(), 1);
+ QCOMPARE(testPointerhandler.m_points[0], 1);
+
+ QTest::touchEvent(&window, dev)
+ .release(1, QPoint(40, 40));
+
+ QVERIFY(testPointerhandler.m_points.isEmpty());
+}
+
+void tst_QQuickOverlay::retainOrientation()
+{
+ QQuickWindow window;
+ auto *overlay = QQuickOverlay::overlay(&window);
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ qreal rot = 10;
+ overlay->setRotation(rot);
+ const QSizeF sz = overlay->size();
+ window.resize(window.size() + QSize(10, 10));
+ // wait for the resize event to call QQuickOverlay::updateGeometry
+ QTRY_COMPARE_NE(overlay->size(), sz);
+
+ QCOMPARE(overlay->rotation(), rot);
+}
+
+QTEST_MAIN(tst_QQuickOverlay)
+
+#include "tst_qquickoverlay.moc"
diff --git a/tests/auto/quickcontrols/qquickpopup/BLACKLIST b/tests/auto/quickcontrols/qquickpopup/BLACKLIST
index aa31440328..3beb1d6cc7 100644
--- a/tests/auto/quickcontrols/qquickpopup/BLACKLIST
+++ b/tests/auto/quickcontrols/qquickpopup/BLACKLIST
@@ -1,5 +1,16 @@
# See qtbase/src/testlib/qtestblacklist.cpp for format
+# QTBUG-114718 (begin)
+[overlay]
+macos
+[invisibleToolTipOpen]
+macos
+[cursorShape]
+macos
+[doubleClickInMouseArea]
+macos
+# QTBUG-114718 (end)
+
[overlay]
macos # QTBUG-89938
@@ -12,3 +23,7 @@ opensuse-leap
[cursorShape]
opensuse-leap
+
+[popupWindowFocus]
+* # QTBUG-121363
+
diff --git a/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt b/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt
index 81eb78c906..3110e4d26b 100644
--- a/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickpopup LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterExit.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterExit.qml
index 359dc772f2..d918159f65 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterExit.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterExit.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterWindowInactive.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterWindowInactive.qml
new file mode 100644
index 0000000000..1d4dc87e41
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterWindowInactive.qml
@@ -0,0 +1,27 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias popup: popup
+ property alias button: button
+
+ Button {
+ id: button
+ text: "button"
+ focus: true
+ }
+
+ Popup {
+ id: popup
+ focus: true
+ width: 100
+ height: 100
+ anchors.centerIn: Overlay.overlay
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose1.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose1.qml
index 81893bbcbd..7cbc5f479a 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose1.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose1.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose2.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose2.qml
index 6cb1c5ad07..c1b60b7282 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose2.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose3.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose3.qml
index 89165e355e..0e1e2aa703 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose3.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose3.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClosingSeveralPopups.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClosingSeveralPopups.qml
index 3a85f7d580..5ed1c5988d 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClosingSeveralPopups.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClosingSeveralPopups.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnDelayedEnter.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnDelayedEnter.qml
index 37a595ec25..e4b7438d2a 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnDelayedEnter.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnDelayedEnter.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import QtQuick.Controls 2.12
diff --git a/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-hover.qml b/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-hover.qml
index d4c8b78355..f1acf42d2a 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-hover.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-hover.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
@@ -15,22 +15,24 @@ ApplicationWindow {
Button {
id: parentButton
text: "Parent"
+ palette.buttonText: hovered ? "tomato" : "black"
anchors.fill: parent
+ anchors.margins: 10
Popup {
id: popup
- x: 1
- y: 1
- leftPadding: 1
- rightPadding: 1
- topPadding: 1
- bottomPadding: 1
-
+ x: 10
+ y: 10
+ leftPadding: 10
+ rightPadding: 10
+ topPadding: 10
+ bottomPadding: 10
Button {
anchors.centerIn: parent
id: childButton
text: "Child"
+ palette.buttonText: hovered ? "tomato" : "black"
}
}
}
diff --git a/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-wheel.qml b/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-wheel.qml
index 1668b042e0..eb09d7eba3 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-wheel.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-wheel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickpopup/data/applicationwindow.qml b/tests/auto/quickcontrols/qquickpopup/data/applicationwindow.qml
index 46c4dda18b..7ab22ff8bd 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/applicationwindow.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/applicationwindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/centerInOverlayWithinStackViewItem.qml b/tests/auto/quickcontrols/qquickpopup/data/centerInOverlayWithinStackViewItem.qml
index 1c96bb687c..a0a76206da 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/centerInOverlayWithinStackViewItem.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/centerInOverlayWithinStackViewItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/closeOnEscapeWithNestedPopups.qml b/tests/auto/quickcontrols/qquickpopup/data/closeOnEscapeWithNestedPopups.qml
index 6aeede9aff..5533591ac4 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/closeOnEscapeWithNestedPopups.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/closeOnEscapeWithNestedPopups.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/countChanged.qml b/tests/auto/quickcontrols/qquickpopup/data/countChanged.qml
index e95be76e56..41f306781d 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/countChanged.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/countChanged.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickpopup/data/cursor.qml b/tests/auto/quickcontrols/qquickpopup/data/cursor.qml
index 3eefa7570e..6ea4e03dac 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/cursor.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/cursor.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/destroyDuringExitTransition.qml b/tests/auto/quickcontrols/qquickpopup/data/destroyDuringExitTransition.qml
index dacffd3199..5c34f22f60 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/destroyDuringExitTransition.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/destroyDuringExitTransition.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/dialog.qml b/tests/auto/quickcontrols/qquickpopup/data/dialog.qml
index 112bfaefcd..d28e540701 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/dialog.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/dialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickpopup/data/dimmerContainmentMask.qml b/tests/auto/quickcontrols/qquickpopup/data/dimmerContainmentMask.qml
index 30a412a1cc..5f7e9afc08 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/dimmerContainmentMask.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/dimmerContainmentMask.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/disabledPalette.qml b/tests/auto/quickcontrols/qquickpopup/data/disabledPalette.qml
index 4b54b5b1fd..2af92158dc 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/disabledPalette.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/disabledPalette.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/doubleClickInMouseArea.qml b/tests/auto/quickcontrols/qquickpopup/data/doubleClickInMouseArea.qml
new file mode 100644
index 0000000000..e43a2f3160
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickpopup/data/doubleClickInMouseArea.qml
@@ -0,0 +1,23 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Window
+
+Rectangle {
+ width: 200; height: 200
+ color: mouseArea.pressed ? "red" : "orange"
+
+ Popup {
+ visible: true
+ closePolicy: Popup.NoAutoClose
+ width: 100
+ height: 100
+ contentItem: MouseArea {
+ id: mouseArea
+
+ anchors.fill: parent
+ }
+ background: Rectangle {
+ color: "green"
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickpopup/data/fadeDimmer.qml b/tests/auto/quickcontrols/qquickpopup/data/fadeDimmer.qml
new file mode 100644
index 0000000000..d5edc11466
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickpopup/data/fadeDimmer.qml
@@ -0,0 +1,39 @@
+import QtQuick
+import QtQuick.Controls
+
+Window {
+ id: window
+
+ Text {text: "Hello"}
+ Popup {
+ id: popup
+ anchors.centerIn: parent
+ dim: true
+ property double dimmerOpacity: 0.5
+
+ Overlay.modeless: Rectangle {
+ color: "blue"
+ opacity: popup.dimmerOpacity
+
+ Behavior on opacity {
+ NumberAnimation { from: 0; to: popup.dimmerOpacity; duration: 250 }
+ }
+ }
+
+ Overlay.modal: Rectangle {
+ color: "blue"
+ opacity: popup.dimmerOpacity
+
+ Behavior on opacity {
+ NumberAnimation { from: 0; to: popup.dimmerOpacity; duration: 250 }
+ }
+ }
+
+ enter: Transition {
+ NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 250 }
+ }
+ exit: Transition {
+ NumberAnimation { property: "opacity"; from: 1; to: 0; duration: 250 }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickpopup/data/grabber.qml b/tests/auto/quickcontrols/qquickpopup/data/grabber.qml
index ec76829f4f..952212dc0b 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/grabber.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/grabber.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/mirroredCombobox.qml b/tests/auto/quickcontrols/qquickpopup/data/mirroredCombobox.qml
index ed48179bce..7449072e89 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/mirroredCombobox.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/mirroredCombobox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/modelessOnModalOnModeless.qml b/tests/auto/quickcontrols/qquickpopup/data/modelessOnModalOnModeless.qml
index 5da5a5524b..f1fe64e49a 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/modelessOnModalOnModeless.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/modelessOnModalOnModeless.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/multiplepopup.qml b/tests/auto/quickcontrols/qquickpopup/data/multiplepopup.qml
new file mode 100644
index 0000000000..395514546d
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickpopup/data/multiplepopup.qml
@@ -0,0 +1,82 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+Window {
+ id: window
+ width: 200
+ height: 200
+ visible: false
+
+ Item {
+ id: rootItem
+ objectName: "rootItem"
+
+ width: parent.width
+ height: parent.height
+ visible: true
+ focus: true
+
+ Popup {
+ id: popup1
+ objectName: "popup1"
+
+ width: parent.width / 2
+ height: parent.height
+ focus: true
+ modal: true
+ closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
+
+ Button {
+ id: buttonPopup1
+ objectName: "button"
+
+ text: "ButtonPopup"
+ width: 20
+ visible: true
+ }
+ }
+
+ Popup {
+ id: popup2
+ objectName: "popup2"
+
+ width: parent.width / 2
+ height: parent.height
+ focus: true
+ modal: true
+ closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
+
+ TextEdit {
+ id: texteditPopup2
+ objectName: "textedit"
+
+ focus: true
+ text: "Text Edit Content"
+ visible: true
+ }
+ }
+
+ Popup {
+ id: popup3
+ objectName: "popup3"
+
+ width: parent.width / 2
+ height: parent.height
+ focus: true
+ modal: true
+ closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
+
+ Drawer {
+ id: drawerPopup3
+ objectName: "drawer"
+
+ width: parent.width / 2
+ height: parent.height
+ focus: true
+ visible: true
+ }
+ }
+ }
+}
+
diff --git a/tests/auto/quickcontrols/qquickpopup/data/nested-wheel-overlay-parent.qml b/tests/auto/quickcontrols/qquickpopup/data/nested-wheel-overlay-parent.qml
new file mode 100644
index 0000000000..06dafa112a
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickpopup/data/nested-wheel-overlay-parent.qml
@@ -0,0 +1,39 @@
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 100
+ height: 100
+
+ property alias _drawer: drawer
+ property alias _listView: drawer.contentItem
+ property alias _dropArea: dropArea
+
+ Drawer {
+ id: drawer
+ width: 50
+ height: parent.height
+ contentItem: ListView {
+ width: parent.width
+ height: contentHeight
+ model: 500
+ delegate: Rectangle {
+ height: 15
+ Label {
+ text: modelData
+ }
+ }
+ }
+ }
+
+ DropArea {
+ id: dropArea
+ anchors.fill: parent
+ Connections {
+ target: drawer
+ function onOpened() {
+ dropArea.parent = drawer.parent
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickpopup/data/nested.qml b/tests/auto/quickcontrols/qquickpopup/data/nested.qml
index d88142f661..d0257bf700 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/nested.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/nested.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/noDimmer.qml b/tests/auto/quickcontrols/qquickpopup/data/noDimmer.qml
new file mode 100644
index 0000000000..6d42dc10e8
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickpopup/data/noDimmer.qml
@@ -0,0 +1,22 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Templates as T
+
+Window {
+ T.Drawer {
+ id: root
+ onModalChanged: {
+ if (!modal) {
+ open()
+ }
+ }
+ }
+ Timer {
+ interval: 100
+ running: true
+ repeat: false
+ onTriggered: root.modal = false
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickpopup/data/orientation.qml b/tests/auto/quickcontrols/qquickpopup/data/orientation.qml
index 198f716fc0..f83cfda74e 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/orientation.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/orientation.qml
@@ -1,29 +1,35 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
import QtQuick.Controls
Window {
- width: 600
- height: 300
+ width: 200
+ height: 100
property alias popup: popup
Rectangle {
- width: 60
- height: 30
+ width: 100
+ height: 80
anchors.centerIn: parent
border.width: 1
Popup {
id: popup
- x: parent.width
- y: parent.height
- width: 30
- height: 60
+ width: 50
+ height: 40
+ anchors.centerIn: parent
visible: true
+ modal: false
+ dim: true
+
+ Overlay.modeless: Rectangle {
+ opacity: 0.5
+ color: "blue"
+ }
}
}
}
diff --git a/tests/auto/quickcontrols/qquickpopup/data/popupCenterIn.qml b/tests/auto/quickcontrols/qquickpopup/data/popupCenterIn.qml
new file mode 100644
index 0000000000..6a67af30fc
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickpopup/data/popupCenterIn.qml
@@ -0,0 +1,22 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+Window {
+ width: 1080
+ height: 720
+
+ property alias popup: simplepopup
+
+ Popup {
+ id: simplepopup
+ anchors.centerIn: parent
+ popupType: Popup.Window
+
+ Text {
+ text: "I am a centered popup"
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickpopup/data/popupWindowFocusHandling.qml b/tests/auto/quickcontrols/qquickpopup/data/popupWindowFocusHandling.qml
new file mode 100644
index 0000000000..1477db047e
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickpopup/data/popupWindowFocusHandling.qml
@@ -0,0 +1,28 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+Window {
+ width: 400
+ height: 400
+
+ property alias popup: simplepopup
+ property alias textField1: outerTextField
+ property alias textField2: innerTextField
+
+ TextField {
+ id: outerTextField
+ focus: true
+ }
+
+ Popup {
+ id: simplepopup
+ popupType: Popup.Window
+ TextField {
+ id: innerTextField
+ focus: true
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickpopup/data/popupWithButtonInBackground.qml b/tests/auto/quickcontrols/qquickpopup/data/popupWithButtonInBackground.qml
new file mode 100644
index 0000000000..b265a80df7
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickpopup/data/popupWithButtonInBackground.qml
@@ -0,0 +1,28 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+Window {
+ width: 1080
+ height: 720
+
+ property alias popup: simplepopup
+
+ Button {
+ text: "Button"
+ }
+
+ Popup {
+ id: simplepopup
+ popupType: Popup.Window
+
+ x: 50
+ y: 50
+
+ Text {
+ text: "I am a very interesting popup"
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickpopup/data/releaseAfterExitTransition.qml b/tests/auto/quickcontrols/qquickpopup/data/releaseAfterExitTransition.qml
index f3a1f218c1..9ddf4577ee 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/releaseAfterExitTransition.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/releaseAfterExitTransition.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/reparentingPopup.qml b/tests/auto/quickcontrols/qquickpopup/data/reparentingPopup.qml
new file mode 100644
index 0000000000..bf622b7713
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickpopup/data/reparentingPopup.qml
@@ -0,0 +1,48 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+Window {
+ width: 400
+ height: 400
+
+ property alias popup: simplepopup
+ property alias rectangle1: item1
+ property alias rectangle2: item2
+ property alias rectangle3: item3
+
+ Popup {
+ id: simplepopup
+ popupType: Popup.Window
+ x: 10
+ y: 10
+ width: 200
+ height: 200
+ }
+
+ Rectangle {
+ id: item1
+ color: "red"
+ width: 200
+ height: 200
+ }
+
+ Rectangle {
+ id: item2
+ color: "green"
+ x: 0
+ y: 200
+ width: parent.width
+ height: 200
+ Rectangle {
+ id: item3
+ color: "blue"
+ x: 200
+ y: 0
+ width: 200
+ height: item2.height
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickpopup/data/rotatedCombobox.qml b/tests/auto/quickcontrols/qquickpopup/data/rotatedCombobox.qml
index df217be4b7..16cce45263 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/rotatedCombobox.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/rotatedCombobox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowHeight.qml b/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowHeight.qml
index b9b8874622..0de6122431 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowHeight.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowHeight.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowWidth.qml b/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowWidth.qml
index aa78353eb0..2cb655f129 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowWidth.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowWidth.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickpopup/data/simplepopup.qml b/tests/auto/quickcontrols/qquickpopup/data/simplepopup.qml
new file mode 100644
index 0000000000..eeafa10c9e
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickpopup/data/simplepopup.qml
@@ -0,0 +1,22 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+Window {
+ width: 1080
+ height: 720
+
+ property alias popup: simplepopup
+
+ Popup {
+ id: simplepopup
+ x: 50
+ y: 50
+
+ Text {
+ text: "I am a very interesting popup"
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickpopup/data/tabFence.qml b/tests/auto/quickcontrols/qquickpopup/data/tabFence.qml
index a96cf1687c..376ca66e6e 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/tabFence.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/tabFence.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Layouts
diff --git a/tests/auto/quickcontrols/qquickpopup/data/toolTipCrashOnClose.qml b/tests/auto/quickcontrols/qquickpopup/data/toolTipCrashOnClose.qml
index f40fa0939c..8e4eb877dc 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/toolTipCrashOnClose.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/toolTipCrashOnClose.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickpopup/data/window-hover.qml b/tests/auto/quickcontrols/qquickpopup/data/window-hover.qml
index fa61e8b706..5beca69317 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/window-hover.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/window-hover.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
@@ -16,21 +16,24 @@ Window {
Button {
id: parentButton
text: "Parent"
+ palette.buttonText: hovered ? "tomato" : "black"
anchors.fill: parent
+ anchors.margins: 10
Popup {
id: popup
- x: 1
- y: 1
- topPadding: 1
- bottomPadding: 1
- leftPadding: 1
- rightPadding: 1
+ x: 10
+ y: 10
+ leftPadding: 10
+ rightPadding: 10
+ topPadding: 10
+ bottomPadding: 10
Button {
anchors.centerIn: parent
id: childButton
text: "Child"
+ palette.buttonText: hovered ? "tomato" : "black"
}
}
}
diff --git a/tests/auto/quickcontrols/qquickpopup/data/window-wheel.qml b/tests/auto/quickcontrols/qquickpopup/data/window-wheel.qml
index ae9c2ecdfd..57cce40982 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/window-wheel.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/window-wheel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickpopup/data/window.qml b/tests/auto/quickcontrols/qquickpopup/data/window.qml
index 6ffe5165fe..0db6896f59 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/window.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/window.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp
index 8343cc4f3a..650d168c65 100644
--- a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp
+++ b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp
@@ -1,30 +1,39 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
+#include <QtQuickTest/quicktest.h>
#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/qpa/qwindowsysteminterface.h>
#include <QtGui/qpa/qplatformintegration.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtQuick/qquickview.h>
+#include <QtQuick/private/qquickmousearea_p.h>
#include <QtQuick/private/qquickpalette_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
+#include <QtQuickTemplates2/private/qquickbutton_p.h>
#include <QtQuickTemplates2/private/qquickcombobox_p.h>
#include <QtQuickTemplates2/private/qquickdialog_p.h>
+#include <QtQuickTemplates2/private/qquickdrawer_p.h>
#include <QtQuickTemplates2/private/qquickoverlay_p.h>
#include <QtQuickTemplates2/private/qquickoverlay_p_p.h>
#include <QtQuickTemplates2/private/qquickpopup_p.h>
+#include <QtQuickTemplates2/private/qquickpopup_p_p.h>
+#include <QtQuickTemplates2/private/qquickpopupanchors_p.h>
#include <QtQuickTemplates2/private/qquickpopupitem_p_p.h>
-#include <QtQuickTemplates2/private/qquickbutton_p.h>
+#include <QtQuickTemplates2/private/qquickpopupwindow_p_p.h>
#include <QtQuickTemplates2/private/qquickslider_p.h>
#include <QtQuickTemplates2/private/qquickstackview_p.h>
-#include <QtQuickTemplates2/private/qquickpopup_p_p.h>
#include <QtQuickTemplates2/private/qquicktooltip_p.h>
+#include <QtQuick/private/qquicktextinput_p.h>
+#include <QtQuick/private/qquicklistview_p.h>
+#include <QtQuick/private/qquicktextedit_p.h>
+#include <QtQuick/private/qquickdroparea_p.h>
#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
#include <QtQuickControlsTestUtils/private/qtest_quickcontrols_p.h>
@@ -59,13 +68,19 @@ private slots:
void activeFocusAfterExit();
void activeFocusOnDelayedEnter();
void activeFocusDespiteLowerStackingOrder();
+ void activeFocusItemAfterWindowInactive();
void hover_data();
void hover();
+#if QT_CONFIG(wheelevent)
void wheel_data();
void wheel();
+#endif
void parentDestroyed();
void nested();
+#if QT_CONFIG(wheelevent)
void nestedWheel();
+ void nestedWheelWithOverlayParent();
+#endif
void modelessOnModalOnModeless();
void grabber();
void cursorShape();
@@ -92,10 +107,28 @@ private slots:
void relativeZOrder();
void mirroredCombobox();
void rotatedCombobox();
+ void focusMultiplePopup();
+ void contentChildrenChange();
+ void doubleClickInMouseArea();
+ void fadeDimmer_data();
+ void fadeDimmer();
+ void noDimmer();
+
+ void popupWindowPositioning();
+ void popupWindowAnchorsCenterIn_data();
+ void popupWindowAnchorsCenterIn();
+ void popupWindowModality();
+ void popupWindowClosesOnParentWindowClosing();
+ void initialPopupSize_data();
+ void initialPopupSize();
+ void popupWindowChangingParent();
+ void popupWindowFocus();
+ void popupTypeChangeFromWindowToItem();
+ void popupTypeChangeFromItemToWindow();
private:
- static bool hasWindowActivation();
QScopedPointer<QPointingDevice> touchScreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
+ bool popupWindowsSupported = false;
};
using namespace Qt::StringLiterals;
@@ -103,11 +136,14 @@ using namespace Qt::StringLiterals;
tst_QQuickPopup::tst_QQuickPopup()
: QQmlDataTest(QT_QMLTEST_DATADIR)
{
+ popupWindowsSupported = QGuiApplicationPrivate::platformIntegration()
+ ->hasCapability(QPlatformIntegration::Capability::MultipleWindows);
}
void tst_QQuickPopup::initTestCase()
{
QQmlDataTest::initTestCase();
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
qputenv("QML_NO_TOUCH_COMPRESSION", "1");
}
@@ -118,11 +154,6 @@ void tst_QQuickPopup::visible_data()
QTest::newRow("ApplicationWindow") << "applicationwindow.qml";
}
-bool tst_QQuickPopup::hasWindowActivation()
-{
- return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation));
-}
-
void tst_QQuickPopup::visible()
{
QFETCH(QString, source);
@@ -217,6 +248,10 @@ void tst_QQuickPopup::overlay_data()
void tst_QQuickPopup::overlay()
{
+#ifdef Q_OS_ANDROID
+ QSKIP("Test crashes. See QTBUG-118532");
+#endif
+
QFETCH(QString, source);
QFETCH(bool, modal);
QFETCH(bool, dim);
@@ -497,8 +532,7 @@ void tst_QQuickPopup::closePolicy_data()
void tst_QQuickPopup::closePolicy()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QFETCH(QString, source);
QFETCH(const QPointingDevice *, device);
@@ -640,8 +674,7 @@ void tst_QQuickPopup::closePolicy_grabberInside()
void tst_QQuickPopup::activeFocusOnClose1()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
// Test that a popup that never sets focus: true (e.g. ToolTip) doesn't affect
// the active focus item when it closes.
@@ -686,8 +719,7 @@ void tst_QQuickPopup::activeFocusOnClose1()
void tst_QQuickPopup::activeFocusOnClose2()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
// Test that a popup that sets focus: true but relinquishes focus (e.g. by
// calling forceActiveFocus() on another item) before it closes doesn't
@@ -728,8 +760,7 @@ void tst_QQuickPopup::activeFocusOnClose2()
void tst_QQuickPopup::activeFocusOnClose3()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
// Test that a closing popup that had focus doesn't steal focus from
// another popup that the focus was transferred to.
@@ -764,8 +795,7 @@ void tst_QQuickPopup::activeFocusOnClose3()
void tst_QQuickPopup::activeFocusOnClosingSeveralPopups()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
// Test that active focus isn't lost when multiple popup closing simultaneously
QQuickControlsApplicationHelper helper(this, QStringLiteral("activeFocusOnClosingSeveralPopups.qml"));
@@ -816,8 +846,7 @@ void tst_QQuickPopup::activeFocusOnClosingSeveralPopups()
void tst_QQuickPopup::activeFocusAfterExit()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
// Test that after closing a popup the highest one in z-order receives it instead.
QQuickControlsApplicationHelper helper(this, QStringLiteral("activeFocusAfterExit.qml"));
@@ -868,8 +897,7 @@ void tst_QQuickPopup::activeFocusAfterExit()
void tst_QQuickPopup::activeFocusOnDelayedEnter()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
// Test that after opening two popups, first of which has an animation, does not cause
// the first one to receive focus after the animation stops.
@@ -897,8 +925,7 @@ void tst_QQuickPopup::activeFocusOnDelayedEnter()
// key events due to having active focus.
void tst_QQuickPopup::activeFocusDespiteLowerStackingOrder()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QQuickControlsApplicationHelper helper(this, QStringLiteral("activeFocusOnClose3.qml"));
QVERIFY2(helper.ready, helper.failureMessage());
@@ -937,6 +964,52 @@ void tst_QQuickPopup::activeFocusDespiteLowerStackingOrder()
QVERIFY(!popup1->hasActiveFocus());
}
+void tst_QQuickPopup::activeFocusItemAfterWindowInactive()
+{
+ SKIP_IF_NO_WINDOW_ACTIVATION
+
+ QQuickControlsApplicationHelper helper(this, QStringLiteral("activeFocusAfterWindowInactive.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowFocused(window));
+
+ QQuickPopup *popup = helper.appWindow->property("popup").value<QQuickPopup*>();
+ QQuickButton *button = helper.appWindow->property("button").value<QQuickButton*>();
+ QVERIFY(popup);
+ QVERIFY(button);
+
+ popup->open();
+ QVERIFY(popup->isVisible());
+ QTRY_VERIFY(popup->isOpened());
+ QVERIFY(popup->hasActiveFocus());
+ QVERIFY(!button->hasActiveFocus());
+
+ popup->close();
+ QVERIFY(!popup->isVisible());
+ QTRY_VERIFY(!popup->isOpened());
+ QVERIFY(button->hasActiveFocus());
+ QCOMPARE(window->activeFocusItem(), button);
+
+ popup->open();
+ QVERIFY(popup->isVisible());
+ QTRY_VERIFY(popup->isOpened());
+
+ QQuickWindow newWindow;
+ newWindow.setTitle("newFocusWindow");
+ newWindow.show();
+ newWindow.requestActivate();
+ QVERIFY(QTest::qWaitForWindowFocused(&newWindow));
+
+ popup->close();
+ QCOMPARE(QGuiApplication::focusWindow(), &newWindow);
+
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowFocused(window));
+ QCOMPARE(window->activeFocusItem(), button);
+}
+
void tst_QQuickPopup::hover_data()
{
QTest::addColumn<QString>("source");
@@ -977,18 +1050,19 @@ void tst_QQuickPopup::hover()
QVERIFY(openedSpy.size() == 1 || openedSpy.wait());
QTRY_VERIFY(popup->width() > 10); // somehow this can take a short time with macOS style
- // hover the parent button outside the popup
- QTest::mouseMove(window, QPoint(window->width() - 1, window->height() - 1));
+ // Hover the parent button outside the popup. It has 10 pixel anchor margins around the window.
+ PointLerper pointLerper(window);
+ pointLerper.move(15, 15);
QCOMPARE(parentButton->isHovered(), !modal);
QVERIFY(!childButton->isHovered());
- // hover the popup background
- QTest::mouseMove(window, QPoint(1, 1));
+ // Hover the popup background. Its top-left is 10 pixels in from its parent.
+ pointLerper.move(25, 25);
QVERIFY(!parentButton->isHovered());
QVERIFY(!childButton->isHovered());
- // hover the child button in a popup
- QTest::mouseMove(window, QPoint(popup->x() + popup->width() / 2, popup->y() + popup->height() / 2));
+ // Hover the child button in a popup.
+ pointLerper.move(mapCenterToWindow(childButton));
QVERIFY(!parentButton->isHovered());
QVERIFY(childButton->isHovered());
@@ -1002,6 +1076,7 @@ void tst_QQuickPopup::hover()
QVERIFY(parentButton->isHovered());
}
+#if QT_CONFIG(wheelevent)
void tst_QQuickPopup::wheel_data()
{
QTest::addColumn<QString>("source");
@@ -1115,6 +1190,7 @@ void tst_QQuickPopup::wheel()
QVERIFY(qFuzzyCompare(popupSlider->value(), oldPopupValue)); // must not have moved
}
}
+#endif
void tst_QQuickPopup::parentDestroyed()
{
@@ -1153,6 +1229,7 @@ void tst_QQuickPopup::nested()
QCOMPARE(modalPopup->isVisible(), true);
}
+#if QT_CONFIG(wheelevent)
void tst_QQuickPopup::nestedWheel()
{
QQuickControlsApplicationHelper helper(this, QStringLiteral("nested-wheel.qml"));
@@ -1183,6 +1260,42 @@ void tst_QQuickPopup::nestedWheel()
QTRY_COMPARE_GT(vbar->property("position").toDouble(), startPosition);
}
+void tst_QQuickPopup::nestedWheelWithOverlayParent()
+{
+ QQuickControlsApplicationHelper helper(this, QStringLiteral("nested-wheel-overlay-parent.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *drawer= window->property("_drawer").value<QQuickDrawer *>();
+ QVERIFY(drawer);
+
+ auto *dropArea = window->property("_dropArea").value<QQuickDropArea *>();
+ QVERIFY(dropArea);
+
+ drawer->open();
+ QCOMPARE(drawer->isVisible(), true);
+ QTRY_COMPARE(drawer->isOpened(), true);
+
+ QQuickListView *listView = window->property("_listView").value<QQuickListView *>();
+ QTRY_VERIFY(listView != nullptr);
+ QQuickItem *contentItem = listView->contentItem();
+ QTRY_VERIFY(contentItem != nullptr);
+
+ // Check parent is set as overlay
+ QTRY_COMPARE(dropArea->parentItem(), QQuickOverlay::overlay(window));
+ // Consider the center point of the control as event position to trigger wheel event
+ QVERIFY(sendWheelEvent(listView, -15));
+
+ if (QQuickTest::qIsPolishScheduled(listView))
+ QVERIFY(QQuickTest::qWaitForPolish(listView));
+
+ // Wheel over the list view, verify that it scrolls
+ QTRY_COMPARE(listView->contentY(), 72.);
+}
+#endif
+
void tst_QQuickPopup::modelessOnModalOnModeless()
{
QQuickControlsApplicationHelper helper(this, QStringLiteral("modelessOnModalOnModeless.qml"));
@@ -1339,8 +1452,7 @@ void tst_QQuickPopup::componentComplete()
void tst_QQuickPopup::closeOnEscapeWithNestedPopups()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
// Tests the scenario in the Gallery example, where there are nested popups that should
// close in the correct order when the Escape key is pressed.
@@ -1409,8 +1521,7 @@ void tst_QQuickPopup::closeOnEscapeWithNestedPopups()
void tst_QQuickPopup::closeOnEscapeWithVisiblePopup()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QQuickControlsApplicationHelper helper(this, QStringLiteral("closeOnEscapeWithVisiblePopup.qml"));
QVERIFY2(helper.ready, helper.failureMessage());
@@ -1450,66 +1561,49 @@ void tst_QQuickPopup::enabled()
void tst_QQuickPopup::orientation_data()
{
QTest::addColumn<Qt::ScreenOrientation>("orientation");
- QTest::addColumn<QPointF>("position");
- // On Android the screen size will usually be smaller than the 600x300
- // size of a Window in orientation.qml
- // Because of that we need to calculate proper positions at runtime.
-#ifndef Q_OS_ANDROID
- QQuickControlsApplicationHelper helper(this, "orientation.qml");
- const QSize availableSize = helper.window->size();
-#else
- const QSize availableSize = QGuiApplication::primaryScreen()->availableSize();
-#endif
- const int width = availableSize.width();
- const int height = availableSize.height();
-
- // The width & height might be odd numbers, so we calculate center in a way
- // similar to anchors.centerIn.
- // Also note that when we emulate the screen orientation change (by calling
- // window->reportContentOrientationChange() in the test), these values need
- // to be adjusted, because the "logical" (0, 0) of the screen changes.
- const int widthCenter = (width % 2) ? (width + 1) / 2 : width / 2;
- const int heightCenter = (height % 2) ? (height + 1) / 2 : height / 2;
-
- // Rectangle is (60x30); popup is (30x60).
- // Rectangle is using "anchors.centerIn: parent", and popup is positioned at
- // (rectangle.width, rectangle.height)
- QTest::newRow("Portrait") << Qt::PortraitOrientation
- << QPointF(widthCenter - 30 + 60, heightCenter - 15 + 30);
- // in landscape orientation the top left corner of physical screen
- // (not rotated) becomes (0, 0), so we need to adjust our widthCenter
- QTest::newRow("Landscape") << Qt::LandscapeOrientation
- << QPointF(heightCenter - 15 + 30, (width - widthCenter) + 30 - 60);
- // In inverted portrait orientation the bottom right corner of physical
- // screen (not rotated) becomes (0, 0), so we need to adjust both
- // widthCenter and heightCenter
- QTest::newRow("InvertedPortrait") << Qt::InvertedPortraitOrientation
- << QPointF((width - widthCenter) + 30 - 60, (height - heightCenter) + 15 - 30);
- // In inverted landscape orientation the bottom right corner of physical
- // screen (not rotated) becomes (0, 0), so we need to adjust heightCenter
- QTest::newRow("InvertedLandscape") << Qt::InvertedLandscapeOrientation
- << QPointF((height - heightCenter) + 15 - 30, widthCenter - 30 + 60);
+ QTest::newRow("Portrait") << Qt::PortraitOrientation;
+ QTest::newRow("Landscape") << Qt::LandscapeOrientation;
+ QTest::newRow("InvertedPortrait") << Qt::InvertedPortraitOrientation;
+ QTest::newRow("InvertedLandscape") << Qt::InvertedLandscapeOrientation;
}
+/*
+ Verify that the popup is centered, and that the dimmer and overlay cover
+ the content item for any content orientation and content rotation.
+*/
void tst_QQuickPopup::orientation()
{
QFETCH(Qt::ScreenOrientation, orientation);
- QFETCH(QPointF, position);
QQuickControlsApplicationHelper helper(this, "orientation.qml");
QVERIFY2(helper.ready, helper.failureMessage());
QQuickWindow *window = helper.window;
- window->reportContentOrientationChange(orientation);
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
- QQuickPopup *popup = window->property("popup").value<QQuickPopup*>();
+ QQuickPopup *popup = window->property("popup").value<QQuickPopup *>();
QVERIFY(popup);
- popup->open();
QTRY_VERIFY(popup->isOpened());
- QCOMPARE(popup->popupItem()->position(), position);
+
+ QQuickItem *dimmer = QQuickPopupPrivate::get(popup)->dimmer;
+ QVERIFY(dimmer);
+ QQuickItem *popupItem = popup->popupItem();
+ QVERIFY(popupItem);
+ QQuickOverlay *overlay = QQuickOverlay::overlay(window);
+ QVERIFY(overlay);
+ QQuickItem *contentItem = window->contentItem();
+ QVERIFY(contentItem);
+
+ const auto rotation = window->screen()->angleBetween(Qt::PrimaryOrientation, orientation);
+ QCOMPARE(popupItem->mapToScene(popupItem->boundingRect().center()), contentItem->boundingRect().center());
+ QCOMPARE(dimmer->boundingRect(), contentItem->boundingRect());
+ QCOMPARE(overlay->boundingRect(), contentItem->boundingRect());
+ window->contentItem()->setRotation(rotation);
+ QCOMPARE(popupItem->mapToScene(popupItem->boundingRect().center()), contentItem->boundingRect().center());
+ QCOMPARE(dimmer->boundingRect(), contentItem->boundingRect());
+ QCOMPARE(overlay->boundingRect(), contentItem->boundingRect());
}
void tst_QQuickPopup::qquickview()
@@ -1537,8 +1631,7 @@ void tst_QQuickPopup::qquickview()
// QTBUG-73447
void tst_QQuickPopup::disabledPalette()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QQuickControlsApplicationHelper helper(this, "disabledPalette.qml");
QVERIFY2(helper.ready, helper.failureMessage());
@@ -1577,8 +1670,7 @@ void tst_QQuickPopup::disabledPalette()
void tst_QQuickPopup::disabledParentPalette()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QQuickControlsApplicationHelper helper(this, "disabledPalette.qml");
QVERIFY2(helper.ready, helper.failureMessage());
@@ -1686,8 +1778,7 @@ void tst_QQuickPopup::setOverlayParentToNull()
void tst_QQuickPopup::tabFence()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls)
QSKIP("This platform only allows tab focus for text controls");
@@ -1799,8 +1890,7 @@ void tst_QQuickPopup::centerInOverlayWithinStackViewItem()
void tst_QQuickPopup::destroyDuringExitTransition()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QQuickControlsApplicationHelper helper(this, "destroyDuringExitTransition.qml");
QVERIFY2(helper.ready, helper.failureMessage());
@@ -2149,6 +2239,582 @@ void tst_QQuickPopup::rotatedCombobox()
}
}
+void tst_QQuickPopup::focusMultiplePopup()
+{
+ QQuickApplicationHelper helper(this, "multiplepopup.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *rootItem = window->findChild<QQuickItem *>("rootItem");
+ QTRY_VERIFY(rootItem->hasFocus());
+
+ auto *buttonPopup = window->findChild<QQuickPopup *>("popup1");
+ buttonPopup->open();
+ QTRY_VERIFY(buttonPopup->isOpened());
+ QVERIFY(!rootItem->hasFocus());
+ QVERIFY(buttonPopup->hasFocus());
+
+ auto *textEditPopup = window->findChild<QQuickPopup *>("popup2");
+ textEditPopup->open();
+ QTRY_VERIFY(textEditPopup->isOpened());
+ QVERIFY(textEditPopup->hasFocus());
+
+ auto *drawerPopup = window->findChild<QQuickPopup *>("popup3");
+ drawerPopup->open();
+ QTRY_VERIFY(drawerPopup->isVisible());
+ QVERIFY(drawerPopup->hasFocus());
+
+ auto *drawer = window->findChild<QQuickDrawer *>("drawer");
+ drawer->close();
+ QTRY_VERIFY(!drawer->isVisible());
+ drawerPopup->close();
+ QTRY_VERIFY(!drawerPopup->isVisible());
+ QVERIFY(textEditPopup->hasFocus());
+
+ textEditPopup->close();
+ QTRY_VERIFY(!textEditPopup->isVisible());
+ QVERIFY(buttonPopup->hasFocus());
+
+ buttonPopup->close();
+ QTRY_VERIFY(!buttonPopup->isVisible());
+
+ QVERIFY(rootItem->hasFocus());
+}
+
+void tst_QQuickPopup::contentChildrenChange()
+{
+ QQmlEngine engine;
+ QQmlComponent comp(&engine);
+ comp.loadFromModule("QtQuick.Controls", "Popup");
+ std::unique_ptr<QObject> root {comp.create()};
+ QVERIFY(root);
+ QQuickPopup *popup = qobject_cast<QQuickPopup *>(root.get());
+ QVERIFY(popup);
+ QSignalSpy spy(popup, &QQuickPopup::contentChildrenChanged);
+ auto contentItem = std::make_unique<QQuickItem>();
+ popup->setContentItem(contentItem.get());
+ QCOMPARE(spy.count(), 1);
+ auto newChild = std::make_unique<QQuickItem>();
+ QQmlProperty contentItemChildren(contentItem.get());
+ contentItemChildren.write(QVariant::fromValue(newChild.get()));
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_QQuickPopup::doubleClickInMouseArea()
+{
+#ifdef Q_OS_ANDROID
+ QSKIP("Test crashes. See QTBUG-118532");
+#endif
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("doubleClickInMouseArea.qml")));
+
+ auto *ma = window.rootObject()->findChild<QQuickMouseArea *>();
+ QVERIFY(ma);
+ QSignalSpy doubleClickSpy(ma, &QQuickMouseArea::doubleClicked);
+ QSignalSpy longPressSpy(ma, &QQuickMouseArea::pressAndHold);
+ QPoint p = ma->mapToScene(ma->boundingRect().center()).toPoint();
+
+ // check with normal double click
+ QTest::mouseDClick(&window, Qt::LeftButton, Qt::NoModifier, p);
+ QCOMPARE(doubleClickSpy.count(), 1);
+
+ // wait enough time for a wrong long press to happen
+ QTest::qWait(QGuiApplication::styleHints()->mousePressAndHoldInterval() + 10);
+ QCOMPARE(longPressSpy.count(), 0);
+}
+
+void tst_QQuickPopup::fadeDimmer_data()
+{
+ QTest::addColumn<bool>("modality");
+
+ QTest::addRow("modal") << true;
+ QTest::addRow("modeless") << true;
+}
+
+void tst_QQuickPopup::fadeDimmer()
+{
+ QFETCH(const bool, modality);
+ QQuickApplicationHelper helper(this, "fadeDimmer.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *popup = window->contentItem()->findChild<QQuickPopup *>();
+ QVERIFY(popup);
+
+ popup->setModal(modality);
+ popup->open();
+ auto dimmer = QQuickPopupPrivate::get(popup)->dimmer;
+ QVERIFY(dimmer);
+ int opacityChangeCount = 0;
+ connect(dimmer, &QQuickItem::opacityChanged, this, [&opacityChangeCount]{
+ ++opacityChangeCount;
+ });
+ QTRY_VERIFY(popup->isOpened());
+ QTRY_COMPARE(dimmer->opacity(), popup->property("dimmerOpacity").toDouble());
+ QCOMPARE_GT(opacityChangeCount, 2);
+
+ opacityChangeCount = 0;
+ popup->setVisible(false);
+ QTRY_VERIFY(!popup->isVisible());
+ QCOMPARE_GT(opacityChangeCount, 2);
+}
+
+void tst_QQuickPopup::noDimmer()
+{
+ QQuickApplicationHelper helper(this, "noDimmer.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *drawer = window->contentItem()->findChild<QQuickDrawer *>();
+ QVERIFY(drawer);
+
+ drawer->open();
+ auto dimmer = QQuickPopupPrivate::get(drawer)->dimmer;
+ QVERIFY(dimmer);
+ // this must not crash
+ QTRY_VERIFY(!drawer->isModal());
+}
+
+#define VERIFY_LOCAL_POS(POPUP, EXPECTED) \
+ QTRY_VERIFY2(qAbs(POPUP->x() - qreal(EXPECTED.x())) <= 1, \
+ qPrintable(QStringLiteral("QQuickPopup::x() = %1, expected = %2").arg(POPUP->x()).arg(EXPECTED.x())));\
+ QVERIFY2(qAbs(POPUP->y() - qreal(EXPECTED.y())) <= 1, \
+ qPrintable(QStringLiteral("QQuickPopup::y() = %1, expected = %2").arg(POPUP->y()).arg(EXPECTED.y())))
+
+#define VERIFY_GLOBAL_POS(FROM, POPUPWINDOW, EXPECTED) \
+ QTRY_VERIFY2((POPUPWINDOW->position() - FROM->mapToGlobal(EXPECTED.x(), EXPECTED.y())).manhattanLength() <= 2, \
+ qPrintable(QStringLiteral("PopupWindow pos = (%1, %2), expected (%3, %4)") \
+ .arg(POPUPWINDOW->x()).arg(POPUPWINDOW->y()).arg(EXPECTED.x()).arg(EXPECTED.y())))
+
+void tst_QQuickPopup::popupWindowPositioning()
+{
+ if (!popupWindowsSupported)
+ QSKIP("The platform doesn't support popup windows. Skipping test.");
+
+ QQuickApplicationHelper helper(this, "simplepopup.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *popup = window->contentItem()->findChild<QQuickPopup *>();
+ QVERIFY(popup);
+ auto *popupPrivate = QQuickPopupPrivate::get(popup);
+ QVERIFY(popupPrivate);
+
+ popup->setPopupType(QQuickPopup::Window);
+
+ popup->open();
+ QTRY_VERIFY(popup->isVisible());
+
+ QSignalSpy xSpy(popup, SIGNAL(xChanged()));
+ QSignalSpy ySpy(popup, SIGNAL(yChanged()));
+
+ auto *popupWindow = popupPrivate->popupWindow;
+ QVERIFY(popupWindow);
+
+ // x and y properties should be 50 initially
+ const QPoint initialPos(50, 50);
+
+ VERIFY_GLOBAL_POS(popup->parentItem(), popupWindow, initialPos);
+ VERIFY_LOCAL_POS(popup, initialPos);
+
+ // Move popup via QQuickPopup API
+ const QPoint secondPosition(100, 100);
+ popup->setPosition(secondPosition.toPointF());
+
+ QTRY_COMPARE(xSpy.count(), 1);
+ QCOMPARE(ySpy.count(), 1);
+
+ VERIFY_GLOBAL_POS(popup->parentItem(), popupWindow, secondPosition);
+ VERIFY_LOCAL_POS(popup, secondPosition);
+
+ // Move popup via QWindow API (which uses global coordinates)
+ const QPoint thirdPosition(150, 150);
+ popupWindow->setPosition(popup->parentItem()->mapToGlobal(thirdPosition.x(), thirdPosition.y()).toPoint());
+
+ QTRY_COMPARE(xSpy.count(), 2);
+ QCOMPARE(ySpy.count(), 2);
+
+ VERIFY_GLOBAL_POS(popup->parentItem(), popupWindow, thirdPosition);
+ VERIFY_LOCAL_POS(popup, thirdPosition);
+
+ // Moving parent window should change the popups position (because it's stationary, but x and y are relative coordinates)
+ const QPoint movement(30, 30);
+ const QPoint oldPos = window->position();
+ window->setPosition(oldPos + movement);
+
+ // TODO: Figure out these signals are emitted twice
+ // QTRY_COMPARE(xSpy.count(), 3);
+ // QCOMPARE(ySpy.count(), 3);
+
+ VERIFY_GLOBAL_POS(popup->parentItem(), popupWindow, (thirdPosition - movement));
+}
+
+void tst_QQuickPopup::popupWindowAnchorsCenterIn_data()
+{
+ QTest::addColumn<bool>("centerInParent");
+ QTest::newRow("parent") << true;
+ QTest::newRow("overlay") << false;
+}
+
+void tst_QQuickPopup::popupWindowAnchorsCenterIn()
+{
+ QFETCH(bool, centerInParent);
+
+ if (!popupWindowsSupported)
+ QSKIP("The platform doesn't support popup windows. Skipping test.");
+
+ QQuickApplicationHelper helper(this, "popupCenterIn.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *popup = window->contentItem()->findChild<QQuickPopup *>();
+ QVERIFY(popup);
+ auto *popupPrivate = QQuickPopupPrivate::get(popup);
+ QVERIFY(popupPrivate);
+
+ popupPrivate->getAnchors()->setCenterIn(centerInParent ? window->contentItem() : QQuickOverlay::overlay(window));
+
+ popup->open();
+ QTRY_VERIFY(popup->isVisible());
+
+ auto *popupWindow = popupPrivate->popupWindow;
+ QVERIFY(popupWindow);
+
+ const QPoint centeredPosition(qFloor(window->width() / 2 - popupWindow->width() / 2), qFloor(window->height() / 2 - popupWindow->height() / 2));
+
+ VERIFY_GLOBAL_POS(popup->parentItem(), popupWindow, centeredPosition);
+ VERIFY_LOCAL_POS(popup, centeredPosition);
+}
+
+void tst_QQuickPopup::popupWindowModality()
+{
+ QSKIP("The behavior isn't correctly implemented yet. Waiting for patch in qtbase");
+
+ if (!popupWindowsSupported)
+ QSKIP("The platform doesn't support popup windows. Skipping test.");
+
+ QQuickApplicationHelper helper(this, "popupWithButtonInBackground.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *popup = window->contentItem()->findChild<QQuickPopup *>();
+ QVERIFY(popup);
+
+ auto *popupPrivate = QQuickPopupPrivate::get(popup);
+ QVERIFY(popupPrivate);
+
+ auto *button = window->findChild<QQuickButton *>();
+ QVERIFY(button);
+
+ QSignalSpy buttonSpy(button, SIGNAL(clicked()));
+
+ popup->open();
+ QTRY_VERIFY(popup->isVisible());
+
+ auto *popupWindow = popupPrivate->popupWindow;
+ QVERIFY(popupWindow);
+ QVERIFY(popupWindow->isVisible());
+ // NonModal by default
+ QCOMPARE(popupWindow->modality(), Qt::NonModal);
+
+ // Non modal popups should close on press outside
+ QTest::mouseClick(helper.window, Qt::LeftButton, Qt::NoModifier, button->mapToScene(QPointF(button->width() / 2, button->height() / 2)).toPoint());
+ QTRY_COMPARE(buttonSpy.count(), 1);
+ QVERIFY(!popupWindow->isVisible());
+
+ popup->setModal(true);
+ popup->open();
+ QTRY_VERIFY(popup->isVisible());
+ QVERIFY(popupWindow->isVisible());
+ QCOMPARE(popupWindow->modality(), Qt::ApplicationModal);
+
+ // Pressing outside the popup shouldn't cause the button to get the event, because of modality.
+ QTest::mouseClick(helper.window, Qt::LeftButton, Qt::NoModifier, button->mapToScene(QPointF(button->width() / 2, button->height() / 2)).toPoint());
+ QCoreApplication::processEvents();
+ QCOMPARE(buttonSpy.count(), 1);
+ QVERIFY(popupWindow->isVisible());
+
+ popup->close();
+ QTRY_VERIFY(!popup->isVisible());
+}
+
+void tst_QQuickPopup::popupWindowClosesOnParentWindowClosing()
+{
+ QSKIP("The behavior isn't correctly implemented yet. Waiting for patch in qtbase");
+ if (!popupWindowsSupported)
+ QSKIP("The platform doesn't support popup windows. Skipping test.");
+
+ QQuickApplicationHelper helper(this, "simplepopup.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *popup = window->contentItem()->findChild<QQuickPopup *>();
+ QVERIFY(popup);
+ auto *popupPrivate = QQuickPopupPrivate::get(popup);
+ QVERIFY(popupPrivate);
+
+ popup->setPopupType(QQuickPopup::Window);
+
+ popup->open();
+ QTRY_VERIFY(popup->isVisible());
+
+ auto *popupWindow = popupPrivate->popupWindow;
+ QVERIFY(popupWindow);
+ QVERIFY(popupWindow->isVisible());
+
+ // Closing parent window, should close child window;
+ window->close();
+
+ QTRY_VERIFY(!window->isVisible());
+ QTRY_VERIFY(!popupWindow->isVisible());
+}
+
+void tst_QQuickPopup::initialPopupSize_data()
+{
+ QTest::addColumn<QQuickPopup::PopupType>("popupType");
+
+ QTest::newRow("Item") << QQuickPopup::Item;
+ if (popupWindowsSupported)
+ QTest::newRow("Window") << QQuickPopup::Window;
+}
+
+void tst_QQuickPopup::initialPopupSize()
+{
+ QFETCH(QQuickPopup::PopupType, popupType);
+ QQuickApplicationHelper helper(this, "reparentingPopup.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *popup = window->contentItem()->findChild<QQuickPopup *>();
+ QVERIFY(popup);
+ auto *popupPrivate = QQuickPopupPrivate::get(popup);
+ QVERIFY(popupPrivate);
+
+ popup->setPopupType(popupType);
+ popup->open();
+ QTRY_VERIFY(popup->isOpened());
+
+ QCOMPARE(popup->width(), 200);
+ QCOMPARE(popup->height(), 200);
+
+ auto popupItem = popupPrivate->popupItem;
+ QCOMPARE(popupItem->width(), 200);
+ QCOMPARE(popupItem->height(), 200);
+
+ if (popupType == QQuickPopup::Window) {
+ auto *popupWindow = popupPrivate->popupWindow;
+ QVERIFY(popupWindow);
+ QVERIFY(popupWindow->isVisible());
+ QCOMPARE(popupWindow->width(), 200);
+ QCOMPARE(popupWindow->height(), 200);
+ }
+}
+
+void tst_QQuickPopup::popupWindowChangingParent()
+{
+ if (!popupWindowsSupported)
+ QSKIP("The platform doesn't support popup windows. Skipping test.");
+
+ QQuickApplicationHelper helper(this, "reparentingPopup.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickWindow *window = helper.window;
+ auto *popup = window->contentItem()->findChild<QQuickPopup *>();
+ QVERIFY(popup);
+ auto *popupPrivate = QQuickPopupPrivate::get(popup);
+ QVERIFY(popupPrivate);
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(!popup->isVisible());
+
+ QQuickItem *item1 = window->property("rectangle1").value<QQuickItem *>();
+ QVERIFY(item1);
+
+ QQuickItem *item2 = window->property("rectangle2").value<QQuickItem *>();
+ QVERIFY(item2);
+
+ QQuickItem *item3 = window->property("rectangle3").value<QQuickItem *>();
+ QVERIFY(item3);
+
+ popup->open();
+ QTRY_VERIFY(popup->isOpened());
+
+ QTRY_VERIFY(popupPrivate->popupWindow);
+ QWindow *popupWindow = popupPrivate->popupWindow;
+
+ QTRY_VERIFY(popupWindow->isVisible());
+ QVERIFY(QTest::qWaitForWindowExposed(popupWindow));
+
+ const QPoint initialPos(10, 10);
+
+ VERIFY_GLOBAL_POS(item1, popupWindow, initialPos);
+ VERIFY_LOCAL_POS(popup, initialPos);
+
+ popup->setParentItem(item1);
+
+ VERIFY_GLOBAL_POS(item1, popupWindow, initialPos);
+ VERIFY_LOCAL_POS(popup, initialPos);
+
+ popup->setParentItem(item2);
+
+ VERIFY_GLOBAL_POS(item2, popupWindow, initialPos);
+ VERIFY_LOCAL_POS(popup, initialPos);
+
+ popup->setParentItem(item3);
+
+ VERIFY_GLOBAL_POS(item3, popupWindow, initialPos);
+ VERIFY_LOCAL_POS(popup, initialPos);
+}
+
+void tst_QQuickPopup::popupWindowFocus()
+{
+ if (!popupWindowsSupported)
+ QSKIP("The platform doesn't support popup windows. Skipping test.");
+
+ QQuickApplicationHelper helper(this, "popupWindowFocusHandling.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickWindow *window = helper.window;
+ QVERIFY(window);
+ auto *popup = window->contentItem()->findChild<QQuickPopup *>();
+ QVERIFY(popup);
+ auto *popupPrivate = QQuickPopupPrivate::get(popup);
+ QVERIFY(popupPrivate);
+ QQuickTextInput *textField1 = window->property("textField1").value<QQuickTextInput *>();
+ QVERIFY(textField1);
+ QQuickTextInput *textField2 = window->property("textField2").value<QQuickTextInput *>();
+ QVERIFY(textField2);
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowFocused(window));
+ QVERIFY(QGuiApplication::focusObject() == textField1);
+ QTest::keyClick(helper.window, Qt::Key_Q);
+ QTRY_COMPARE(textField1->text(), "q");
+ popup->open();
+ QTRY_VERIFY(popup->isVisible());
+ auto *popupWindow = popupPrivate->popupWindow;
+ QVERIFY(popupWindow);
+ QVERIFY(popupWindow->isVisible());
+ // The focusWindow should still be the main window,
+ // the popup window should get its event forwarded via the delivery agent
+ QVERIFY(QGuiApplication::focusWindow() == helper.window);
+ QVERIFY(popupWindow->focusObject() == textField2);
+ QTest::keyClick(popupWindow, Qt::Key_T);
+ QTRY_COMPARE(textField2->text(), "t");
+ popup->close();
+ QTRY_VERIFY(!popup->isVisible());
+ QVERIFY(QGuiApplication::focusObject() == textField1);
+}
+
+void tst_QQuickPopup::popupTypeChangeFromWindowToItem()
+{
+ if (!popupWindowsSupported)
+ QSKIP("The platform doesn't support native popup windows. Skipping test.");
+
+ QQuickApplicationHelper helper(this, "simplepopup.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ auto *popup = window->contentItem()->findChild<QQuickPopup *>();
+ QVERIFY(popup);
+ auto *popupPrivate = QQuickPopupPrivate::get(popup);
+ QVERIFY(popupPrivate);
+
+ QQuickOverlay *overlay = QQuickOverlay::overlay(window);
+ QVERIFY(overlay);
+
+ popup->setPopupType(QQuickPopup::Window);
+
+ popup->open();
+ QTRY_VERIFY(popup->isOpened());
+ const QWindow *popupWindow = popupPrivate->popupWindow;
+ QVERIFY(popupWindow);
+ QTRY_VERIFY(popupWindow->isVisible());
+ QCOMPARE(popupPrivate->popupItem->position(), QPointF(0, 0));
+ QVERIFY(!overlay->childItems().contains(popup->popupItem()));
+
+ popup->close();
+ QTRY_VERIFY(!popup->isVisible());
+ QVERIFY(!popupWindow->isVisible());
+
+ popup->setPopupType(QQuickPopup::Item);
+
+ popup->open();
+ QTRY_VERIFY(popup->isOpened());
+ QVERIFY(!popupWindow || !popupWindow->isVisible());
+ QCOMPARE(popupPrivate->popupItem->position(), QPointF(50, 50));
+ QVERIFY(overlay->childItems().contains(popup->popupItem()));
+
+ popup->close();
+}
+
+void tst_QQuickPopup::popupTypeChangeFromItemToWindow()
+{
+ if (!popupWindowsSupported)
+ QSKIP("The platform doesn't support popup windows. Skipping test.");
+
+ QQuickApplicationHelper helper(this, "simplepopup.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ auto *popup = window->contentItem()->findChild<QQuickPopup *>();
+ QVERIFY(popup);
+ auto *popupPrivate = QQuickPopupPrivate::get(popup);
+ QVERIFY(popupPrivate);
+
+ QQuickOverlay *overlay = QQuickOverlay::overlay(window);
+ QVERIFY(overlay);
+
+ popup->setPopupType(QQuickPopup::Item);
+
+ popup->open();
+ QTRY_VERIFY(popup->isOpened());
+ QVERIFY(!popupPrivate->popupWindow);
+ QCOMPARE(popupPrivate->popupItem->position(), QPointF(50, 50));
+ QVERIFY(overlay->childItems().contains(popup->popupItem()));
+
+ popup->close();
+ QTRY_VERIFY(!popup->isVisible());
+
+ popup->setPopupType(QQuickPopup::Window);
+
+ popup->open();
+ QTRY_VERIFY(popup->isOpened());
+ const QWindow *popupWindow = popupPrivate->popupWindow;
+ QVERIFY(popupWindow);
+ QTRY_VERIFY(popupWindow->isVisible());
+ QCOMPARE(popupPrivate->popupItem->position(), QPointF(0, 0));
+ QVERIFY(!overlay->childItems().contains(popup->popupItem()));
+
+ popup->close();
+}
+
QTEST_QUICKCONTROLS_MAIN(tst_QQuickPopup)
#include "tst_qquickpopup.moc"
diff --git a/tests/auto/quickcontrols/qquickstyle/CMakeLists.txt b/tests/auto/quickcontrols/qquickstyle/CMakeLists.txt
index 4255850e30..01b13e1f11 100644
--- a/tests/auto/quickcontrols/qquickstyle/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickstyle/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickstyle LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickstyle/tst_qquickstyle.cpp b/tests/auto/quickcontrols/qquickstyle/tst_qquickstyle.cpp
index e7572164b8..8806b04a1e 100644
--- a/tests/auto/quickcontrols/qquickstyle/tst_qquickstyle.cpp
+++ b/tests/auto/quickcontrols/qquickstyle/tst_qquickstyle.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtQml/qqmlengine.h>
diff --git a/tests/auto/quickcontrols/qquicktextarea/CMakeLists.txt b/tests/auto/quickcontrols/qquicktextarea/CMakeLists.txt
index f64b896e5c..1d159b69b5 100644
--- a/tests/auto/quickcontrols/qquicktextarea/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquicktextarea/CMakeLists.txt
@@ -1,10 +1,10 @@
# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+# SPDX-License-Identifier: BSD-3-Clause
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquicktextarea LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquicktextarea/tst_qquicktextarea.cpp b/tests/auto/quickcontrols/qquicktextarea/tst_qquicktextarea.cpp
index 1c40b078f7..75e2550d7a 100644
--- a/tests/auto/quickcontrols/qquicktextarea/tst_qquicktextarea.cpp
+++ b/tests/auto/quickcontrols/qquicktextarea/tst_qquicktextarea.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
@@ -12,6 +12,7 @@
#include <QtQuick/qquickview.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
+#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtQuickTemplates2/private/qquicktextarea_p.h>
#include <QtQuickControlsTestUtils/private/qtest_quickcontrols_p.h>
@@ -29,7 +30,6 @@ private slots:
void touchscreenSetsFocusAndMovesCursor();
private:
- static bool hasWindowActivation();
QScopedPointer<QPointingDevice> touchDevice = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
};
@@ -86,9 +86,11 @@ void tst_QQuickTextArea::touchscreenDoesNotSelect()
if (selectByMouse) {
// press-drag-and-release from x1 to x2
- int x1 = 10;
- int x2 = 70;
- int y = QFontMetrics(textEditObject->font()).height() / 2;
+ const int x1 = textEditObject->leftPadding();
+ const int x2 = textEditObject->width() / 2;
+ // Account for all styles by being aware of vertical padding.
+ // contentHeight / 2 should be half the line height considering that we only have one line of text.
+ const int y = textEditObject->topPadding() + textEditObject->contentHeight() / 2;
QTest::touchEvent(&window, touchDevice.data()).press(0, QPoint(x1,y), &window);
QTest::touchEvent(&window, touchDevice.data()).move(0, QPoint(x2,y), &window);
QTest::touchEvent(&window, touchDevice.data()).release(0, QPoint(x2,y), &window);
@@ -100,8 +102,7 @@ void tst_QQuickTextArea::touchscreenDoesNotSelect()
void tst_QQuickTextArea::touchscreenSetsFocusAndMovesCursor()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
qunsetenv("QT_QUICK_CONTROLS_TEXT_SELECTION_BEHAVIOR");
QQuickView window;
@@ -156,11 +157,6 @@ void tst_QQuickTextArea::touchscreenSetsFocusAndMovesCursor()
QCOMPARE_GT(top->selectedText().size(), 0);
}
-bool tst_QQuickTextArea::hasWindowActivation()
-{
- return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation));
-}
-
QTEST_QUICKCONTROLS_MAIN(tst_QQuickTextArea)
#include "tst_qquicktextarea.moc"
diff --git a/tests/auto/quickcontrols/qquicktextfield/CMakeLists.txt b/tests/auto/quickcontrols/qquicktextfield/CMakeLists.txt
index 50755b7f1c..9ad2308e7c 100644
--- a/tests/auto/quickcontrols/qquicktextfield/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquicktextfield/CMakeLists.txt
@@ -1,10 +1,10 @@
# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+# SPDX-License-Identifier: BSD-3-Clause
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquicktextfield LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquicktextfield/tst_qquicktextfield.cpp b/tests/auto/quickcontrols/qquicktextfield/tst_qquicktextfield.cpp
index 19219bb79e..11d309fd42 100644
--- a/tests/auto/quickcontrols/qquicktextfield/tst_qquicktextfield.cpp
+++ b/tests/auto/quickcontrols/qquicktextfield/tst_qquicktextfield.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
@@ -84,9 +84,9 @@ void tst_QQuickTextField::touchscreenDoesNotSelect()
if (selectByMouse) {
// press-drag-and-release from x1 to x2
- int x1 = 10;
- int x2 = 70;
- int y = QFontMetrics(textField->font()).height() / 2;
+ const int x1 = textField->leftPadding();
+ const int x2 = textField->width() / 2;
+ const int y = textField->height() / 2;
QTest::touchEvent(&window, touchDevice.data()).press(0, QPoint(x1,y), &window);
QTest::touchEvent(&window, touchDevice.data()).move(0, QPoint(x2,y), &window);
QTest::touchEvent(&window, touchDevice.data()).release(0, QPoint(x2,y), &window);
diff --git a/tests/auto/quickcontrols/qquicktreeviewdelegate/CMakeLists.txt b/tests/auto/quickcontrols/qquicktreeviewdelegate/CMakeLists.txt
index 94d4096586..e577bb6a5d 100644
--- a/tests/auto/quickcontrols/qquicktreeviewdelegate/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquicktreeviewdelegate/CMakeLists.txt
@@ -4,7 +4,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquicktreeviewdelegate LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquicktreeviewdelegate/data/unmodified.qml b/tests/auto/quickcontrols/qquicktreeviewdelegate/data/unmodified.qml
index c3edb37d1c..65de049893 100644
--- a/tests/auto/quickcontrols/qquicktreeviewdelegate/data/unmodified.qml
+++ b/tests/auto/quickcontrols/qquicktreeviewdelegate/data/unmodified.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import TestModel
diff --git a/tests/auto/quickcontrols/qquicktreeviewdelegate/testmodel.cpp b/tests/auto/quickcontrols/qquicktreeviewdelegate/testmodel.cpp
index 6c6da8452b..26822bfa1e 100644
--- a/tests/auto/quickcontrols/qquicktreeviewdelegate/testmodel.cpp
+++ b/tests/auto/quickcontrols/qquicktreeviewdelegate/testmodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testmodel.h"
diff --git a/tests/auto/quickcontrols/qquicktreeviewdelegate/testmodel.h b/tests/auto/quickcontrols/qquicktreeviewdelegate/testmodel.h
index f886c56d4a..e0c4a9953e 100644
--- a/tests/auto/quickcontrols/qquicktreeviewdelegate/testmodel.h
+++ b/tests/auto/quickcontrols/qquicktreeviewdelegate/testmodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTMODEL_H
#define TESTMODEL_H
diff --git a/tests/auto/quickcontrols/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp b/tests/auto/quickcontrols/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp
index 8471a31408..2725248aee 100644
--- a/tests/auto/quickcontrols/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp
+++ b/tests/auto/quickcontrols/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuickTest/quicktest.h>
@@ -25,7 +25,7 @@ using namespace QQuickVisualTestUtils;
#define LOAD_TREEVIEW(fileName) \
view->setSource(testFileUrl(fileName)); \
view->show(); \
- QVERIFY(QTest::qWaitForWindowActive(view)); \
+ QVERIFY(QTest::qWaitForWindowActive(view.get())); \
auto treeView = view->rootObject()->property("treeView").value<QQuickTreeView *>(); \
QVERIFY(treeView); \
auto treeViewPrivate = QQuickTreeViewPrivate::get(treeView); \
@@ -46,7 +46,7 @@ public:
tst_qquicktreeviewdelegate();
private:
- QQuickView *view = nullptr;
+ std::unique_ptr<QQuickView> view = nullptr;
private slots:
void initTestCase() override;
@@ -74,7 +74,7 @@ void tst_qquicktreeviewdelegate::initTestCase()
{
QQmlDataTest::initTestCase();
qmlRegisterType<TestModel>("TestModel", 1, 0, "TestModel");
- view = createView();
+ view.reset(createView());
}
void tst_qquicktreeviewdelegate::showTreeView()
@@ -91,7 +91,7 @@ void tst_qquicktreeviewdelegate::expandAndCollapsUsingDoubleClick()
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
// Expand the root by double clicking on the row
- const auto item = treeView->itemAtCell(0, 0);
+ const auto item = treeView->itemAtIndex(treeView->index(0, 0));
QVERIFY(item);
const QPoint localPos = QPoint(item->width() / 2, item->height() / 2);
const QPoint pos = item->window()->contentItem()->mapFromItem(item, localPos).toPoint();
@@ -128,7 +128,7 @@ void tst_qquicktreeviewdelegate::expandAndCollapseClickOnIndicator()
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
// Expand the root by clicking on the indicator
- const auto item = qobject_cast<QQuickTreeViewDelegate *>(treeView->itemAtCell(0, 0));
+ const auto item = qobject_cast<QQuickTreeViewDelegate *>(treeView->itemAtIndex(treeView->index(0, 0)));
QVERIFY(item);
const auto indicator = item->indicator();
const QPoint localPos = QPoint(indicator->width() / 2, indicator->height() / 2);
@@ -159,7 +159,7 @@ void tst_qquicktreeviewdelegate::pointerNavigationDisabled()
QVERIFY(!treeView->isExpanded(0));
// Try to expand the root by clicking on the indicator
- const auto item = qobject_cast<QQuickTreeViewDelegate *>(treeView->itemAtCell(0, 0));
+ const auto item = qobject_cast<QQuickTreeViewDelegate *>(treeView->itemAtIndex(treeView->index(0, 0)));
QVERIFY(item);
const auto indicator = item->indicator();
QPoint localPos = QPoint(indicator->width() / 2, indicator->height() / 2);
@@ -292,7 +292,7 @@ void tst_qquicktreeviewdelegate::checkClickedSignal()
LOAD_TREEVIEW("unmodified.qml");
treeView->setPointerNavigationEnabled(pointerNavigationEnabled);
- const auto item = treeView->itemAtCell(0, 0);
+ const auto item = treeView->itemAtIndex(treeView->index(0, 0));
QVERIFY(item);
QSignalSpy clickedSpy(item, SIGNAL(clicked()));
@@ -323,7 +323,7 @@ void tst_qquicktreeviewdelegate::clearSelectionOnClick()
QCOMPARE(treeView->selectionModel()->selectedIndexes().size(), 1);
// Click on a cell. This should remove the selection
- const auto item = qobject_cast<QQuickTreeViewDelegate *>(treeView->itemAtCell(0, 0));
+ const auto item = qobject_cast<QQuickTreeViewDelegate *>(treeView->itemAtIndex(treeView->index(0, 0)));
QVERIFY(item);
QPoint localPos = QPoint(item->width() / 2, item->height() / 2);
QPoint pos = item->window()->contentItem()->mapFromItem(item, localPos).toPoint();
@@ -348,8 +348,8 @@ void tst_qquicktreeviewdelegate::dragToSelect()
QCOMPARE(treeView->selectionBehavior(), QQuickTableView::SelectRows);
// Drag on from cell 0,0 to 0,1
- const auto item0_0 = treeView->itemAtCell(0, 0);
- const auto item0_1 = treeView->itemAtCell(0, 1);
+ const auto item0_0 = treeView->itemAtIndex(treeView->index(0, 0));
+ const auto item0_1 = treeView->itemAtIndex(treeView->index(1, 0));
QVERIFY(item0_0);
QVERIFY(item0_1);
@@ -385,7 +385,7 @@ void tst_qquicktreeviewdelegate::pressAndHoldToSelect()
QCOMPARE(treeView->selectionBehavior(), QQuickTableView::SelectRows);
// PressAndHold on cell 0,0
- const auto item0_0 = treeView->itemAtCell(0, 0);
+ const auto item0_0 = treeView->itemAtIndex(treeView->index(0, 0));
QVERIFY(item0_0);
QQuickWindow *window = treeView->window();
diff --git a/tests/auto/quickcontrols/qquickuniversalstyle/CMakeLists.txt b/tests/auto/quickcontrols/qquickuniversalstyle/CMakeLists.txt
index a7f8ebfd6f..7b93c9812b 100644
--- a/tests/auto/quickcontrols/qquickuniversalstyle/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickuniversalstyle/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickuniversalstyle LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickuniversalstyle/data/tst_universal.qml b/tests/auto/quickcontrols/qquickuniversalstyle/data/tst_universal.qml
index 2ce0cadb38..20b2fedc06 100644
--- a/tests/auto/quickcontrols/qquickuniversalstyle/data/tst_universal.qml
+++ b/tests/auto/quickcontrols/qquickuniversalstyle/data/tst_universal.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
diff --git a/tests/auto/quickcontrols/qquickuniversalstyle/tst_qquickuniversalstyle.cpp b/tests/auto/quickcontrols/qquickuniversalstyle/tst_qquickuniversalstyle.cpp
index 1d2d6332f7..538bac0203 100644
--- a/tests/auto/quickcontrols/qquickuniversalstyle/tst_qquickuniversalstyle.cpp
+++ b/tests/auto/quickcontrols/qquickuniversalstyle/tst_qquickuniversalstyle.cpp
@@ -1,5 +1,19 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
-QUICK_TEST_MAIN(tst_qquickuniversalstyle)
+
+class Setup : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void applicationAvailable()
+ {
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
+ }
+};
+
+QUICK_TEST_MAIN_WITH_SETUP(tst_qquickuniversalstyle, Setup)
+
+#include "tst_qquickuniversalstyle.moc"
diff --git a/tests/auto/quickcontrols/qquickuniversalstyleconf/CMakeLists.txt b/tests/auto/quickcontrols/qquickuniversalstyleconf/CMakeLists.txt
index cfe781950d..a8387a0486 100644
--- a/tests/auto/quickcontrols/qquickuniversalstyleconf/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickuniversalstyleconf/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickuniversalstyleconf LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickuniversalstyleconf/data/applicationwindow.qml b/tests/auto/quickcontrols/qquickuniversalstyleconf/data/applicationwindow.qml
index acbccdeab0..a1d9367b7b 100644
--- a/tests/auto/quickcontrols/qquickuniversalstyleconf/data/applicationwindow.qml
+++ b/tests/auto/quickcontrols/qquickuniversalstyleconf/data/applicationwindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickuniversalstyleconf/qtquickcontrols2.conf b/tests/auto/quickcontrols/qquickuniversalstyleconf/qtquickcontrols2.conf
index 0ec1325871..aef058c7d2 100644
--- a/tests/auto/quickcontrols/qquickuniversalstyleconf/qtquickcontrols2.conf
+++ b/tests/auto/quickcontrols/qquickuniversalstyleconf/qtquickcontrols2.conf
@@ -4,7 +4,5 @@ Style=Universal
[Universal]
Background=#444444
Foreground=Red
+Font\Family=Courier
Font\PixelSize=22
-
-[Universal\Font]
-Family=Courier
diff --git a/tests/auto/quickcontrols/qquickuniversalstyleconf/tst_qquickuniversalstyleconf.cpp b/tests/auto/quickcontrols/qquickuniversalstyleconf/tst_qquickuniversalstyleconf.cpp
index b75668fb66..f220a8c54e 100644
--- a/tests/auto/quickcontrols/qquickuniversalstyleconf/tst_qquickuniversalstyleconf.cpp
+++ b/tests/auto/quickcontrols/qquickuniversalstyleconf/tst_qquickuniversalstyleconf.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQuick/private/qquickitem_p.h>
diff --git a/tests/auto/quickcontrols/revisions/CMakeLists.txt b/tests/auto/quickcontrols/revisions/CMakeLists.txt
index 8c51f85d20..2dc13eb887 100644
--- a/tests/auto/quickcontrols/revisions/CMakeLists.txt
+++ b/tests/auto/quickcontrols/revisions/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_revisions LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/revisions/tst_revisions.cpp b/tests/auto/quickcontrols/revisions/tst_revisions.cpp
index 51f0f02aae..f000603fb0 100644
--- a/tests/auto/quickcontrols/revisions/tst_revisions.cpp
+++ b/tests/auto/quickcontrols/revisions/tst_revisions.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
diff --git a/tests/auto/quickcontrols/sanity/CMakeLists.txt b/tests/auto/quickcontrols/sanity/CMakeLists.txt
index 31fbe176c0..bf9a061be7 100644
--- a/tests/auto/quickcontrols/sanity/CMakeLists.txt
+++ b/tests/auto/quickcontrols/sanity/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_sanity LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
file(GLOB_RECURSE test_data_glob
diff --git a/tests/auto/quickcontrols/sanity/data/attachedTypeResolution.qml b/tests/auto/quickcontrols/sanity/data/attachedTypeResolution.qml
new file mode 100644
index 0000000000..d6062be1f6
--- /dev/null
+++ b/tests/auto/quickcontrols/sanity/data/attachedTypeResolution.qml
@@ -0,0 +1,6 @@
+import QtQml
+import QtQuick
+
+Window {
+
+}
diff --git a/tests/auto/quickcontrols/sanity/quickcontrolssanity.cpp b/tests/auto/quickcontrols/sanity/quickcontrolssanity.cpp
index 7d8a216c78..0f8ea47bfd 100644
--- a/tests/auto/quickcontrols/sanity/quickcontrolssanity.cpp
+++ b/tests/auto/quickcontrols/sanity/quickcontrolssanity.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "quickcontrolssanity.h"
@@ -10,7 +10,7 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
-static constexpr LoggerWarningId qmlControlsSanity{ "QuickControlsSanity.controls-sanity" };
+static constexpr QQmlJS::LoggerWarningId qmlControlsSanity{ "QuickControlsSanity.controls-sanity" };
AnchorsElementPass::AnchorsElementPass(QQmlSA::PassManager *manager)
: QQmlSA::ElementPass(manager), m_item(resolveType("QtQuick"_L1, "Item"_L1))
@@ -19,14 +19,14 @@ AnchorsElementPass::AnchorsElementPass(QQmlSA::PassManager *manager)
bool AnchorsElementPass::shouldRun(const QQmlSA::Element &element)
{
- return !m_item.isNull() && element->inherits(m_item)
- && element->hasOwnPropertyBindings("anchors"_L1);
+ return !m_item.isNull() && element.inherits(m_item)
+ && element.hasOwnPropertyBindings("anchors"_L1);
}
void AnchorsElementPass::run(const QQmlSA::Element &element)
{
- const auto anchorBindings = element->propertyBindings("anchors"_L1);
- for (auto &&anchors : anchorBindings) {
+ const auto anchorBindings = element.propertyBindings("anchors"_L1);
+ for (const auto &anchors : anchorBindings) {
emitWarning(u"Using anchors here"_s, qmlControlsSanity, anchors.sourceLocation());
}
}
@@ -38,17 +38,19 @@ SignalHandlerPass::SignalHandlerPass(QQmlSA::PassManager *manager)
bool SignalHandlerPass::shouldRun(const QQmlSA::Element &element)
{
- return !m_qtobject.isNull() && element->inherits(m_qtobject);
+ return !m_qtobject.isNull() && element.inherits(m_qtobject);
}
void SignalHandlerPass::run(const QQmlSA::Element &element)
{
- for (auto &&[propertyName, propertyBinding] :
- element->ownPropertyBindings().asKeyValueRange()) {
+ const auto &ownBindings = element.ownPropertyBindings();
+ for (auto it = ownBindings.constBegin(); it != ownBindings.constEnd(); ++it) {
+ const auto &propertyName = it.key();
+ const auto &propertyBinding = it.value();
// Already script binding, check if the script kind is signal handler
- if (propertyBinding.bindingType() == QQmlJSMetaPropertyBinding::Script) {
- if (propertyBinding.scriptKind() == QQmlJSMetaPropertyBinding::Script_SignalHandler) {
+ if (propertyBinding.bindingType() == QQmlSA::BindingType::Script) {
+ if (propertyBinding.scriptKind() == QQmlSA::ScriptBindingKind::SignalHandler) {
emitWarning(u"Declared signal handler \"%1\""_s.arg(propertyName),
qmlControlsSanity, propertyBinding.sourceLocation());
}
@@ -56,11 +58,11 @@ void SignalHandlerPass::run(const QQmlSA::Element &element)
}
// Current property is attached property, recursively go through attaching type
- if (propertyBinding.bindingType() == QQmlJSMetaPropertyBinding::AttachedProperty) {
- const auto scope = propertyBinding.attachingType();
+ if (propertyBinding.bindingType() == QQmlSA::BindingType::AttachedProperty) {
+ const auto scope = QQmlSA::Element{ propertyBinding.attachingType() };
run(scope);
}
- };
+ }
}
FunctionDeclarationPass::FunctionDeclarationPass(QQmlSA::PassManager *manager)
@@ -76,12 +78,12 @@ bool FunctionDeclarationPass::shouldRun(const QQmlSA::Element &element)
void FunctionDeclarationPass::run(const QQmlSA::Element &element)
{
- for (auto &&method : element->ownMethods()) {
- if (method.methodType() != QQmlJSMetaMethod::Method)
+ for (const auto &method : element.ownMethods()) {
+ if (method.methodType() != QQmlSA::MethodType::Method)
continue;
emitWarning(u"Declared function \"%1\""_s.arg(method.methodName()), qmlControlsSanity,
- element->sourceLocation());
+ element.sourceLocation());
}
}
diff --git a/tests/auto/quickcontrols/sanity/quickcontrolssanity.h b/tests/auto/quickcontrols/sanity/quickcontrolssanity.h
index 2b6eb5b9d9..29bc0c7a3a 100644
--- a/tests/auto/quickcontrols/sanity/quickcontrolssanity.h
+++ b/tests/auto/quickcontrols/sanity/quickcontrolssanity.h
@@ -1,5 +1,5 @@
// Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef QUICKCONTROLSSANITY_H
#define QUICKCONTROLSSANITY_H
diff --git a/tests/auto/quickcontrols/sanity/tst_sanity.cpp b/tests/auto/quickcontrols/sanity/tst_sanity.cpp
index 493b717253..01524e4a89 100644
--- a/tests/auto/quickcontrols/sanity/tst_sanity.cpp
+++ b/tests/auto/quickcontrols/sanity/tst_sanity.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest>
#include <QtQml>
@@ -19,6 +19,8 @@
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
#include <QtQmlCompiler/private/qqmljslinter_p.h>
+#include <QtQmlCompiler/private/qqmljstyperesolver_p.h>
+#include <QtQmlCompiler/private/qqmljsimportvisitor_p.h>
Q_IMPORT_PLUGIN(QuickControlsSanityPlugin)
@@ -33,7 +35,7 @@ public:
tst_Sanity();
private slots:
- void initTestCase();
+ void initTestCase() override;
void jsFiles();
void qmllint();
@@ -48,7 +50,7 @@ private:
QStringList m_importPaths;
QQmlJSLinter m_linter;
- QList<QQmlJSLogger::Category> m_categories;
+ QList<QQmlJS::LoggerCategory> m_categories;
};
tst_Sanity::tst_Sanity()
@@ -64,10 +66,12 @@ tst_Sanity::tst_Sanity()
m_linter.setPluginsEnabled(true);
for (auto &category : m_categories) {
- if (category == qmlDeferredPropertyId || category == qmlAttachedPropertyReuse) {
- category.setLevel(u"warning"_s);
+ if (category.id() == qmlDeferredPropertyId || category.id() == qmlAttachedPropertyReuse) {
+ category.setLevel(QtWarningMsg);
+ category.setIgnored(false);
} else {
- category.setLevel(u"disable"_s);
+ category.setLevel(QtCriticalMsg);
+ category.setIgnored(true);
}
}
}
diff --git a/tests/auto/quickcontrols/snippets/CMakeLists.txt b/tests/auto/quickcontrols/snippets/CMakeLists.txt
index cfb2fb4560..37a4b67e49 100644
--- a/tests/auto/quickcontrols/snippets/CMakeLists.txt
+++ b/tests/auto/quickcontrols/snippets/CMakeLists.txt
@@ -1,12 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
# Generated from snippets.pro.
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_snippets LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/snippets/tst_snippets.cpp b/tests/auto/quickcontrols/snippets/tst_snippets.cpp
index b16066a693..68e6ef5dfa 100644
--- a/tests/auto/quickcontrols/snippets/tst_snippets.cpp
+++ b/tests/auto/quickcontrols/snippets/tst_snippets.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest>
#include <QtQuick>
@@ -39,6 +39,9 @@ static QMap<QString, QStringPair> findSnippets(const QDir &inputDir, const QDir
void tst_Snippets::initTestCase()
{
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
+
qInfo() << "Snippets are taken from" << QQC2_SNIPPETS_PATH;
QDir snippetsDir(QQC2_SNIPPETS_PATH);
diff --git a/tests/auto/quickcontrols/styleimports/CMakeLists.txt b/tests/auto/quickcontrols/styleimports/CMakeLists.txt
index 4d19521f2e..d18a7effc1 100644
--- a/tests/auto/quickcontrols/styleimports/CMakeLists.txt
+++ b/tests/auto/quickcontrols/styleimports/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_styleimports LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/styleimports/data/applicationWindowWithButton.qml b/tests/auto/quickcontrols/styleimports/data/applicationWindowWithButton.qml
index 512bd0bb08..50f0e43419 100644
--- a/tests/auto/quickcontrols/styleimports/data/applicationWindowWithButton.qml
+++ b/tests/auto/quickcontrols/styleimports/data/applicationWindowWithButton.qml
@@ -1,7 +1,6 @@
-// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-import QtQuick
import QtQuick.Controls
ApplicationWindow {
diff --git a/tests/auto/quickcontrols/styleimports/data/customStyleSelector.qml b/tests/auto/quickcontrols/styleimports/data/customStyleSelector.qml
index a3def8b14b..020d091156 100644
--- a/tests/auto/quickcontrols/styleimports/data/customStyleSelector.qml
+++ b/tests/auto/quickcontrols/styleimports/data/customStyleSelector.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/styleimports/data/importStyleWithQmlDirFallback.qml b/tests/auto/quickcontrols/styleimports/data/importStyleWithQmlDirFallback.qml
new file mode 100644
index 0000000000..3202fca1cd
--- /dev/null
+++ b/tests/auto/quickcontrols/styleimports/data/importStyleWithQmlDirFallback.qml
@@ -0,0 +1,17 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import StyleThatImportsMaterial
+
+ApplicationWindow {
+ title: "Test Application Window"
+ width: 400
+ height: 400
+
+ property alias button: button
+
+ Button {
+ id: button
+ text: "QmlOnly Button"
+ }
+}
diff --git a/tests/auto/quickcontrols/styleimports/data/styles/FileSystemStyle/Button.qml b/tests/auto/quickcontrols/styleimports/data/styles/FileSystemStyle/Button.qml
index a5078b14c2..71c451ab0f 100644
--- a/tests/auto/quickcontrols/styleimports/data/styles/FileSystemStyle/Button.qml
+++ b/tests/auto/quickcontrols/styleimports/data/styles/FileSystemStyle/Button.qml
@@ -1,4 +1,9 @@
import QtQuick.Templates as T
T.Button {
+ id: control
objectName: "FileSystemStyle"
+ contentItem: T.Label {
+ text: control.text
+ color: "#0000ff"
+ }
}
diff --git a/tests/auto/quickcontrols/styleimports/data/styles/StyleThatImportsMaterial/Button.qml b/tests/auto/quickcontrols/styleimports/data/styles/StyleThatImportsMaterial/Button.qml
new file mode 100644
index 0000000000..b7e77c2864
--- /dev/null
+++ b/tests/auto/quickcontrols/styleimports/data/styles/StyleThatImportsMaterial/Button.qml
@@ -0,0 +1,34 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Templates as T
+
+T.Button {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ padding: 6
+ horizontalPadding: padding + 2
+ spacing: 6
+
+ contentItem: T.Label {
+ text: control.text
+ font: control.font
+ color: "#ff0000"
+ verticalAlignment: T.Label.AlignVCenter
+ }
+
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ visible: !control.flat || control.down || control.checked || control.highlighted
+ color: "#ccc"
+ border.color: control.palette.highlight
+ border.width: control.visualFocus ? 2 : 0
+ }
+}
diff --git a/tests/auto/quickcontrols/styleimports/data/styles/StyleThatImportsMaterial/qmldir b/tests/auto/quickcontrols/styleimports/data/styles/StyleThatImportsMaterial/qmldir
new file mode 100644
index 0000000000..eeffe70d4e
--- /dev/null
+++ b/tests/auto/quickcontrols/styleimports/data/styles/StyleThatImportsMaterial/qmldir
@@ -0,0 +1,3 @@
+module StyleThatImportsMaterial
+Button 1.0 Button.qml
+import QtQuick.Controls.Material
diff --git a/tests/auto/quickcontrols/styleimports/tst_styleimports.cpp b/tests/auto/quickcontrols/styleimports/tst_styleimports.cpp
index 175541296a..a88c154448 100644
--- a/tests/auto/quickcontrols/styleimports/tst_styleimports.cpp
+++ b/tests/auto/quickcontrols/styleimports/tst_styleimports.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qregularexpression.h>
#include <QtGui/qpalette.h>
@@ -15,7 +15,12 @@
#include <QtQuickControls2/qquickstyle.h>
#include <QtQuickControls2/private/qquickstyle_p.h>
#include <QtQuickControls2Impl/private/qquickiconlabel_p.h>
+#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
#include <QtQuickControlsTestUtils/private/qtest_quickcontrols_p.h>
+#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
+#include <QtQuickTemplates2/private/qquickbutton_p.h>
+
+using namespace QQuickControlsTestUtils;
class tst_StyleImports : public QQmlDataTest
{
@@ -38,6 +43,9 @@ private slots:
void fallbackStyleShouldNotOverwriteTheme_data();
void fallbackStyleShouldNotOverwriteTheme();
+ void fallbackStyleThemeRespected_data();
+ void fallbackStyleThemeRespected();
+
void attachedTypesAvailable_data();
void attachedTypesAvailable();
};
@@ -278,6 +286,92 @@ void tst_StyleImports::fallbackStyleShouldNotOverwriteTheme()
QCOMPARE(contentItem->color(), expectedContentItemColor);
}
+enum FallbackMethod {
+ QmlDirImport,
+ EnvVar
+};
+
+void tst_StyleImports::fallbackStyleThemeRespected_data()
+{
+ QTest::addColumn<QString>("qmlFilePath");
+ QTest::addColumn<QString>("runtimeStyle");
+ QTest::addColumn<FallbackMethod>("fallbackMethod");
+ QTest::addColumn<Qt::ColorScheme>("colorScheme");
+ QTest::addColumn<QColor>("expectedButtonTextColor");
+ QTest::addColumn<QColor>("expectedWindowColor");
+
+ // Taken from qquickmaterialstyle.cpp.
+ static const QRgb materialBackgroundColorLight = 0xFFFFFBFE;
+ static const QRgb materialBackgroundColorDark = 0xFF1C1B1F;
+
+ // Notes:
+ // - FileSystemStyle has blue button text.
+ // - StyleThatImportsMaterial has red button text.
+ // - All rows result in Material being the fallback.
+
+ QTest::newRow("import controls, env var fallback, light") << "applicationWindowWithButton.qml"
+ << "FileSystemStyle" << EnvVar << Qt::ColorScheme::Light
+ << QColor::fromRgb(0x0000ff) << QColor::fromRgba(materialBackgroundColorLight);
+ QTest::newRow("import controls, env var fallback, dark") << "applicationWindowWithButton.qml"
+ << "FileSystemStyle" << EnvVar << Qt::ColorScheme::Dark
+ << QColor::fromRgb(0x0000ff) << QColor::fromRgba(materialBackgroundColorDark);
+
+ QTest::newRow("import style, qmldir fallback, light") << "importStyleWithQmlDirFallback.qml"
+ << "" << QmlDirImport << Qt::ColorScheme::Light
+ << QColor::fromRgb(0xff0000) << QColor::fromRgba(materialBackgroundColorLight);
+ QTest::newRow("import style, qmldir fallback, dark") << "importStyleWithQmlDirFallback.qml"
+ << "" << QmlDirImport << Qt::ColorScheme::Dark
+ << QColor::fromRgb(0xff0000) << QColor::fromRgba(materialBackgroundColorDark);
+}
+
+// Tests that a fallback style's (the Material style, in this case) theme settings
+// are respected for both run-time and compile-time style selection.
+void tst_StyleImports::fallbackStyleThemeRespected()
+{
+ QFETCH(QString, qmlFilePath);
+ QFETCH(QString, runtimeStyle);
+ QFETCH(FallbackMethod, fallbackMethod);
+ QFETCH(Qt::ColorScheme, colorScheme);
+ QFETCH(QColor, expectedButtonTextColor);
+ QFETCH(QColor, expectedWindowColor);
+
+ const char *materialThemeEnvVarName = "QT_QUICK_CONTROLS_MATERIAL_THEME";
+ const QString originalMaterialTheme = qgetenv(materialThemeEnvVarName);
+ qputenv(materialThemeEnvVarName, colorScheme == Qt::ColorScheme::Light ? "Light" : "Dark");
+
+ // Only set this if it's not empty, because setting an empty style
+ // will still cause it be resolved and we end up using the platform default.
+ if (!runtimeStyle.isEmpty())
+ QQuickStyle::setStyle(runtimeStyle);
+
+ const char *fallbackStyleEnvVarName = "QT_QUICK_CONTROLS_FALLBACK_STYLE";
+ const QString originalFallbackStyle = qgetenv(fallbackStyleEnvVarName);
+ if (fallbackMethod == EnvVar)
+ qputenv(fallbackStyleEnvVarName, "Material");
+
+ auto cleanup = qScopeGuard([&]() {
+ qputenv(materialThemeEnvVarName, qPrintable(originalMaterialTheme));
+ qputenv(fallbackStyleEnvVarName, qPrintable(originalFallbackStyle));
+ });
+
+ QQuickControlsApplicationHelper helper(this, qmlFilePath, {},
+ QStringList() << dataDirectory() + QLatin1String("/styles"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ auto button = helper.window->property("button").value<QQuickButton*>();
+ QVERIFY(button);
+ // contentItem should be a label with "salmon" text color.
+ QCOMPARE(button->contentItem()->property("color").value<QColor>(), expectedButtonTextColor);
+ QCOMPARE(helper.appWindow->color(), expectedWindowColor);
+
+ // If using run-time style selection, check that QQuickStyle reports the correct values.
+ // QQuickStyle is not supported when using compile-time style selection.
+ if (!runtimeStyle.isEmpty()) {
+ QCOMPARE(QQuickStyle::name(), runtimeStyle);
+ QCOMPARE(QQuickStylePrivate::fallbackStyle(), "Material");
+ }
+}
+
void tst_StyleImports::attachedTypesAvailable_data()
{
QTest::addColumn<QString>("import");
diff --git a/tests/auto/quickcontrols/styleimportscompiletimematerial/CMakeLists.txt b/tests/auto/quickcontrols/styleimportscompiletimematerial/CMakeLists.txt
index 6e7f22da64..6352b778d3 100644
--- a/tests/auto/quickcontrols/styleimportscompiletimematerial/CMakeLists.txt
+++ b/tests/auto/quickcontrols/styleimportscompiletimematerial/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_styleimportscompiletimematerial LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/styleimportscompiletimematerial/data/importMaterialStyleWithoutControls.qml b/tests/auto/quickcontrols/styleimportscompiletimematerial/data/importMaterialStyleWithoutControls.qml
index 2c8a8dadfd..0d5300ec27 100644
--- a/tests/auto/quickcontrols/styleimportscompiletimematerial/data/importMaterialStyleWithoutControls.qml
+++ b/tests/auto/quickcontrols/styleimportscompiletimematerial/data/importMaterialStyleWithoutControls.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick.Controls.Material
diff --git a/tests/auto/quickcontrols/styleimportscompiletimematerial/tst_styleimportscompiletimematerial.cpp b/tests/auto/quickcontrols/styleimportscompiletimematerial/tst_styleimportscompiletimematerial.cpp
index dc582ea6c2..5c78b97a8d 100644
--- a/tests/auto/quickcontrols/styleimportscompiletimematerial/tst_styleimportscompiletimematerial.cpp
+++ b/tests/auto/quickcontrols/styleimportscompiletimematerial/tst_styleimportscompiletimematerial.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qregularexpression.h>
#include <QtTest/qtest.h>
diff --git a/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/CMakeLists.txt b/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/CMakeLists.txt
index 6e56e6a96e..e1f88295ce 100644
--- a/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/CMakeLists.txt
+++ b/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_styleimportscompiletimeqmlonly LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/data/QmlOnly/Button.qml b/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/data/QmlOnly/Button.qml
index 16b83c93d3..3e0fefed02 100644
--- a/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/data/QmlOnly/Button.qml
+++ b/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/data/QmlOnly/Button.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Templates as T
diff --git a/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/data/importQmlOnlyStyleWithoutControls.qml b/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/data/importQmlOnlyStyleWithoutControls.qml
index 4d0492232c..3298a4ac41 100644
--- a/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/data/importQmlOnlyStyleWithoutControls.qml
+++ b/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/data/importQmlOnlyStyleWithoutControls.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QmlOnly
diff --git a/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/tst_styleimportscompiletimeqmlonly.cpp b/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/tst_styleimportscompiletimeqmlonly.cpp
index ec5d51f846..dae8424ec8 100644
--- a/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/tst_styleimportscompiletimeqmlonly.cpp
+++ b/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/tst_styleimportscompiletimeqmlonly.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qregularexpression.h>
#include <QtTest/qtest.h>
diff --git a/tests/auto/quickcontrols/translation/CMakeLists.txt b/tests/auto/quickcontrols/translation/CMakeLists.txt
index 745262cdcc..cfb2ca6a0a 100644
--- a/tests/auto/quickcontrols/translation/CMakeLists.txt
+++ b/tests/auto/quickcontrols/translation/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_translation LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/translation/data/comboBox.qml b/tests/auto/quickcontrols/translation/data/comboBox.qml
index e6a58787ae..f410b7f586 100644
--- a/tests/auto/quickcontrols/translation/data/comboBox.qml
+++ b/tests/auto/quickcontrols/translation/data/comboBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/translation/data/dialogButtonBox.qml b/tests/auto/quickcontrols/translation/data/dialogButtonBox.qml
index ababa65019..11e3260e4b 100644
--- a/tests/auto/quickcontrols/translation/data/dialogButtonBox.qml
+++ b/tests/auto/quickcontrols/translation/data/dialogButtonBox.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/translation/data/dialogButtonBoxWithCustomButtons.qml b/tests/auto/quickcontrols/translation/data/dialogButtonBoxWithCustomButtons.qml
index 6e8dca8ad5..b58e58f2e7 100644
--- a/tests/auto/quickcontrols/translation/data/dialogButtonBoxWithCustomButtons.qml
+++ b/tests/auto/quickcontrols/translation/data/dialogButtonBoxWithCustomButtons.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/translation/data/stackView.qml b/tests/auto/quickcontrols/translation/data/stackView.qml
index 44d85c2ea1..85d5c41ce5 100644
--- a/tests/auto/quickcontrols/translation/data/stackView.qml
+++ b/tests/auto/quickcontrols/translation/data/stackView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/translation/tst_translation.cpp b/tests/auto/quickcontrols/translation/tst_translation.cpp
index f0798d0367..abd30a7ddb 100644
--- a/tests/auto/quickcontrols/translation/tst_translation.cpp
+++ b/tests/auto/quickcontrols/translation/tst_translation.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qsignalspy.h>
#include <QtTest/qtest.h>
diff --git a/tests/auto/quickdialogs/qquickcolordialogimpl/CMakeLists.txt b/tests/auto/quickdialogs/qquickcolordialogimpl/CMakeLists.txt
index c046db0124..f7e49089fd 100644
--- a/tests/auto/quickdialogs/qquickcolordialogimpl/CMakeLists.txt
+++ b/tests/auto/quickdialogs/qquickcolordialogimpl/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickcolordialogimpl LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialog.qml b/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialog.qml
index c7be270a6d..5b0361622f 100644
--- a/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialog.qml
+++ b/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindow.qml b/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindow.qml
new file mode 100644
index 0000000000..4794d20106
--- /dev/null
+++ b/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindow.qml
@@ -0,0 +1,27 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+
+Rectangle {
+ width: 480
+ height: 640
+ color: dialog.selectedColor
+
+ property alias dialog: dialog
+
+ function doneAccepted() {
+ dialog.done(ColorDialog.Accepted)
+ }
+
+ function doneRejected() {
+ dialog.done(ColorDialog.Rejected)
+ }
+
+ ColorDialog {
+ id: dialog
+ objectName: "ColorDialog"
+ }
+}
diff --git a/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindowVisibleTrue.qml b/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindowVisibleTrue.qml
new file mode 100644
index 0000000000..9a5a4d6f4d
--- /dev/null
+++ b/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindowVisibleTrue.qml
@@ -0,0 +1,28 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+
+Rectangle {
+ width: 480
+ height: 640
+ color: dialog.selectedColor
+
+ property alias dialog: dialog
+
+ function doneAccepted() {
+ dialog.done(ColorDialog.Accepted)
+ }
+
+ function doneRejected() {
+ dialog.done(ColorDialog.Rejected)
+ }
+
+ ColorDialog {
+ id: dialog
+ objectName: "ColorDialog"
+ visible: true
+ }
+}
diff --git a/tests/auto/quickdialogs/qquickcolordialogimpl/data/windowSwapping.qml b/tests/auto/quickdialogs/qquickcolordialogimpl/data/windowSwapping.qml
new file mode 100644
index 0000000000..d84e52ca9f
--- /dev/null
+++ b/tests/auto/quickdialogs/qquickcolordialogimpl/data/windowSwapping.qml
@@ -0,0 +1,58 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+
+Window {
+ width: 480
+ height: 640
+
+ property alias dialog: dialog
+
+ function getSubWindow1 () {
+ return subwindow1
+ }
+
+ function getSubWindow2 () {
+ return subwindow2
+ }
+
+ function goToSubWindow1() {
+ dialog.close()
+ dialog.parentWindow = subwindow1
+ dialog.open()
+ }
+
+ function goToSubWindow2() {
+ dialog.close()
+ dialog.parentWindow = subwindow2
+ dialog.open()
+ }
+
+ function resetParentWindow() {
+ dialog.close()
+ dialog.parentWindow = undefined
+ dialog.open()
+ }
+
+ Window {
+ id: subwindow1
+ width: 480
+ height: 640
+ visible: true
+ }
+
+ Window {
+ id: subwindow2
+ width: 480
+ height: 640
+ visible: true
+ }
+
+ ColorDialog {
+ id: dialog
+ objectName: "ColorDialog"
+ }
+}
diff --git a/tests/auto/quickdialogs/qquickcolordialogimpl/tst_qquickcolordialogimpl.cpp b/tests/auto/quickdialogs/qquickcolordialogimpl/tst_qquickcolordialogimpl.cpp
index c8a1eb2231..786d0ca207 100644
--- a/tests/auto/quickdialogs/qquickcolordialogimpl/tst_qquickcolordialogimpl.cpp
+++ b/tests/auto/quickdialogs/qquickcolordialogimpl/tst_qquickcolordialogimpl.cpp
@@ -1,9 +1,10 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtQuickTest/quicktest.h>
#include <QtTest/qsignalspy.h>
+#include <QtQuick/qquickview.h>
#include <QtQuick/private/qquicklistview_p.h>
#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
#include <QtQuickControlsTestUtils/private/dialogstestutils_p.h>
@@ -18,6 +19,7 @@
#include <QtQuickTemplates2/private/qquicklabel_p.h>
#include <QtQuickTemplates2/private/qquickoverlay_p.h>
#include <QtQuickTemplates2/private/qquickslider_p.h>
+#include <QtQuickTemplates2/private/qquickbutton_p.h>
#include <QtQuickControls2/qquickstyle.h>
#include <qpa/qplatformintegration.h>
@@ -53,6 +55,9 @@ private slots:
void changeColorFromTextFields();
void windowTitle_data();
void windowTitle();
+ void workingInsideQQuickViewer_data();
+ void workingInsideQQuickViewer();
+ void dialogCanMoveBetweenWindows();
private:
bool closePopup(DialogTestHelper<QQuickColorDialog, QQuickColorDialogImpl> *dialogHelper,
@@ -127,6 +132,23 @@ void tst_QQuickColorDialogImpl::defaultValues()
QVERIFY(dialogHelper.openDialog());
QVERIFY(alphaSlider->isVisible());
+ const bool wayland = QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive) == 0;
+ const bool offscreen = qgetenv("QT_QPA_PLATFORM").compare(QLatin1String("offscreen"), Qt::CaseInsensitive) == 0;
+
+ if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ScreenWindowGrabbing) && !wayland && !offscreen) {
+ QQuickButton *eyeDropperButton = dialogHelper.quickDialog->findChild<QQuickButton *>("eyeDropperButton");
+ QVERIFY(eyeDropperButton);
+
+ QVERIFY2(eyeDropperButton->isVisible(),
+ "The Eye Dropper Button should be visible unless the NoEyeDropperButton option has "
+ "explicitly been set");
+ dialogHelper.dialog->close();
+ QTRY_VERIFY(!dialogHelper.isQuickDialogOpen());
+ dialogHelper.dialog->setOptions(QColorDialogOptions::NoEyeDropperButton);
+ QVERIFY(dialogHelper.openDialog());
+ QVERIFY(!eyeDropperButton->isVisible());
+ }
+
QVERIFY(dialogHelper.quickDialog->isHsl());
QCOMPARE(dialogHelper.quickDialog->alpha(), 1.0);
QCOMPARE(dialogHelper.quickDialog->hue(), 0.0);
@@ -352,17 +374,17 @@ void tst_QQuickColorDialogImpl::changeColorFromTextFields_data()
QTest::newRow("rgbRed") << ColorSpec::Rgb << "255" << "100" << QColor(100, 255, 255);
QTest::newRow("rgbGreen") << ColorSpec::Rgb << "255" << "0" << QColorConstants::Magenta;
QTest::newRow("rgbBlue") << ColorSpec::Rgb << "255" << "200" << QColor(255, 255, 200);
- QTest::newRow("rgbAlpha") << ColorSpec::Rgb << "100%" << "50%" << QColor::fromRgbF(1.0, 1.0, 1.0, 0.5);
+ QTest::newRow("rgbAlpha") << ColorSpec::Rgb << "100%" << "50%" << QColor::fromRgbF(1.0f, 1.0f, 1.0f, 0.5f);
- QTest::newRow("hsvHue") << ColorSpec::Hsv << "0°" << "60°" << QColor::fromHsvF(.2, 0.0, 1.0);
- QTest::newRow("hsvSaturation") << ColorSpec::Hsv << "0%" << "50%" << QColor::fromHsvF(0.0, 0.5, 1.0);
- QTest::newRow("hsvValue") << ColorSpec::Hsv << "100%" << "90%" << QColor::fromHsvF(0.0, 0.0, 0.9, 1.0);
- QTest::newRow("hsvAlpha") << ColorSpec::Hsv << "100%" << "40%" << QColor::fromHsvF(0.0, 0.0, 1.0, 0.4);
+ QTest::newRow("hsvHue") << ColorSpec::Hsv << "0°" << "60°" << QColor::fromHsvF(.2f, 0.0f, 1.0f);
+ QTest::newRow("hsvSaturation") << ColorSpec::Hsv << "0%" << "50%" << QColor::fromHsvF(0.0f, 0.5f, 1.0f);
+ QTest::newRow("hsvValue") << ColorSpec::Hsv << "100%" << "90%" << QColor::fromHsvF(0.0f, 0.0f, 0.9f, 1.0f);
+ QTest::newRow("hsvAlpha") << ColorSpec::Hsv << "100%" << "40%" << QColor::fromHsvF(0.0f, 0.0f, 1.0f, 0.4f);
- QTest::newRow("hslHue") << ColorSpec::Hsl << "0°" << "90°" << QColor::fromHslF(.25, 1.0, 1.0);
- QTest::newRow("hslSaturation") << ColorSpec::Hsl << "0%" << "40%" << QColor::fromHslF(0.0, 0.4, 1.0);
- QTest::newRow("hslLightness") << ColorSpec::Hsl << "100%" << "80%" << QColor::fromHslF(0.0, 0.0, 0.8, 1.0);
- QTest::newRow("hslAlpha") << ColorSpec::Hsl << "100%" << "60%" << QColor::fromHslF(0.0, 0.0, 1.0, 0.6);
+ QTest::newRow("hslHue") << ColorSpec::Hsl << "0°" << "90°" << QColor::fromHslF(.25f, 1.0f, 1.0f);
+ QTest::newRow("hslSaturation") << ColorSpec::Hsl << "0%" << "40%" << QColor::fromHslF(0.0f, 0.4f, 1.0f);
+ QTest::newRow("hslLightness") << ColorSpec::Hsl << "100%" << "80%" << QColor::fromHslF(0.0f, 0.0f, 0.8f, 1.0f);
+ QTest::newRow("hslAlpha") << ColorSpec::Hsl << "100%" << "60%" << QColor::fromHslF(0.0f, 0.0f, 1.0f, 0.6f);
}
void tst_QQuickColorDialogImpl::changeColorFromTextFields()
@@ -456,6 +478,60 @@ void tst_QQuickColorDialogImpl::windowTitle()
CLOSE_DIALOG("Ok");
}
+void tst_QQuickColorDialogImpl::workingInsideQQuickViewer_data()
+{
+ QTest::addColumn<bool>("initialVisible");
+ QTest::addColumn<QString>("urlToQmlFile");
+ QTest::newRow("visible: false") << false << "colorDialogWithoutWindow.qml";
+ QTest::newRow("visible: true") << true << "colorDialogWithoutWindowVisibleTrue.qml";
+}
+
+void tst_QQuickColorDialogImpl::workingInsideQQuickViewer() // QTBUG-106598
+{
+ QFETCH(bool, initialVisible);
+ QFETCH(QString, urlToQmlFile);
+
+ QQuickView dialogView;
+ dialogView.setSource(testFileUrl(urlToQmlFile));
+ dialogView.show();
+
+ auto dialog = dialogView.findChild<QQuickColorDialog *>("ColorDialog");
+ QVERIFY(dialog);
+ QCOMPARE(dialog->isVisible(), initialVisible);
+
+ dialog->open();
+ QVERIFY(dialog->isVisible());
+}
+
+void tst_QQuickColorDialogImpl::dialogCanMoveBetweenWindows()
+{
+ DialogTestHelper<QQuickColorDialog, QQuickColorDialogImpl> dialogHelper(this, "windowSwapping.qml");
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ QCOMPARE(dialogHelper.quickDialog->parent(), dialogHelper.window());
+ QVariant subWindow1;
+ QVariant subWindow2;
+
+ QMetaObject::invokeMethod(dialogHelper.window(), "getSubWindow1", Q_RETURN_ARG(QVariant, subWindow1));
+ QMetaObject::invokeMethod(dialogHelper.window(), "getSubWindow2", Q_RETURN_ARG(QVariant, subWindow2));
+
+ // Confirm that the dialog can swap to different windows
+ QMetaObject::invokeMethod(dialogHelper.window(), "goToSubWindow1");
+ QCOMPARE(dialogHelper.dialog->parentWindow(), qvariant_cast<QQuickWindow *>(subWindow1));
+
+ QMetaObject::invokeMethod(dialogHelper.window(), "goToSubWindow2");
+ QCOMPARE(dialogHelper.dialog->parentWindow(), qvariant_cast<QQuickWindow *>(subWindow2));
+
+ QMetaObject::invokeMethod(dialogHelper.window(), "resetParentWindow");
+ QCOMPARE(dialogHelper.quickDialog->parent(), dialogHelper.window());
+
+ CLOSE_DIALOG("Ok");
+}
+
QTEST_MAIN(tst_QQuickColorDialogImpl)
#include "tst_qquickcolordialogimpl.moc"
diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/CMakeLists.txt b/tests/auto/quickdialogs/qquickfiledialogimpl/CMakeLists.txt
index c5f9bdb7f6..fa6888a537 100644
--- a/tests/auto/quickdialogs/qquickfiledialogimpl/CMakeLists.txt
+++ b/tests/auto/quickdialogs/qquickfiledialogimpl/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickfiledialogimpl LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/data/acceptRejectLabel.qml b/tests/auto/quickdialogs/qquickfiledialogimpl/data/acceptRejectLabel.qml
index d164acb986..4aa4d9dfe0 100644
--- a/tests/auto/quickdialogs/qquickfiledialogimpl/data/acceptRejectLabel.qml
+++ b/tests/auto/quickdialogs/qquickfiledialogimpl/data/acceptRejectLabel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindAllTxtHtmlNameFilters.qml b/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindAllTxtHtmlNameFilters.qml
index 4e13824df6..9356a6e93a 100644
--- a/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindAllTxtHtmlNameFilters.qml
+++ b/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindAllTxtHtmlNameFilters.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindCurrentFolder.qml b/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindCurrentFolder.qml
index 78af831403..367decb18d 100644
--- a/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindCurrentFolder.qml
+++ b/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindCurrentFolder.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindTitle.qml b/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindTitle.qml
index 0695d44a2a..4df73c6a9e 100644
--- a/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindTitle.qml
+++ b/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindTitle.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindTxtHtmlNameFilters.qml b/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindTxtHtmlNameFilters.qml
index 4cb84d0ffb..fbdbd406a0 100644
--- a/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindTxtHtmlNameFilters.qml
+++ b/tests/auto/quickdialogs/qquickfiledialogimpl/data/bindTxtHtmlNameFilters.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/data/fileDialog.qml b/tests/auto/quickdialogs/qquickfiledialogimpl/data/fileDialog.qml
index a863e10129..104b0449f0 100644
--- a/tests/auto/quickdialogs/qquickfiledialogimpl/data/fileDialog.qml
+++ b/tests/auto/quickdialogs/qquickfiledialogimpl/data/fileDialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/data/setSelectedFile.qml b/tests/auto/quickdialogs/qquickfiledialogimpl/data/setSelectedFile.qml
index 62ef23fff8..e0c13fdff2 100644
--- a/tests/auto/quickdialogs/qquickfiledialogimpl/data/setSelectedFile.qml
+++ b/tests/auto/quickdialogs/qquickfiledialogimpl/data/setSelectedFile.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp b/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp
index 31c2a93d1c..f7f2bd8c85 100644
--- a/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp
+++ b/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qloggingcategory.h>
#include <QtTest/qtest.h>
@@ -89,8 +89,20 @@ private slots:
void setSelectedFile();
void selectNewFileViaTextField_data();
void selectNewFileViaTextField();
+ void selectExistingFileShouldWarnUserWhenFileModeEqualsSaveFile();
+ void fileNameTextFieldOnlyChangesWhenSelectingFiles();
+ void setSchemeForSelectedFile();
private:
+ enum DelegateOrderPolicy
+ {
+ ShowDirectoriesFirst,
+ ShowFilesFirst
+ };
+
+ QStringList tempDirExpectedVisibleFiles(DelegateOrderPolicy order) const;
+ QStringList tempSubDirExpectedVisibleFiles(DelegateOrderPolicy order) const;
+
QTemporaryDir tempDir;
QScopedPointer<QFile> tempFile1;
QScopedPointer<QFile> tempFile2;
@@ -106,10 +118,26 @@ private:
QDir oldCurrentDir;
+#if QT_CONFIG(shortcut)
const QKeySequence goUpKeySequence = QKeySequence(Qt::ALT | Qt::Key_Up);
const QKeySequence editPathKeySequence = QKeySequence(Qt::CTRL | Qt::Key_L);
+#endif
};
+QStringList tst_QQuickFileDialogImpl::tempDirExpectedVisibleFiles(DelegateOrderPolicy order) const
+{
+ return order == ShowDirectoriesFirst
+ ? QStringList { tempSubDir.path(), tempFile1->fileName(), tempFile2->fileName() }
+ : QStringList { tempFile1->fileName(), tempFile2->fileName(), tempSubDir.path() };
+}
+
+QStringList tst_QQuickFileDialogImpl::tempSubDirExpectedVisibleFiles(DelegateOrderPolicy order) const
+{
+ return order == ShowDirectoriesFirst
+ ? QStringList { tempSubSubDir.path(), tempSubFile1->fileName(), tempSubFile2->fileName() }
+ : QStringList { tempSubFile1->fileName(), tempSubFile2->fileName(), tempSubSubDir.path() };
+}
+
// We don't want to fail on warnings until QTBUG-98964 is fixed,
// as we deliberately prevent deferred execution in some of the tests here,
// which causes warnings.
@@ -135,13 +163,13 @@ void tst_QQuickFileDialogImpl::initTestCase()
/*
Create a couple of files within the temporary directory. The structure is:
- [temp directory]
- ├── sub-dir
- │ ├── sub-sub-dir
- │ ├── sub-file1.txt
- │ └── sub-file2.txt
- ├── file1.txt
- └── file2.txt
+ [temp directory] (tempDir)
+ ├── sub-dir (tempSubDir)
+ │ ├── sub-sub-dir (tempSubSubDir)
+ │ ├── sub-file1.txt (tempSubFile1)
+ │ └── sub-file2.txt (tempSubFile2)
+ ├── file1.txt (tempFile1)
+ └── file2.txt (tempFile2)
*/
tempSubDir = QDir(tempDir.path());
QVERIFY2(tempSubDir.mkdir("sub-dir"), qPrintable(QString::fromLatin1(
@@ -232,8 +260,8 @@ void tst_QQuickFileDialogImpl::cleanupTestCase()
QTRY_VERIFY(findViewDelegateItem(dialogHelper.fileDialogListView, expectedCurrentIndex, fileDelegate)); \
QVERIFY2(fileDelegate->hasActiveFocus(), qPrintable(QString::fromLatin1( \
"Expected delegate at index %1 to have focus, but %2 has it") \
- .arg(QString::number(expectedCurrentIndex)) \
- .arg(QDebug::toString(dialogHelper.window()->activeFocusItem())))); \
+ .arg(QString::number(expectedCurrentIndex), \
+ QDebug::toString(dialogHelper.window()->activeFocusItem())))); \
QVERIFY(fileDelegate->isHighlighted()); \
}
@@ -365,6 +393,7 @@ void tst_QQuickFileDialogImpl::chooseFileViaTextEdit()
// below fail due to it being hidden when it loses activeFocus.
VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), 0);
+#if QT_CONFIG(shortcut)
// Get the text edit visible with Ctrl+L.
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
@@ -384,6 +413,7 @@ void tst_QQuickFileDialogImpl::chooseFileViaTextEdit()
COMPARE_URLS(dialogHelper.dialog->selectedFiles(), { QUrl::fromLocalFile(tempFile2->fileName()) });
QVERIFY(!dialogHelper.dialog->isVisible());
QTRY_VERIFY(!dialogHelper.quickDialog->isVisible());
+#endif
}
void tst_QQuickFileDialogImpl::chooseFileViaEnter()
@@ -418,8 +448,8 @@ void tst_QQuickFileDialogImpl::bindCurrentFolder_data()
const auto tempSubDirUrl = QUrl::fromLocalFile(tempSubDir.path());
const auto tempSubFile1Url = QUrl::fromLocalFile(tempSubFile1->fileName());
- const QStringList currentDirFiles = { tempSubDir.path(), tempFile1->fileName(), tempFile2->fileName() };
- const QStringList tempSubDirFiles = { tempSubSubDir.path(), tempSubFile1->fileName(), tempSubFile2->fileName() };
+ const QStringList currentDirFiles = tempDirExpectedVisibleFiles(ShowDirectoriesFirst);
+ const QStringList tempSubDirFiles = tempSubDirExpectedVisibleFiles(ShowDirectoriesFirst);
// Setting the folder to "sub-dir" should result in "sub-file1.txt" and "sub-file2.txt" being visible.
QTest::addRow("sub-dir") << tempSubDirUrl << tempSubDirUrl << tempSubDirFiles;
@@ -505,9 +535,7 @@ void tst_QQuickFileDialogImpl::changeFolderViaDoubleClick()
QTRY_VERIFY(findViewDelegateItem(dialogHelper.fileDialogListView, subDirIndex, subDirDelegate));
COMPARE_URL(subDirDelegate->file(), QUrl::fromLocalFile(tempSubDir.path()));
QVERIFY(doubleClickButton(subDirDelegate));
- const QStringList expectedVisibleFiles = showDirsFirst
- ? QStringList { tempSubSubDir.path(), tempSubFile1->fileName(), tempSubFile2->fileName() }
- : QStringList { tempSubFile1->fileName(), tempSubFile2->fileName(), tempSubSubDir.path() };
+ const QStringList expectedVisibleFiles = tempSubDirExpectedVisibleFiles(showDirsFirst ? ShowDirectoriesFirst : ShowFilesFirst);
QString failureMessage;
QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView, expectedVisibleFiles, failureMessage), qPrintable(failureMessage));
// The first file in the directory should now be selected.
@@ -529,9 +557,11 @@ void tst_QQuickFileDialogImpl::chooseFolderViaTextEdit()
// See comment in chooseFileViaTextEdit for why we check for this.
VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), 0);
+#if QT_CONFIG(shortcut)
// Get the text edit visible with Ctrl+L.
const auto editPathKeySequence = QKeySequence(Qt::CTRL | Qt::Key_L);
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+#endif
auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
QVERIFY(breadcrumbBar);
QVERIFY(breadcrumbBar->textField()->isVisible());
@@ -544,6 +574,9 @@ void tst_QQuickFileDialogImpl::chooseFolderViaTextEdit()
// Hit enter to accept.
QTest::keyClick(dialogHelper.window(), Qt::Key_Return);
+ QString failureMessage;
+ QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView,
+ tempSubDirExpectedVisibleFiles(ShowDirectoriesFirst), failureMessage), qPrintable(failureMessage));
// The first file in the directory should be selected, which is "sub-sub-dir".
// Note that the TextEdit will still have focus, so we can't use VERIFY_FILE_SELECTED_AND_FOCUSED.
VERIFY_FILE_SELECTED(QUrl::fromLocalFile(tempSubDir.path()), QUrl::fromLocalFile(tempSubSubDir.path()));
@@ -566,9 +599,9 @@ void tst_QQuickFileDialogImpl::chooseFolderViaEnter()
// Select the delegate by pressing enter.
QTest::keyClick(dialogHelper.window(), Qt::Key_Return);
- const QStringList expectedVisibleFiles = { tempSubSubDir.path(), tempSubFile1->fileName(), tempSubFile2->fileName() };
QString failureMessage;
- QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView, expectedVisibleFiles, failureMessage), qPrintable(failureMessage));
+ QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView,
+ tempSubDirExpectedVisibleFiles(ShowDirectoriesFirst), failureMessage), qPrintable(failureMessage));
// The first file in the new directory should be selected, which is "sub-sub-dir".
VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempSubDir.path()), QUrl::fromLocalFile(tempSubSubDir.path()), 0);
// Since we only chose a folder, the dialog should still be open.
@@ -587,8 +620,10 @@ void tst_QQuickFileDialogImpl::chooseFileAndThenFolderViaTextEdit()
// See comment in chooseFileViaTextEdit for why we check for this.
VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), 0);
+#if QT_CONFIG(shortcut)
// Get the text edit visible with Ctrl+L.
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+#endif
auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
QVERIFY(breadcrumbBar);
QVERIFY(breadcrumbBar->textField()->isVisible());
@@ -615,8 +650,10 @@ void tst_QQuickFileDialogImpl::chooseFileAndThenFolderViaTextEdit()
// The breadcrumbs should be visible after opening, not the text edit.
QVERIFY(!breadcrumbBar->textField()->isVisible());
+#if QT_CONFIG(shortcut)
// Get the text edit visible with Ctrl+L.
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+#endif
QVERIFY(breadcrumbBar->textField()->isVisible());
// The text edit should show the directory that contains the last file that was selected.
QCOMPARE(breadcrumbBar->textField()->text(), tempDir.path());
@@ -628,6 +665,9 @@ void tst_QQuickFileDialogImpl::chooseFileAndThenFolderViaTextEdit()
// Hit enter to accept.
QTest::keyClick(dialogHelper.window(), Qt::Key_Return);
+ QString failureMessage;
+ QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView,
+ tempSubDirExpectedVisibleFiles(ShowDirectoriesFirst), failureMessage), qPrintable(failureMessage));
// The first file in the directory should be selected, which is "sub-sub-dir".
// Note that the TextEdit will still have focus, so we can't use VERIFY_FILE_SELECTED_AND_FOCUSED.
VERIFY_FILE_SELECTED(QUrl::fromLocalFile(tempSubDir.path()), QUrl::fromLocalFile(tempSubSubDir.path()));
@@ -647,8 +687,10 @@ void tst_QQuickFileDialogImpl::cancelDialogWhileTextEditHasFocus()
// See comment in chooseFileViaTextEdit for why we check for this.
VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), 0);
+#if QT_CONFIG(shortcut)
// Get the text edit visible with Ctrl+L.
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+#endif
auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
QVERIFY(breadcrumbBar);
QVERIFY(breadcrumbBar->textField()->hasActiveFocus());
@@ -727,9 +769,13 @@ void tst_QQuickFileDialogImpl::goUp()
QVERIFY(QQuickTest::qWaitForPolish(barListView));
QVERIFY(clickButton(breadcrumbBar->upButton()));
// The previous directory that we were in should now be selected (matches e.g. Windows and Ubuntu).
+ QString failureMessage;
+ QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView,
+ tempDirExpectedVisibleFiles(showDirsFirst ? ShowDirectoriesFirst : ShowFilesFirst), failureMessage), qPrintable(failureMessage));
int expectedCurrentIndex = showDirsFirst ? 0 : 2;
VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), expectedCurrentIndex);
+#if QT_CONFIG(shortcut)
// Go up a directory via the keyboard shortcut.
QDir tempParentDir(tempDir.path());
QVERIFY(tempParentDir.cdUp());
@@ -742,6 +788,7 @@ void tst_QQuickFileDialogImpl::goUp()
QVERIFY(expectedCurrentIndex != -1);
VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempParentDir.path()), QUrl::fromLocalFile(tempDir.path()), expectedCurrentIndex);
}
+#endif
}
void tst_QQuickFileDialogImpl::goUpWhileTextEditHasFocus()
@@ -753,8 +800,10 @@ void tst_QQuickFileDialogImpl::goUpWhileTextEditHasFocus()
// See comment in chooseFileViaTextEdit for why we check for this.
VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempSubDir.path()), QUrl::fromLocalFile(tempSubSubDir.path()), 0);
+#if QT_CONFIG(shortcut)
// Get the text edit visible with Ctrl+L.
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+#endif
auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
QVERIFY(breadcrumbBar);
QVERIFY(breadcrumbBar->textField()->hasActiveFocus());
@@ -821,6 +870,7 @@ void tst_QQuickFileDialogImpl::goUpIntoLargeFolder()
VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(largeTempDirLargeSubDir.path()),
QUrl::fromLocalFile(largeTempDirLargeSubDir.path() + "/sub-dir000"), 0);
+#if QT_CONFIG(shortcut)
// Go up a directory via the keyboard shortcut.
QTest::keySequence(dialogHelper.window(), goUpKeySequence);
QString failureMessage;
@@ -828,6 +878,7 @@ void tst_QQuickFileDialogImpl::goUpIntoLargeFolder()
largeTempDirPaths, failureMessage), qPrintable(failureMessage));
VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(largeTempDir.path()),
QUrl::fromLocalFile(largeTempDirLargeSubDir.path()), largeTempDirLargeSubDirIndex);
+#endif
}
void tst_QQuickFileDialogImpl::keyAndShortcutHandling()
@@ -837,16 +888,20 @@ void tst_QQuickFileDialogImpl::keyAndShortcutHandling()
OPEN_QUICK_DIALOG();
VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), 0);
+#if QT_CONFIG(shortcut)
// Get the text edit visible with Ctrl+L.
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+#endif
auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
QVERIFY(breadcrumbBar);
QVERIFY(breadcrumbBar->textField()->isVisible());
QCOMPARE(breadcrumbBar->textField()->text(), dialogHelper.dialog->currentFolder().toLocalFile());
QCOMPARE(breadcrumbBar->textField()->selectedText(), breadcrumbBar->textField()->text());
+#if QT_CONFIG(shortcut)
// Ctrl+L shouldn't hide it.
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+#endif
QVERIFY(breadcrumbBar->textField()->isVisible());
// Cancel it with the escape key.
@@ -854,8 +909,10 @@ void tst_QQuickFileDialogImpl::keyAndShortcutHandling()
QVERIFY(!breadcrumbBar->textField()->isVisible());
QVERIFY(dialogHelper.dialog->isVisible());
+#if QT_CONFIG(shortcut)
// Make it visible.
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+#endif
QVERIFY(breadcrumbBar->textField()->isVisible());
// Cancel it with the escape key again.
@@ -878,7 +935,7 @@ void tst_QQuickFileDialogImpl::bindNameFilters()
// Only "sub-dir", "text1.txt" and "text2.txt" should be visible, since *.txt is the first filter.
QString failureMessage;
QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView,
- { tempSubDir.path(), tempFile1->fileName(), tempFile2->fileName() }, failureMessage), qPrintable(failureMessage));
+ tempDirExpectedVisibleFiles(ShowDirectoriesFirst), failureMessage), qPrintable(failureMessage));
}
void tst_QQuickFileDialogImpl::changeNameFilters()
@@ -929,7 +986,7 @@ void tst_QQuickFileDialogImpl::changeNameFilters()
// Only "sub-dir", "text1.txt" and "text2.txt" should be visible, since *.txt is the first filter.
QString failureMessage;
QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView,
- { tempSubDir.path(), tempFile1->fileName(), tempFile2->fileName() }, failureMessage), qPrintable(failureMessage));
+ tempDirExpectedVisibleFiles(ShowDirectoriesFirst), failureMessage), qPrintable(failureMessage));
// Open the ComboBox's popup.
const QQuickComboBox *comboBox = dialogHelper.quickDialog->findChild<QQuickComboBox*>();
@@ -964,7 +1021,7 @@ void tst_QQuickFileDialogImpl::changeNameFilters()
}
QTRY_VERIFY(!comboBox->popup()->isVisible());
QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView,
- { tempSubDir.path(), tempFile1->fileName(), tempFile2->fileName() }, failureMessage), qPrintable(failureMessage));
+ tempDirExpectedVisibleFiles(ShowDirectoriesFirst), failureMessage), qPrintable(failureMessage));
}
void tst_QQuickFileDialogImpl::changeNameFiltersAfterChangingFolder()
@@ -976,7 +1033,7 @@ void tst_QQuickFileDialogImpl::changeNameFiltersAfterChangingFolder()
// Go into the "sub-dir" folder.
QString failureMessage;
QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView,
- { tempSubDir.path(), tempFile1->fileName(), tempFile2->fileName() }, failureMessage), qPrintable(failureMessage));
+ tempDirExpectedVisibleFiles(ShowDirectoriesFirst), failureMessage), qPrintable(failureMessage));
QQuickFileDialogDelegate *subDirDelegate = nullptr;
QTRY_VERIFY(findViewDelegateItem(dialogHelper.fileDialogListView, 0, subDirDelegate));
QVERIFY(doubleClickButton(subDirDelegate));
@@ -1154,10 +1211,12 @@ void tst_QQuickFileDialogImpl::itemsDisabledWhenNecessary()
COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(anotherTempDir.path()));
COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(anotherTempDir.path()));
+#if QT_CONFIG(shortcut)
// Get the text edit visible with Ctrl+L. The Open button should now be disabled.
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
QVERIFY(breadcrumbBar->textField()->isVisible());
QCOMPARE(openButton->isEnabled(), false);
+#endif
// Hide it with the escape key. The Open button should now be enabled.
QTest::keyClick(dialogHelper.window(), Qt::Key_Escape);
@@ -1168,15 +1227,17 @@ void tst_QQuickFileDialogImpl::itemsDisabledWhenNecessary()
void tst_QQuickFileDialogImpl::fileMode_data()
{
QTest::addColumn<QQuickFileDialog::FileMode>("fileMode");
+ QTest::addColumn<QString>("acceptButtonText");
- QTest::newRow("OpenFile") << QQuickFileDialog::OpenFile;
- QTest::newRow("OpenFiles") << QQuickFileDialog::OpenFiles;
- QTest::newRow("SaveFile") << QQuickFileDialog::SaveFile;
+ QTest::newRow("OpenFile") << QQuickFileDialog::OpenFile << "Open";
+ QTest::newRow("OpenFiles") << QQuickFileDialog::OpenFiles << "Open";
+ QTest::newRow("SaveFile") << QQuickFileDialog::SaveFile << "Save";
}
void tst_QQuickFileDialogImpl::fileMode()
{
QFETCH(QQuickFileDialog::FileMode, fileMode);
+ QFETCH(QString, acceptButtonText);
// Open the dialog.
FileDialogTestHelper dialogHelper(this, "fileDialog.qml");
@@ -1191,13 +1252,13 @@ void tst_QQuickFileDialogImpl::fileMode()
COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile1->fileName()));
COMPARE_URLS(dialogHelper.dialog->currentFiles(), { QUrl::fromLocalFile(tempFile1->fileName()) });
- // All modes should support opening an existing file, so the Open button should be enabled.
+ // All modes should support opening an existing file, so the accept button should be enabled.
QVERIFY(dialogHelper.quickDialog->footer());
auto dialogButtonBox = dialogHelper.quickDialog->footer()->findChild<QQuickDialogButtonBox*>();
QVERIFY(dialogButtonBox);
- QQuickAbstractButton* openButton = findDialogButton(dialogButtonBox, "Open");
- QVERIFY(openButton);
- QCOMPARE(openButton->isEnabled(), true);
+ QQuickAbstractButton *acceptButton = findDialogButton(dialogButtonBox, acceptButtonText);
+ QVERIFY(acceptButton);
+ QCOMPARE(acceptButton->isEnabled(), true);
// Only the OpenFiles mode should allow multiple files to be selected, however.
QQuickFileDialogDelegate *tempFile2Delegate = nullptr;
@@ -1219,8 +1280,10 @@ void tst_QQuickFileDialogImpl::fileMode()
COMPARE_URLS(dialogHelper.dialog->currentFiles(), { QUrl::fromLocalFile(tempFile2->fileName()) });
}
+#if QT_CONFIG(shortcut)
// Get the text edit visible with Ctrl+L.
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+#endif
auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
QVERIFY(breadcrumbBar);
QVERIFY(breadcrumbBar->textField()->isVisible());
@@ -1342,6 +1405,9 @@ void tst_QQuickFileDialogImpl::setSelectedFile()
};
FileDialogTestHelper dialogHelper(
this, "setSelectedFile.qml", {}, initialProperties);
+
+ dialogHelper.dialog->setOptions(QFileDialogOptions::DontConfirmOverwrite);
+
OPEN_QUICK_DIALOG();
// The selected file should be what we set.
@@ -1396,6 +1462,7 @@ void tst_QQuickFileDialogImpl::selectNewFileViaTextField_data()
void tst_QQuickFileDialogImpl::selectNewFileViaTextField()
{
QFETCH(QQuickFileDialog::FileMode, fileMode);
+ QFETCH(QString, acceptButtonText);
// Open the dialog.
FileDialogTestHelper dialogHelper(this, "fileDialog.qml");
@@ -1415,22 +1482,208 @@ void tst_QQuickFileDialogImpl::selectNewFileViaTextField()
"The TextField for file name should only be visible when the FileMode is 'SaveFile'");
if (fileMode == QQuickFileDialog::SaveFile) {
+ QVERIFY(dialogHelper.quickDialog->footer());
+ auto dialogButtonBox = dialogHelper.quickDialog->footer()->findChild<QQuickDialogButtonBox*>();
+ QVERIFY(dialogButtonBox);
+ QQuickAbstractButton *acceptButton = findDialogButton(dialogButtonBox, acceptButtonText);
+ QVERIFY(acceptButton);
+ QCOMPARE(acceptButton->isEnabled(), false);
+
const QPoint textFieldCenterPos =
fileNameTextField->mapToScene({ fileNameTextField->width() / 2, fileNameTextField->height() / 2 }).toPoint();
QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, textFieldCenterPos);
QTRY_VERIFY(fileNameTextField->hasActiveFocus());
+ QCOMPARE(acceptButton->isEnabled(), false);
const QByteArray newFileName("foo.txt");
for (const auto &c : newFileName)
QTest::keyClick(dialogHelper.window(), c);
+ QCOMPARE(acceptButton->isEnabled(), true);
+
QTest::keyClick(dialogHelper.window(), Qt::Key_Enter);
+ QCOMPARE(acceptButton->isEnabled(), true);
QTRY_COMPARE(fileNameTextField->text(), newFileName);
QCOMPARE(dialogHelper.dialog->selectedFile().fileName(), newFileName);
+
+ QVERIFY(fileNameTextField->hasActiveFocus());
+ for (int i = 0; i < newFileName.size(); i++)
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Backspace);
+ QCOMPARE(acceptButton->isEnabled(), false);
}
}
+void tst_QQuickFileDialogImpl::selectExistingFileShouldWarnUserWhenFileModeEqualsSaveFile()
+{
+ FileDialogTestHelper dialogHelper(this, "fileDialog.qml");
+ dialogHelper.dialog->setFileMode(QQuickFileDialog::SaveFile);
+ dialogHelper.dialog->setSelectedFile(QUrl::fromLocalFile(tempFile1->fileName()));
+
+ OPEN_QUICK_DIALOG();
+ QQuickTest::qWaitForPolish(dialogHelper.window());
+
+ QSignalSpy acceptedSpy(dialogHelper.dialog, SIGNAL(accepted()));
+
+ auto *dialogButtonBox = dialogHelper.quickDialog->footer()->findChild<QQuickDialogButtonBox *>();
+ QVERIFY(dialogButtonBox);
+
+ auto *confirmationDialog = dialogHelper.quickDialog->findChild<QQuickDialog *>("confirmationDialog");
+ QVERIFY(confirmationDialog);
+
+ auto *openButton = dialogButtonBox->standardButton(QPlatformDialogHelper::Open);
+ QVERIFY(openButton);
+
+ auto *confirmationButtonBox = qobject_cast<QQuickDialogButtonBox *>(confirmationDialog->footer());
+ QVERIFY(confirmationButtonBox);
+
+ const QPoint openButtonCenterPos =
+ openButton->mapToScene({ openButton->width() / 2, openButton->height() / 2 }).toPoint();
+
+ QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, openButtonCenterPos);
+
+ QTRY_VERIFY(confirmationDialog->isOpened());
+ QVERIFY(dialogHelper.dialog->isVisible());
+
+ // Yes button should have focus by default
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Space, Qt::NoModifier);
+
+ QTRY_VERIFY(!confirmationDialog->isOpened());
+ QVERIFY(!dialogHelper.dialog->isVisible());
+ QCOMPARE(acceptedSpy.count(), 1);
+
+ // Try again, but click "No" this time.
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Enter, Qt::NoModifier);
+
+ QTRY_VERIFY(confirmationDialog->isOpened());
+ QVERIFY(dialogHelper.dialog->isVisible());
+
+ // Make No button trigger a clicked() event.
+ auto *confirmationNoButton = confirmationButtonBox->standardButton(QPlatformDialogHelper::No);
+ QVERIFY(confirmationNoButton);
+ QVERIFY(clickButton(confirmationNoButton));
+
+ // FileDialog is still opened
+ QTRY_VERIFY(!confirmationDialog->isOpened());
+ QVERIFY(dialogHelper.dialog->isVisible());
+ QCOMPARE(acceptedSpy.count(), 1);
+
+ // Try again
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Enter, Qt::NoModifier);
+
+ QTRY_VERIFY(confirmationDialog->isOpened());
+ QVERIFY(dialogHelper.dialog->isVisible());
+
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Space, Qt::NoModifier);
+
+ QTRY_VERIFY(!confirmationDialog->isOpened());
+ QVERIFY(!dialogHelper.dialog->isVisible());
+ QCOMPARE(acceptedSpy.count(), 2);
+
+ // Make sure that DontConfirmOverwrite works
+ dialogHelper.dialog->setOptions(QFileDialogOptions::DontConfirmOverwrite);
+
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Enter, Qt::NoModifier);
+ QTRY_VERIFY(!confirmationDialog->isOpened());
+ QVERIFY(!dialogHelper.dialog->isVisible());
+ QCOMPARE(acceptedSpy.count(), 3);
+}
+
+void tst_QQuickFileDialogImpl::fileNameTextFieldOnlyChangesWhenSelectingFiles()
+{
+ const auto tempSubFile1Url = QUrl::fromLocalFile(tempSubFile1->fileName());
+ const auto tempSubDirUrl = QUrl::fromLocalFile(tempSubDir.path());
+ const auto tempFile11Url = QUrl::fromLocalFile(tempFile1->fileName());
+
+ const QVariantMap initialProperties = {
+ { "tempFile1Url", QVariant::fromValue(tempSubFile1Url) },
+ { "fileMode", QVariant::fromValue(QQuickFileDialog::SaveFile) }
+ };
+ FileDialogTestHelper dialogHelper(this, "setSelectedFile.qml", {}, initialProperties);
+
+ OPEN_QUICK_DIALOG();
+ QQuickTest::qWaitForPolish(dialogHelper.window());
+
+ QQuickTextField *fileNameTextField =
+ dialogHelper.quickDialog->findChild<QQuickTextField *>("fileNameTextField");
+ QVERIFY(fileNameTextField);
+
+ auto getSelectedFileInfo = [&dialogHelper]() {
+ return QFileInfo(dialogHelper.dialog->selectedFile().toLocalFile());
+ };
+
+ QVERIFY(getSelectedFileInfo().isFile());
+ QCOMPARE(fileNameTextField->text(), tempSubFile1Url.fileName());
+ QCOMPARE(dialogHelper.dialog->selectedFile(), tempSubFile1Url);
+
+ auto *breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar *>();
+ QVERIFY(breadcrumbBar);
+
+ // Pressing the up button causes tempSubDir to be selected
+ QVERIFY(clickButton(breadcrumbBar->upButton()));
+
+ QVERIFY(getSelectedFileInfo().isDir());
+ QCOMPARE(fileNameTextField->text(), tempSubFile1Url.fileName());
+ QCOMPARE(dialogHelper.dialog->selectedFile(), tempSubDirUrl);
+
+ // Change the selected file from the outside
+ dialogHelper.dialog->close();
+ dialogHelper.dialog->setSelectedFile(tempFile11Url);
+ dialogHelper.openDialog();
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ QVERIFY(getSelectedFileInfo().isFile());
+ QCOMPARE(fileNameTextField->text(), tempFile11Url.fileName());
+ QCOMPARE(dialogHelper.dialog->selectedFile(), tempFile11Url);
+}
+
+void tst_QQuickFileDialogImpl::setSchemeForSelectedFile()
+{
+ const auto tempSubFile1Url = QUrl::fromLocalFile(tempSubFile1->fileName());
+
+ const QVariantMap initialProperties = {
+ { "tempFile1Url", QVariant::fromValue(tempSubFile1Url) },
+ { "fileMode", QVariant::fromValue(QQuickFileDialog::SaveFile) }
+ };
+ FileDialogTestHelper dialogHelper(this, "setSelectedFile.qml", {}, initialProperties);
+
+ OPEN_QUICK_DIALOG();
+ QQuickTest::qWaitForPolish(dialogHelper.window());
+
+ QQuickTextField *fileNameTextField =
+ dialogHelper.quickDialog->findChild<QQuickTextField *>("fileNameTextField");
+ QVERIFY(fileNameTextField);
+
+ QVERIFY(!tempSubFile1Url.scheme().isEmpty());
+ QVERIFY(!dialogHelper.dialog->selectedFile().scheme().isEmpty());
+ QCOMPARE(tempSubFile1Url, dialogHelper.dialog->selectedFile());
+
+ fileNameTextField->clear();
+
+ const QPoint textFieldCenterPos =
+ fileNameTextField->mapToScene({ fileNameTextField->width() / 2, fileNameTextField->height() / 2 }).toPoint();
+ QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, textFieldCenterPos);
+
+ const QByteArray newFileName("helloworld.txt");
+ for (const auto &c : newFileName)
+ QTest::keyClick(dialogHelper.window(), c);
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Enter, Qt::NoModifier);
+
+ QTRY_COMPARE(fileNameTextField->text(), QString::fromLatin1(newFileName));
+
+ const auto newFilePath =
+ QUrl::fromLocalFile(QFileInfo(tempSubFile1Url.toLocalFile()).dir().absolutePath() + u'/' + newFileName);
+ QVERIFY(!newFilePath.scheme().isEmpty());
+ QVERIFY(!dialogHelper.dialog->selectedFile().scheme().isEmpty());
+ QCOMPARE(dialogHelper.dialog->selectedFile(), newFilePath);
+}
+
QTEST_MAIN(tst_QQuickFileDialogImpl)
#include "tst_qquickfiledialogimpl.moc"
diff --git a/tests/auto/quickdialogs/qquickfolderdialogimpl/CMakeLists.txt b/tests/auto/quickdialogs/qquickfolderdialogimpl/CMakeLists.txt
index d3a2f9f2ae..48ffeeeef8 100644
--- a/tests/auto/quickdialogs/qquickfolderdialogimpl/CMakeLists.txt
+++ b/tests/auto/quickdialogs/qquickfolderdialogimpl/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickfolderdialogimpl LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quickdialogs/qquickfolderdialogimpl/data/acceptRejectLabel.qml b/tests/auto/quickdialogs/qquickfolderdialogimpl/data/acceptRejectLabel.qml
index 0b056fc8e1..f84c55d890 100644
--- a/tests/auto/quickdialogs/qquickfolderdialogimpl/data/acceptRejectLabel.qml
+++ b/tests/auto/quickdialogs/qquickfolderdialogimpl/data/acceptRejectLabel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickdialogs/qquickfolderdialogimpl/data/bindCurrentFolder.qml b/tests/auto/quickdialogs/qquickfolderdialogimpl/data/bindCurrentFolder.qml
index 4cc5027547..a38629c53b 100644
--- a/tests/auto/quickdialogs/qquickfolderdialogimpl/data/bindCurrentFolder.qml
+++ b/tests/auto/quickdialogs/qquickfolderdialogimpl/data/bindCurrentFolder.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickdialogs/qquickfolderdialogimpl/data/bindTitle.qml b/tests/auto/quickdialogs/qquickfolderdialogimpl/data/bindTitle.qml
index a35d58d759..38ae9f3288 100644
--- a/tests/auto/quickdialogs/qquickfolderdialogimpl/data/bindTitle.qml
+++ b/tests/auto/quickdialogs/qquickfolderdialogimpl/data/bindTitle.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickdialogs/qquickfolderdialogimpl/data/folderDialog.qml b/tests/auto/quickdialogs/qquickfolderdialogimpl/data/folderDialog.qml
index 984bba0d58..85e1532ffc 100644
--- a/tests/auto/quickdialogs/qquickfolderdialogimpl/data/folderDialog.qml
+++ b/tests/auto/quickdialogs/qquickfolderdialogimpl/data/folderDialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp b/tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp
index 01116aa7e9..f4e35a37bf 100644
--- a/tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp
+++ b/tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
@@ -185,9 +185,9 @@ class FolderDialogSignalHelper
public:
FolderDialogSignalHelper(const FolderDialogTestHelper &dialogTestHelper) :
dialogSelectedFolderChangedSpy(dialogTestHelper.dialog, SIGNAL(selectedFolderChanged())),
- quickDialogSelectedFolderChangedSpy(dialogTestHelper.quickDialog, SIGNAL(selectedFolderChanged(const QUrl &))),
+ quickDialogSelectedFolderChangedSpy(dialogTestHelper.quickDialog, SIGNAL(selectedFolderChanged(QUrl))),
dialogCurrentFolderChangedSpy(dialogTestHelper.dialog, SIGNAL(currentFolderChanged())),
- quickDialogCurrentFolderChangedSpy(dialogTestHelper.quickDialog, SIGNAL(currentFolderChanged(const QUrl &)))
+ quickDialogCurrentFolderChangedSpy(dialogTestHelper.quickDialog, SIGNAL(currentFolderChanged(QUrl)))
{
if (!dialogSelectedFolderChangedSpy.isValid())
errorMessage = "selectedFolderChanged signal of dialog is not valid";
@@ -344,6 +344,7 @@ void tst_QQuickFolderDialogImpl::changeFolderViaTextEdit()
QVERIFY(dialogHelper.openDialog());
QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+#if QT_CONFIG(shortcut)
// Get the text edit visible with Ctrl+L.
const auto editPathKeySequence = QKeySequence(Qt::CTRL | Qt::Key_L);
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
@@ -356,6 +357,7 @@ void tst_QQuickFolderDialogImpl::changeFolderViaTextEdit()
// Enter the path to the folder in the text edit.
enterText(dialogHelper.window(), tempSubDir2.path());
QCOMPARE(breadcrumbBar->textField()->text(), tempSubDir2.path());
+#endif
// Hit enter to accept.
QTest::keyClick(dialogHelper.window(), Qt::Key_Return);
@@ -417,9 +419,11 @@ void tst_QQuickFolderDialogImpl::cancelDialogWhileTextEditHasFocus()
QVERIFY(dialogHelper.openDialog());
QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+#if QT_CONFIG(shortcut)
// Get the text edit visible with Ctrl+L.
const auto editPathKeySequence = QKeySequence(Qt::CTRL | Qt::Key_L);
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+#endif
auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
QVERIFY(breadcrumbBar);
QVERIFY(breadcrumbBar->textField()->isVisible());
@@ -471,6 +475,7 @@ void tst_QQuickFolderDialogImpl::goUp()
QTRY_VERIFY(findViewDelegateItem(folderDialogListView, 0, subDirDelegate));
QCOMPARE(subDirDelegate->isHighlighted(), true);
+#if QT_CONFIG(shortcut)
// Go up a directory via the keyboard shortcut.
const auto goUpKeySequence = QKeySequence(Qt::ALT | Qt::Key_Up);
QTest::keySequence(dialogHelper.window(), goUpKeySequence);
@@ -478,6 +483,7 @@ void tst_QQuickFolderDialogImpl::goUp()
QVERIFY(tempParentDir.cdUp());
COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempParentDir.path()));
COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempDir.path()));
+#endif
}
void tst_QQuickFolderDialogImpl::goUpWhileTextEditHasFocus()
@@ -610,27 +616,33 @@ void tst_QQuickFolderDialogImpl::keyAndShortcutHandling()
QVERIFY(dialogHelper.openDialog());
QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+#if QT_CONFIG(shortcut)
// Get the text edit visible with Ctrl+L.
const auto editPathKeySequence = QKeySequence(Qt::CTRL | Qt::Key_L);
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+#endif
auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
QVERIFY(breadcrumbBar);
QVERIFY(breadcrumbBar->textField()->isVisible());
QCOMPARE(breadcrumbBar->textField()->text(), dialogHelper.dialog->currentFolder().toLocalFile());
QCOMPARE(breadcrumbBar->textField()->selectedText(), breadcrumbBar->textField()->text());
+#if QT_CONFIG(shortcut)
// Ctrl+L shouldn't hide it.
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
QVERIFY(breadcrumbBar->textField()->isVisible());
+#endif
// Cancel it with the escape key.
QTest::keyClick(dialogHelper.window(), Qt::Key_Escape);
QVERIFY(!breadcrumbBar->textField()->isVisible());
QVERIFY(dialogHelper.dialog->isVisible());
+#if QT_CONFIG(shortcut)
// Make it visible.
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
QVERIFY(breadcrumbBar->textField()->isVisible());
+#endif
// Cancel it with the escape key again.
QTest::keyClick(dialogHelper.window(), Qt::Key_Escape);
@@ -795,12 +807,13 @@ void tst_QQuickFolderDialogImpl::itemsDisabledWhenNecessary()
COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path()));
COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempDir.path()));
+#if QT_CONFIG(shortcut)
// Get the text edit visible with Ctrl+L. The Open button should now be disabled.
const auto editPathKeySequence = QKeySequence(Qt::CTRL | Qt::Key_L);
QTest::keySequence(dialogHelper.window(), editPathKeySequence);
QVERIFY(breadcrumbBar->textField()->isVisible());
QCOMPARE(openButton->isEnabled(), false);
-
+#endif
// Hide it with the escape key. The Open button should now be enabled.
QTest::keyClick(dialogHelper.window(), Qt::Key_Escape);
QVERIFY(!breadcrumbBar->textField()->isVisible());
diff --git a/tests/auto/quickdialogs/qquickfontdialogimpl/BLACKLIST b/tests/auto/quickdialogs/qquickfontdialogimpl/BLACKLIST
index 7d88c9868a..39d2a543c0 100644
--- a/tests/auto/quickdialogs/qquickfontdialogimpl/BLACKLIST
+++ b/tests/auto/quickdialogs/qquickfontdialogimpl/BLACKLIST
@@ -2,3 +2,4 @@
# QTBUG-94225
[clickAroundInTheFamilyListView]
b2qt
+
diff --git a/tests/auto/quickdialogs/qquickfontdialogimpl/CMakeLists.txt b/tests/auto/quickdialogs/qquickfontdialogimpl/CMakeLists.txt
index cec40964cd..552b5c9faf 100644
--- a/tests/auto/quickdialogs/qquickfontdialogimpl/CMakeLists.txt
+++ b/tests/auto/quickdialogs/qquickfontdialogimpl/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickfontdialogimpl LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quickdialogs/qquickfontdialogimpl/data/fontDialog.qml b/tests/auto/quickdialogs/qquickfontdialogimpl/data/fontDialog.qml
index 49ba215d6e..3cb6555e7a 100644
--- a/tests/auto/quickdialogs/qquickfontdialogimpl/data/fontDialog.qml
+++ b/tests/auto/quickdialogs/qquickfontdialogimpl/data/fontDialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickdialogs/qquickfontdialogimpl/tst_qquickfontdialogimpl.cpp b/tests/auto/quickdialogs/qquickfontdialogimpl/tst_qquickfontdialogimpl.cpp
index 5de4fe291b..90bc3503b9 100644
--- a/tests/auto/quickdialogs/qquickfontdialogimpl/tst_qquickfontdialogimpl.cpp
+++ b/tests/auto/quickdialogs/qquickfontdialogimpl/tst_qquickfontdialogimpl.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
@@ -273,6 +273,8 @@ void tst_QQuickFontDialogImpl::settingUnderlineAndStrikeoutEffects()
QVERIFY(dialogHelper.dialog->selectedFont().underline());
QVERIFY(!dialogHelper.dialog->selectedFont().strikeOut());
+ QVERIFY(QQuickTest::qWaitForPolish(dialogHelper.window()));
+
QVERIFY(clickButton(underlineCheckBox));
QCOMPARE(selectedFontSpy.size(), 2);
diff --git a/tests/auto/quickdialogs/qquickmessagedialogimpl/CMakeLists.txt b/tests/auto/quickdialogs/qquickmessagedialogimpl/CMakeLists.txt
index 50a2fc1a2c..5685404073 100644
--- a/tests/auto/quickdialogs/qquickmessagedialogimpl/CMakeLists.txt
+++ b/tests/auto/quickdialogs/qquickmessagedialogimpl/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickmessagedialogimpl LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quickdialogs/qquickmessagedialogimpl/data/messageDialog.qml b/tests/auto/quickdialogs/qquickmessagedialogimpl/data/messageDialog.qml
index baa7ac5e90..015ee79dba 100644
--- a/tests/auto/quickdialogs/qquickmessagedialogimpl/data/messageDialog.qml
+++ b/tests/auto/quickdialogs/qquickmessagedialogimpl/data/messageDialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickdialogs/qquickmessagedialogimpl/data/messageDialogWithButtons.qml b/tests/auto/quickdialogs/qquickmessagedialogimpl/data/messageDialogWithButtons.qml
new file mode 100644
index 0000000000..33bc2f4cf2
--- /dev/null
+++ b/tests/auto/quickdialogs/qquickmessagedialogimpl/data/messageDialogWithButtons.qml
@@ -0,0 +1,19 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+
+ApplicationWindow {
+ width: 640
+ height: 480
+
+ property alias dialog: dialog
+
+ MessageDialog {
+ id: dialog
+ objectName: "MessageDialog"
+ buttons: MessageDialog.Yes | MessageDialog.No | MessageDialog.Discard | MessageDialog.Apply
+ }
+}
diff --git a/tests/auto/quickdialogs/qquickmessagedialogimpl/tst_qquickmessagedialogimpl.cpp b/tests/auto/quickdialogs/qquickmessagedialogimpl/tst_qquickmessagedialogimpl.cpp
index b2f3d6456c..92af0036ba 100644
--- a/tests/auto/quickdialogs/qquickmessagedialogimpl/tst_qquickmessagedialogimpl.cpp
+++ b/tests/auto/quickdialogs/qquickmessagedialogimpl/tst_qquickmessagedialogimpl.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
@@ -8,6 +8,7 @@
#include <QtQuickDialogs2QuickImpl/private/qquickmessagedialogimpl_p.h>
#include <QtQuickTest/quicktest.h>
#include <QtQuickControls2/qquickstyle.h>
+#include <QtQuickTemplates2/private/qquickdialog_p_p.h>
#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
#include <QtQuickControlsTestUtils/private/dialogstestutils_p.h>
@@ -39,6 +40,7 @@ private slots:
void changeInformativeText();
void changeStandardButtons();
void detailedText();
+ void resultReflectsLastStandardButtonPressed();
};
// We don't want to fail on warnings until QTBUG-98964 is fixed,
@@ -269,6 +271,101 @@ void tst_QQuickMessageDialogImpl::detailedText()
dialogHelper.dialog->close();
}
+void tst_QQuickMessageDialogImpl::resultReflectsLastStandardButtonPressed()
+{
+ DialogTestHelper<QQuickMessageDialog, QQuickMessageDialogImpl> dialogHelper(
+ this, "messageDialogWithButtons.qml");
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ QSignalSpy acceptedSpy(dialogHelper.dialog, SIGNAL(accepted()));
+ QSignalSpy rejectedSpy(dialogHelper.dialog, SIGNAL(rejected()));
+ QSignalSpy resultChangedSpy(dialogHelper.dialog, SIGNAL(resultChanged()));
+
+ auto buttonBox = dialogHelper.quickDialog->findChild<QQuickDialogButtonBox *>("buttonBox");
+ QVERIFY(buttonBox);
+
+ QQuickTest::qWaitForPolish(dialogHelper.window());
+
+ bool yesFound = false;
+ bool noFound = false;
+ bool discardFound = false;
+ bool applyFound = false;
+
+ int expectedNumberOfAcceptedSignals = 0;
+ int expectedNumberOfRejectedSignals = 0;
+
+ // The dialogButtonBox has different layouts depending on platform. This tries to account for all possible layouts.
+ // If the role of a button is YesRole, AcceptRole, NoRole or RejectRole, then pressing that button should emit accepted, or rejected.
+ // And since this is a MessageDialog, the result property should reflect the last button pressed, rather than the StandardCode.
+ for (int i = 0; i < buttonBox->count(); ++i) {
+ auto button = qobject_cast<QQuickAbstractButton *>(buttonBox->itemAt(i));
+ switch (QQuickDialogPrivate::buttonRole(button)) {
+ case QPlatformDialogHelper::YesRole:
+ yesFound = true;
+ expectedNumberOfAcceptedSignals++;
+
+ QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, button->mapToScene({ button->width() / 2, button->height() / 2 }).toPoint());
+ QTRY_VERIFY(!dialogHelper.isQuickDialogOpen());
+
+ QCOMPARE(dialogHelper.dialog->result(), QPlatformDialogHelper::StandardButton::Yes);
+ QCOMPARE(resultChangedSpy.count(), i + 1);
+
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+ break;
+ case QPlatformDialogHelper::NoRole:
+ noFound = true;
+ expectedNumberOfRejectedSignals++;
+
+ QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, button->mapToScene({ button->width() / 2, button->height() / 2 }).toPoint());
+ QTRY_VERIFY(!dialogHelper.isQuickDialogOpen());
+
+ QCOMPARE(dialogHelper.dialog->result(), QPlatformDialogHelper::StandardButton::No);
+ QCOMPARE(resultChangedSpy.count(), i + 1);
+
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+ break;
+ case QPlatformDialogHelper::DestructiveRole:
+ discardFound = true;
+
+ QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, button->mapToScene({ button->width() / 2, button->height() / 2 }).toPoint());
+ QTRY_VERIFY(!dialogHelper.isQuickDialogOpen());
+
+ QCOMPARE(dialogHelper.dialog->result(), QPlatformDialogHelper::StandardButton::Discard);
+ QCOMPARE(resultChangedSpy.count(), i + 1);
+
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+ break;
+ case QPlatformDialogHelper::ApplyRole:
+ applyFound = true;
+
+ QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, button->mapToScene({ button->width() / 2, button->height() / 2 }).toPoint());
+ QTRY_VERIFY(!dialogHelper.isQuickDialogOpen());
+
+ QCOMPARE(dialogHelper.dialog->result(), QPlatformDialogHelper::StandardButton::Apply);
+ QCOMPARE(resultChangedSpy.count(), i + 1);
+
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+ break;
+ default:
+ QFAIL(qPrintable(QStringLiteral("Unexpected role %1").arg(QQuickDialogPrivate::buttonRole(button))));
+ }
+ }
+
+ QVERIFY2(yesFound && noFound && discardFound && applyFound, "A button that was expected to be present, wasn't found when iterating over all of them.");
+ QCOMPARE(acceptedSpy.count(), expectedNumberOfAcceptedSignals);
+ QCOMPARE(rejectedSpy.count(), expectedNumberOfRejectedSignals);
+
+ dialogHelper.dialog->close();
+}
+
QTEST_MAIN(tst_QQuickMessageDialogImpl)
#include "tst_qquickmessagedialogimpl.moc"
diff --git a/tests/auto/quicktest/polish-qml/CMakeLists.txt b/tests/auto/quicktest/polish-qml/CMakeLists.txt
index cbae62a349..9b7805f57f 100644
--- a/tests/auto/quicktest/polish-qml/CMakeLists.txt
+++ b/tests/auto/quicktest/polish-qml/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_polish-qml Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_polish-qml LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quicktest/polish-qml/data/tst_polish.qml b/tests/auto/quicktest/polish-qml/data/tst_polish.qml
index 089d1d9620..8a62db4ecd 100644
--- a/tests/auto/quicktest/polish-qml/data/tst_polish.qml
+++ b/tests/auto/quicktest/polish-qml/data/tst_polish.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.13
import QtTest 1.13
diff --git a/tests/auto/quicktest/polish-qml/tst_polish-qml.cpp b/tests/auto/quicktest/polish-qml/tst_polish-qml.cpp
index 58156868df..6f4bdc6a9a 100644
--- a/tests/auto/quicktest/polish-qml/tst_polish-qml.cpp
+++ b/tests/auto/quicktest/polish-qml/tst_polish-qml.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtQml/qqmlengine.h>
diff --git a/tests/auto/quicktest/polish/CMakeLists.txt b/tests/auto/quicktest/polish/CMakeLists.txt
index a05f1dfa15..0f7ecb6808 100644
--- a/tests/auto/quicktest/polish/CMakeLists.txt
+++ b/tests/auto/quicktest/polish/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_polish Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_polish LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quicktest/polish/data/childPolish.qml b/tests/auto/quicktest/polish/data/childPolish.qml
index f8e72bfaf4..08f5b5bfb6 100644
--- a/tests/auto/quicktest/polish/data/childPolish.qml
+++ b/tests/auto/quicktest/polish/data/childPolish.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import Test 1.0
diff --git a/tests/auto/quicktest/polish/data/polish.qml b/tests/auto/quicktest/polish/data/polish.qml
index 76783624e9..6015957845 100644
--- a/tests/auto/quicktest/polish/data/polish.qml
+++ b/tests/auto/quicktest/polish/data/polish.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import Test 1.0
diff --git a/tests/auto/quicktest/polish/tst_polish.cpp b/tests/auto/quicktest/polish/tst_polish.cpp
index aea7fb92c5..396375d081 100644
--- a/tests/auto/quicktest/polish/tst_polish.cpp
+++ b/tests/auto/quicktest/polish/tst_polish.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtQml/qqmlengine.h>
diff --git a/tests/auto/quicktest/quicktestmainwithsetup/CMakeLists.txt b/tests/auto/quicktest/quicktestmainwithsetup/CMakeLists.txt
index 2ad66c00c9..9f583c7723 100644
--- a/tests/auto/quicktest/quicktestmainwithsetup/CMakeLists.txt
+++ b/tests/auto/quicktest/quicktestmainwithsetup/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_quicktestmainwithsetup Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_quicktestmainwithsetup LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quicktest/quicktestmainwithsetup/data/tst_setup.qml b/tests/auto/quicktest/quicktestmainwithsetup/data/tst_setup.qml
index 2cfe936a6c..68eebf2965 100644
--- a/tests/auto/quicktest/quicktestmainwithsetup/data/tst_setup.qml
+++ b/tests/auto/quicktest/quicktestmainwithsetup/data/tst_setup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.2
diff --git a/tests/auto/quicktest/quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp b/tests/auto/quicktest/quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp
index 23f59fa06c..d05a5730fb 100644
--- a/tests/auto/quicktest/quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp
+++ b/tests/auto/quicktest/quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtQml/qqmlengine.h>
diff --git a/tests/auto/quicktest/signalspy/CMakeLists.txt b/tests/auto/quicktest/signalspy/CMakeLists.txt
index 75248d4aea..1d5d816f0c 100644
--- a/tests/auto/quicktest/signalspy/CMakeLists.txt
+++ b/tests/auto/quicktest/signalspy/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_signalspy Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_signalspy LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
data/*)
diff --git a/tests/auto/quicktest/signalspy/data/signalspy.qml b/tests/auto/quicktest/signalspy/data/signalspy.qml
index e5fbb915b6..72cae86602 100644
--- a/tests/auto/quicktest/signalspy/data/signalspy.qml
+++ b/tests/auto/quicktest/signalspy/data/signalspy.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/quicktest/signalspy/data/signalspy2.qml b/tests/auto/quicktest/signalspy/data/signalspy2.qml
index 0532e5fb54..5329927f87 100644
--- a/tests/auto/quicktest/signalspy/data/signalspy2.qml
+++ b/tests/auto/quicktest/signalspy/data/signalspy2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.1
diff --git a/tests/auto/quicktest/signalspy/mypropertymap.cpp b/tests/auto/quicktest/signalspy/mypropertymap.cpp
index b374efb167..6ac7fef766 100644
--- a/tests/auto/quicktest/signalspy/mypropertymap.cpp
+++ b/tests/auto/quicktest/signalspy/mypropertymap.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "mypropertymap.h"
diff --git a/tests/auto/quicktest/signalspy/mypropertymap.h b/tests/auto/quicktest/signalspy/mypropertymap.h
index e4a7506b6b..d6a640aab4 100644
--- a/tests/auto/quicktest/signalspy/mypropertymap.h
+++ b/tests/auto/quicktest/signalspy/mypropertymap.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QQmlPropertyMap>
diff --git a/tests/auto/quicktest/signalspy/tst_signalspy.cpp b/tests/auto/quicktest/signalspy/tst_signalspy.cpp
index 545f4d3cc7..6b9c37b237 100644
--- a/tests/auto/quicktest/signalspy/tst_signalspy.cpp
+++ b/tests/auto/quicktest/signalspy/tst_signalspy.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
diff --git a/tests/auto/quicktest/testfiltering/quicktestmain/CMakeLists.txt b/tests/auto/quicktest/testfiltering/quicktestmain/CMakeLists.txt
index 137ab8db95..a60398d2a0 100644
--- a/tests/auto/quicktest/testfiltering/quicktestmain/CMakeLists.txt
+++ b/tests/auto/quicktest/testfiltering/quicktestmain/CMakeLists.txt
@@ -7,6 +7,12 @@
## quicktestmain Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(quicktestmain LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quicktest/testfiltering/quicktestmain/quicktestmain.cpp b/tests/auto/quicktest/testfiltering/quicktestmain/quicktestmain.cpp
index 618ed14351..321763c7e7 100644
--- a/tests/auto/quicktest/testfiltering/quicktestmain/quicktestmain.cpp
+++ b/tests/auto/quicktest/testfiltering/quicktestmain/quicktestmain.cpp
@@ -1,4 +1,4 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTest/quicktest.h>
QUICK_TEST_MAIN(quicktestmain)
diff --git a/tests/auto/quicktest/testfiltering/quicktestmain/tst_first.qml b/tests/auto/quicktest/testfiltering/quicktestmain/tst_first.qml
index 46a4f86e2f..917e731cdb 100644
--- a/tests/auto/quicktest/testfiltering/quicktestmain/tst_first.qml
+++ b/tests/auto/quicktest/testfiltering/quicktestmain/tst_first.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.3
import QtTest 1.1
diff --git a/tests/auto/quicktest/testfiltering/quicktestmain/tst_second.qml b/tests/auto/quicktest/testfiltering/quicktestmain/tst_second.qml
index 61e218facc..0b4ef2c0d6 100644
--- a/tests/auto/quicktest/testfiltering/quicktestmain/tst_second.qml
+++ b/tests/auto/quicktest/testfiltering/quicktestmain/tst_second.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.3
import QtTest 1.1
diff --git a/tests/auto/quicktest/testfiltering/quicktestmain/tst_third.qml b/tests/auto/quicktest/testfiltering/quicktestmain/tst_third.qml
index 41df307755..9856212259 100644
--- a/tests/auto/quicktest/testfiltering/quicktestmain/tst_third.qml
+++ b/tests/auto/quicktest/testfiltering/quicktestmain/tst_third.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.3
import QtTest 1.1
diff --git a/tests/auto/quicktest/testfiltering/test/CMakeLists.txt b/tests/auto/quicktest/testfiltering/test/CMakeLists.txt
index c59818d2f2..fa6a387c91 100644
--- a/tests/auto/quicktest/testfiltering/test/CMakeLists.txt
+++ b/tests/auto/quicktest/testfiltering/test/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_testfiltering Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_testfiltering LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_testfiltering
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../" # special case
diff --git a/tests/auto/quicktest/testfiltering/tst_testfiltering.cpp b/tests/auto/quicktest/testfiltering/tst_testfiltering.cpp
index 3f0c8c41b4..9dc0f46335 100644
--- a/tests/auto/quicktest/testfiltering/tst_testfiltering.cpp
+++ b/tests/auto/quicktest/testfiltering/tst_testfiltering.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QProcess>
#include <QtTest>
diff --git a/tests/auto/quicktest/testswithcomponents/CMakeLists.txt b/tests/auto/quicktest/testswithcomponents/CMakeLists.txt
index 3a77fc38d1..a2beefc298 100644
--- a/tests/auto/quicktest/testswithcomponents/CMakeLists.txt
+++ b/tests/auto/quicktest/testswithcomponents/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_quicktestmainwithsetup Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_quicktestswithcomponents LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quicktest/testswithcomponents/data/tst_setup.qml b/tests/auto/quicktest/testswithcomponents/data/tst_setup.qml
index 685ccd0927..55ba80b92f 100644
--- a/tests/auto/quicktest/testswithcomponents/data/tst_setup.qml
+++ b/tests/auto/quicktest/testswithcomponents/data/tst_setup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtTest 1.2
diff --git a/tests/auto/quicktest/testswithcomponents/tst_quicktestswithcomponents.cpp b/tests/auto/quicktest/testswithcomponents/tst_quicktestswithcomponents.cpp
index 4b3584d33c..cfec909f72 100644
--- a/tests/auto/quicktest/testswithcomponents/tst_quicktestswithcomponents.cpp
+++ b/tests/auto/quicktest/testswithcomponents/tst_quicktestswithcomponents.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtQuickTest/quicktest.h>
diff --git a/tests/auto/quickwidgets/qquickwidget/BLACKLIST b/tests/auto/quickwidgets/qquickwidget/BLACKLIST
index 095e9ee484..8b5585a41e 100644
--- a/tests/auto/quickwidgets/qquickwidget/BLACKLIST
+++ b/tests/auto/quickwidgets/qquickwidget/BLACKLIST
@@ -1,5 +1,12 @@
[tabKey]
opensuse-42.3
opensuse-leap
+macos-12
[enterLeave]
macos
+[focusOnClickInProxyWidget]
+macos-12
+[focusPreserved]
+macos-12
+[synthMouseFromTouch]
+macos-12
diff --git a/tests/auto/quickwidgets/qquickwidget/CMakeLists.txt b/tests/auto/quickwidgets/qquickwidget/CMakeLists.txt
index 5afe445cff..233fae553b 100644
--- a/tests/auto/quickwidgets/qquickwidget/CMakeLists.txt
+++ b/tests/auto/quickwidgets/qquickwidget/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickwidget Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickwidget LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quickwidgets/qquickwidget/data/activeFocusOnTab.qml b/tests/auto/quickwidgets/qquickwidget/data/activeFocusOnTab.qml
index 11bbfdd90e..65f017b1b1 100644
--- a/tests/auto/quickwidgets/qquickwidget/data/activeFocusOnTab.qml
+++ b/tests/auto/quickwidgets/qquickwidget/data/activeFocusOnTab.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.1
diff --git a/tests/auto/quickwidgets/qquickwidget/data/noActiveFocusOnTab.qml b/tests/auto/quickwidgets/qquickwidget/data/noActiveFocusOnTab.qml
index 2168d29831..3fb6e5b7b1 100644
--- a/tests/auto/quickwidgets/qquickwidget/data/noActiveFocusOnTab.qml
+++ b/tests/auto/quickwidgets/qquickwidget/data/noActiveFocusOnTab.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.1
diff --git a/tests/auto/quickwidgets/qquickwidget/data/tapHandler.qml b/tests/auto/quickwidgets/qquickwidget/data/tapHandler.qml
new file mode 100644
index 0000000000..fe3d1925e5
--- /dev/null
+++ b/tests/auto/quickwidgets/qquickwidget/data/tapHandler.qml
@@ -0,0 +1,11 @@
+import QtQuick
+
+Rectangle {
+ width: 100
+ height: 100
+ color: th.pressed ? "steelblue" : "beige"
+
+ TapHandler {
+ id: th
+ }
+}
diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
index 8316625d87..8e8e452120 100644
--- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
+++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <qtesttouch.h>
@@ -11,8 +11,10 @@
#include <QtQuick/qquickitem.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickmousearea_p.h>
+#include <QtQuick/private/qquicktaphandler_p.h>
#include <QtQuickTemplates2/private/qquickbutton_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtGui/QWindow>
#include <QtGui/QScreen>
#include <QtGui/QImage>
@@ -23,6 +25,7 @@
#include <QtGui/qstylehints.h>
#include <QtWidgets/QBoxLayout>
#include <QtWidgets/QLabel>
+#include <QtWidgets/private/qapplication_p.h>
#include <QtQuickWidgets/QQuickWidget>
@@ -127,6 +130,8 @@ private slots:
void synthMouseFromTouch();
void touchTapMouseArea();
void touchTapButton();
+ void touchTapHandler_data();
+ void touchTapHandler();
void touchMultipleWidgets();
void tabKey();
void resizeOverlay();
@@ -135,6 +140,10 @@ private slots:
#if QT_CONFIG(graphicsview)
void focusOnClickInProxyWidget();
#endif
+ void focusPreserved();
+ void accessibilityHandlesViewChange();
+ void cleanupRhi();
+ void dontRecreateRootElementOnWindowChange();
private:
QPointingDevice *device = QTest::createTouchDevice();
@@ -678,11 +687,54 @@ void tst_qquickwidget::touchTapButton()
QTRY_VERIFY(rootItem->property("wasClicked").toBool());
}
+void tst_qquickwidget::touchTapHandler_data()
+{
+ QTest::addColumn<bool>("guiSynthMouse"); // AA_SynthesizeMouseForUnhandledTouchEvents
+ QTest::addColumn<QQuickTapHandler::GesturePolicy>("gesturePolicy");
+
+ // QTest::newRow("nosynth: passive grab") << false << QQuickTapHandler::DragThreshold; // still failing
+ QTest::newRow("nosynth: exclusive grab") << false << QQuickTapHandler::ReleaseWithinBounds;
+ QTest::newRow("allowsynth: passive grab") << true << QQuickTapHandler::DragThreshold; // QTBUG-113558
+ QTest::newRow("allowsynth: exclusive grab") << true << QQuickTapHandler::ReleaseWithinBounds;
+}
+
+void tst_qquickwidget::touchTapHandler()
+{
+ QFETCH(bool, guiSynthMouse);
+ QFETCH(QQuickTapHandler::GesturePolicy, gesturePolicy);
+
+ QCoreApplication::setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, guiSynthMouse);
+ QQuickWidget quick;
+ if (!quick.testAttribute(Qt::WA_AcceptTouchEvents))
+ QSKIP("irrelevant on non-touch platforms");
+
+ quick.setSource(testFileUrl("tapHandler.qml"));
+ quick.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&quick));
+
+ QQuickItem *rootItem = quick.rootObject();
+ QVERIFY(rootItem);
+ QQuickTapHandler *th = rootItem->findChild<QQuickTapHandler *>();
+ QVERIFY(th);
+ th->setGesturePolicy(gesturePolicy);
+ QSignalSpy tappedSpy(th, &QQuickTapHandler::tapped);
+
+ const QPoint p(50, 50);
+ QTest::touchEvent(&quick, device).press(0, p, &quick);
+ QTRY_COMPARE(th->isPressed(), true);
+ QTest::touchEvent(&quick, device).release(0, p, &quick);
+ QTRY_COMPARE(tappedSpy.size(), 1);
+ QCOMPARE(th->isPressed(), false);
+}
+
void tst_qquickwidget::touchMultipleWidgets()
{
QWidget window;
QQuickWidget *leftQuick = new QQuickWidget;
leftQuick->setSource(testFileUrl("button.qml"));
+ if (!leftQuick->testAttribute(Qt::WA_AcceptTouchEvents))
+ QSKIP("irrelevant on non-touch platforms");
+
QQuickWidget *rightQuick = new QQuickWidget;
rightQuick->setSource(testFileUrl("button.qml"));
@@ -939,6 +991,124 @@ void tst_qquickwidget::focusOnClickInProxyWidget()
}
#endif
+void tst_qquickwidget::focusPreserved()
+{
+ SKIP_IF_NO_WINDOW_ACTIVATION
+ if (QGuiApplication::platformName() == "android")
+ QSKIP("Test doesn't exit cleanly on Android and generates many warnings - QTBUG-112696");
+
+ QScopedPointer<QWidget> widget(new QWidget());
+ QScopedPointer<QQuickWidget> quick(new QQuickWidget());
+ QQuickItem *root = new QQuickItem(); // will be owned by quick after setContent
+ QScopedPointer<QQuickItem> content(new QQuickItem());
+ content->setActiveFocusOnTab(true);
+ content->setFocus(true);
+ quick->setFocusPolicy(Qt::StrongFocus);
+ quick->setContent(QUrl(), nullptr, root);
+ root->setFlag(QQuickItem::ItemHasContents);
+ content->setParentItem(root);
+
+ quick->setGeometry(0, 0, 200, 200);
+ quick->show();
+ quick->setFocus();
+ quick->activateWindow();
+ QVERIFY(QTest::qWaitForWindowExposed(quick.get()));
+ QTRY_VERIFY(quick->hasFocus());
+ QTRY_VERIFY(content->hasFocus());
+ QTRY_VERIFY(content->hasActiveFocus());
+
+ widget->show();
+ widget->setFocus();
+ widget->activateWindow();
+ QVERIFY(QTest::qWaitForWindowExposed(widget.get()));
+ QTRY_VERIFY(widget->hasFocus());
+
+ quick->setParent(widget.get());
+
+ quick->show();
+ quick->setFocus();
+ quick->activateWindow();
+ QTRY_VERIFY(quick->hasFocus());
+ QTRY_VERIFY(content->hasFocus());
+ QTRY_VERIFY(content->hasActiveFocus());
+}
+
+/*
+ Reparenting the QQuickWidget recreates the offscreen QQuickWindow.
+ Since the accessible interface that is cached for the QQuickWidget dispatches
+ all calls to the offscreen QQuickWindow, it must fix itself when the offscreen
+ view changes. QTBUG-108226
+*/
+void tst_qquickwidget::accessibilityHandlesViewChange()
+{
+ if (QGuiApplication::platformName() == "offscreen")
+ QSKIP("Doesn't test anything on offscreen platform.");
+ if (QGuiApplication::platformName() == "android")
+ QSKIP("Test doesn't exit cleanly on Android and generates many warnings - QTBUG-112696");
+
+ QWidget window;
+
+ QPointer<QQuickWindow> backingScene;
+
+ QQuickWidget *childView = new QQuickWidget(&window);
+ childView->setSource(testFileUrl("rectangle.qml"));
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ backingScene = childView->quickWindow();
+ QVERIFY(backingScene);
+
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(childView);
+ QVERIFY(iface);
+ (void)iface->child(0);
+
+ std::unique_ptr<QQuickWidget> quickWidget(childView);
+ childView->setParent(nullptr);
+ childView->show();
+ QVERIFY(QTest::qWaitForWindowExposed(childView));
+ QVERIFY(!backingScene); // the old QQuickWindow should be gone now
+ QVERIFY(childView->quickWindow()); // long live the new QQuickWindow
+
+ iface = QAccessible::queryAccessibleInterface(childView);
+ QVERIFY(iface);
+ // this would crash if QAccessibleQuickWidget hadn't repaired itself to
+ // delegate calls to the new (or at least not the old, destroyed) QQuickWindow.
+ (void)iface->child(0);
+}
+
+class CreateDestroyWidget : public QWidget
+{
+public:
+ using QWidget::create;
+ using QWidget::destroy;
+};
+
+void tst_qquickwidget::cleanupRhi()
+{
+ CreateDestroyWidget topLevel;
+ QQuickWidget quickWidget(&topLevel);
+ quickWidget.setSource(testFileUrl("rectangle.qml"));
+ topLevel.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
+
+ topLevel.destroy();
+ topLevel.create();
+}
+
+void tst_qquickwidget::dontRecreateRootElementOnWindowChange()
+{
+ auto *quickWidget = new QQuickWidget();
+ quickWidget->setSource(testFileUrl("rectangle.qml"));
+ QObject *item = quickWidget->rootObject();
+
+ bool wasDestroyed = false;
+ QObject::connect(item, &QObject::destroyed, this, [&] { wasDestroyed = true; });
+
+ QEvent event(QEvent::WindowChangeInternal);
+ QCoreApplication::sendEvent(quickWidget, &event);
+
+ QVERIFY(!wasDestroyed);
+}
+
QTEST_MAIN(tst_qquickwidget)
#include "tst_qquickwidget.moc"
diff --git a/tests/auto/toolsupport/CMakeLists.txt b/tests/auto/toolsupport/CMakeLists.txt
index 71a5cbcd6b..3732b473ef 100644
--- a/tests/auto/toolsupport/CMakeLists.txt
+++ b/tests/auto/toolsupport/CMakeLists.txt
@@ -7,9 +7,13 @@
## tst_toolsupport Test:
#####################################################################
-# special case begin
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qml_toolsupport LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qml_toolsupport
-# special case end
SOURCES
tst_toolsupport.cpp
LIBRARIES
diff --git a/tests/auto/toolsupport/tst_toolsupport.cpp b/tests/auto/toolsupport/tst_toolsupport.cpp
index 893f4b95b9..625e3b660f 100644
--- a/tests/auto/toolsupport/tst_toolsupport.cpp
+++ b/tests/auto/toolsupport/tst_toolsupport.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest>
@@ -9,6 +9,7 @@
#include <private/qobject_p.h>
#include <private/qv4compileddata_p.h>
+#include <private/qv4executablecompilationunit_p.h>
#include <private/qv4string_p.h>
#include <private/qqmlrefcount_p.h>
#include <qobject.h>
@@ -68,7 +69,7 @@ void tst_toolsupport::offsets_data()
{
QTestData &data = QTest::newRow("sizeof(QQmlRefCount)")
<< sizeof(QQmlRefCount);
- data << 8 << 16;
+ data << 4 << 4;
}
#if RUN_MEMBER_OFFSET_TEST
@@ -77,13 +78,13 @@ void tst_toolsupport::offsets_data()
= QTest::newRow("CompiledData::CompilationUnit::data")
<< pmm_to_offsetof(&QV4::CompiledData::CompilationUnit::data);
- data << 20 << 40;
+ data << 4 << 8;
}
{
QTestData &data
- = QTest::newRow("CompiledData::CompilationUnit::runtimeStrings")
- << pmm_to_offsetof(&QV4::CompiledData::CompilationUnit::runtimeStrings);
+ = QTest::newRow("ExecutableCompilationUnit::runtimeStrings")
+ << pmm_to_offsetof(&QV4::ExecutableCompilationUnit::runtimeStrings);
data << 0 << 0;
}