aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/particles/qquickitemparticle/data/takeGive.qml74
-rw-r--r--tests/auto/particles/qquickitemparticle/tst_qquickitemparticle.cpp13
-rw-r--r--tests/auto/qml/debugger/debugger.pro1
-rw-r--r--tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp5
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml4
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp12
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml41
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationservice/qqmldebugtranslationservice.pro12
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp80
-rw-r--r--tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp10
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp3
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp32
-rw-r--r--tests/auto/qml/debugger/shared/debugutil.cpp2
-rw-r--r--tests/auto/qml/debugger/shared/debugutil_p.h5
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations32
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp61
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.cpp16
-rw-r--r--tests/auto/qml/qml.pro5
-rw-r--r--tests/auto/qml/qmlcachegen/data/retain.qrc (renamed from tests/auto/qml/qmlcachegen/retain.qrc)2
-rw-r--r--tests/auto/qml/qmlcachegen/qmlcachegen.pro2
-rw-r--r--tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp22
-rw-r--r--tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp4
-rw-r--r--tests/auto/qml/qmlformat/data/Annotations.formatted.nosort.qml106
-rw-r--r--tests/auto/qml/qmlformat/data/Annotations.formatted.qml106
-rw-r--r--tests/auto/qml/qmlformat/data/Annotations.qml76
-rw-r--r--tests/auto/qml/qmlformat/data/Example1.formatted.nosort.qml152
-rw-r--r--tests/auto/qml/qmlformat/data/Example1.formatted.qml152
-rw-r--r--tests/auto/qml/qmlformat/data/Example1.qml105
-rw-r--r--tests/auto/qml/qmlformat/data/FrontInline.formatted.qml3
-rw-r--r--tests/auto/qml/qmlformat/data/FrontInline.qml2
-rw-r--r--tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml63
-rw-r--r--tests/auto/qml/qmlformat/data/IfBlocks.qml66
-rw-r--r--tests/auto/qml/qmlformat/data/readOnlyProps.formatted.qml29
-rw-r--r--tests/auto/qml/qmlformat/data/readOnlyProps.qml15
-rw-r--r--tests/auto/qml/qmlformat/qmlformat.pro12
-rw-r--r--tests/auto/qml/qmlformat/tst_qmlformat.cpp300
-rw-r--r--tests/auto/qml/qmllint/data/AttachedProps.qml6
-rw-r--r--tests/auto/qml/qmllint/data/AutomatchedSignalHandler.qml15
-rw-r--r--tests/auto/qml/qmllint/data/ButtonLoader.qml10
-rw-r--r--tests/auto/qml/qmllint/data/Cycle1.qml2
-rw-r--r--tests/auto/qml/qmllint/data/Cycle2.qml2
-rw-r--r--tests/auto/qml/qmllint/data/Cycle3.qml2
-rw-r--r--tests/auto/qml/qmllint/data/Dialog.qml10
-rw-r--r--tests/auto/qml/qmllint/data/Drawer.qml5
-rw-r--r--tests/auto/qml/qmllint/data/Form.ui.qml4
-rw-r--r--tests/auto/qml/qmllint/data/FormUser.qml7
-rw-r--r--tests/auto/qml/qmllint/data/ImportWithPrefix.qml5
-rw-r--r--tests/auto/qml/qmllint/data/MethodInItem.qml5
-rw-r--r--tests/auto/qml/qmllint/data/MethodInScope.qml5
-rw-r--r--tests/auto/qml/qmllint/data/Methods.js3
-rw-r--r--tests/auto/qml/qmllint/data/Text.qml6
-rw-r--r--tests/auto/qml/qmllint/data/Things/SomethingElse.qml2
-rw-r--r--tests/auto/qml/qmllint/data/Things/plugins.qmltypes17
-rw-r--r--tests/auto/qml/qmllint/data/Things/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/badAlias.qml5
-rw-r--r--tests/auto/qml/qmllint/data/badAliasProperty.qml6
-rw-r--r--tests/auto/qml/qmllint/data/badParent.qml7
-rw-r--r--tests/auto/qml/qmllint/data/badTypeAssertion.qml6
-rw-r--r--tests/auto/qml/qmllint/data/esmodule.mjs2
-rw-r--r--tests/auto/qml/qmllint/data/forLoop.qml9
-rw-r--r--tests/auto/qml/qmllint/data/goodAlias.qml12
-rw-r--r--tests/auto/qml/qmllint/data/goodParent.qml8
-rw-r--r--tests/auto/qml/qmllint/data/goodTypeAssertion.qml6
-rw-r--r--tests/auto/qml/qmllint/data/incompleteQmltypes.qml6
-rw-r--r--tests/auto/qml/qmllint/data/javascriptMethods.qml6
-rw-r--r--tests/auto/qml/qmllint/data/memberNotFound.qml7
-rw-r--r--tests/auto/qml/qmllint/data/parentIsComponent.qml13
-rw-r--r--tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml6
-rw-r--r--tests/auto/qml/qmllint/data/unknownElement.qml (renamed from tests/auto/qml/qmllint/data/spuriousParentWarning.qml)0
-rw-r--r--tests/auto/qml/qmllint/data/unknownJavascriptMethod.qml6
-rw-r--r--tests/auto/qml/qmllint/tst_qmllint.cpp207
-rw-r--r--tests/auto/qml/qmlmin/tst_qmlmin.cpp1
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp43
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/foreign.h59
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/foreign.pro10
-rw-r--r--tests/auto/qml/qmltyperegistrar/hppheader.hpp64
-rw-r--r--tests/auto/qml/qmltyperegistrar/noextheader64
-rw-r--r--tests/auto/qml/qmltyperegistrar/qmltyperegistrar.pro4
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp78
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h96
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.pro20
-rw-r--r--tests/auto/qml/qqmlapplicationengine/data/i18n/qml_de_CH.qmbin0 -> 101 bytes
-rw-r--r--tests/auto/qml/qqmlapplicationengine/data/i18n/qml_de_CH.ts11
-rw-r--r--tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp23
-rw-r--r--tests/auto/qml/qqmlcomponent/data/AliasToSubcomponentRequiredBase.qml10
-rw-r--r--tests/auto/qml/qqmlcomponent/data/BaseWithRequired.qml6
-rw-r--r--tests/auto/qml/qqmlcomponent/data/RequiredDefault.qml5
-rw-r--r--tests/auto/qml/qqmlcomponent/data/aliasToSubcomponentNotSet.qml4
-rw-r--r--tests/auto/qml/qqmlcomponent/data/createdFromQml.qml11
-rw-r--r--tests/auto/qml/qqmlcomponent/data/createdFromQmlFail.qml11
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredDefault.1.qml5
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredDefault.2.qml3
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredDefault.3.qml6
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredDefault.4.qml4
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredNotSet.qml5
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredSetInSameFile.qml6
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredSetLater.qml5
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasAfterSameFile.qml8
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasBeforeSameFile.qml8
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasParentFile.qml7
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredSetViaChainedAlias.qml9
-rw-r--r--tests/auto/qml/qqmlcomponent/data/setViaAliasToSubcomponent.qml5
-rw-r--r--tests/auto/qml/qqmlcomponent/data/shadowing.qml5
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp117
-rw-r--r--tests/auto/qml/qqmlconsole/data/logging.qml4
-rw-r--r--tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp8
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml37
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/integerModel.qml35
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/listModel.qml45
-rw-r--r--tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro13
-rw-r--r--tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp139
-rw-r--r--tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp8
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h1
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp35
-rw-r--r--tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testEmptyComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testEmptyComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testIncubatedComponent.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testLoaderComponent.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testReloadComponent.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testScriptComponent.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testTopLevelComponent.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testTransientComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testTransientComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMEComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMEComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.1.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.2.qml1
-rw-r--r--tests/auto/qml/qqmlengine/data/uiLanguage.qml9
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp65
-rw-r--r--tests/auto/qml/qqmlenginecleanup/data/MyItem.qml2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp13
-rw-r--r--tests/auto/qml/qqmlimport/tst_qqmlimport.cpp21
-rw-r--r--tests/auto/qml/qqmlincubator/data/requiredProperty.qml5
-rw-r--r--tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp105
-rw-r--r--tests/auto/qml/qqmlinstantiator/data/createAndRemove.qml11
-rw-r--r--tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp4
-rw-r--r--tests/auto/qml/qqmllanguage/data/Action.qml21
-rw-r--r--tests/auto/qml/qqmllanguage/data/InlineComponentBase.qml9
-rw-r--r--tests/auto/qml/qqmllanguage/data/InlineComponentChild.qml7
-rw-r--r--tests/auto/qml/qqmllanguage/data/InlineComponentProvider.qml9
-rw-r--r--tests/auto/qml/qqmllanguage/data/InlineComponentProvider2.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/InlineComponentProvider3.qml11
-rw-r--r--tests/auto/qml/qqmllanguage/data/InlineComponentProviderChild.qml1
-rw-r--r--tests/auto/qml/qqmllanguage/data/InlineComponentReexporter.qml8
-rw-r--r--tests/auto/qml/qqmllanguage/data/NonRequiredBase.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/RequiredBase.qml3
-rw-r--r--tests/auto/qml/qqmllanguage/data/SelfInstantiation.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/SelfInstantiation.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/SelfReference.qml8
-rw-r--r--tests/auto/qml/qqmllanguage/data/SimpleItem.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/alias.14.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/alias.18.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/alias.18.qml9
-rw-r--r--tests/auto/qml/qqmllanguage/data/arrayToContainer.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppRequiredProperty.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParent.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParentNotSet.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParent.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParentNotSet.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppRequiredPropertyNotSet.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppstaticnamespace.2.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppstaticnamespace.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/foreignExtended.qml20
-rw-r--r--tests/auto/qml/qqmllanguage/data/icCycleViaProperty.qml9
-rw-r--r--tests/auto/qml/qqmllanguage/data/icSimpleCycle.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/inlineComponentDuplicateName.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/inlineComponentFoundBeforeOtherImports.qml9
-rw-r--r--tests/auto/qml/qqmllanguage/data/inlineComponentOrder.qml20
-rw-r--r--tests/auto/qml/qqmllanguage/data/inlineComponentUser1.qml13
-rw-r--r--tests/auto/qml/qqmllanguage/data/inlineComponentUser2.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/inlineComponentUser3.qml16
-rw-r--r--tests/auto/qml/qqmllanguage/data/inlineComponentUser4.qml12
-rw-r--r--tests/auto/qml/qqmllanguage/data/inlineComponentUser5.qml11
-rw-r--r--tests/auto/qml/qqmllanguage/data/inlineComponentWithAlias.qml17
-rw-r--r--tests/auto/qml/qqmllanguage/data/inlineComponentWithId.qml14
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidRoot.4.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidTypeName.4.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/listContainingDeleted.qml36
-rw-r--r--tests/auto/qml/qqmllanguage/data/listPropertiesChild.qml7
-rw-r--r--tests/auto/qml/qqmllanguage/data/nestedIC.qml7
-rw-r--r--tests/auto/qml/qqmllanguage/data/nonExistingICUser1.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/nonExistingICUser2.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/nonExistingICUser3.qml3
-rw-r--r--tests/auto/qml/qqmllanguage/data/nonExistingICUser4.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/nonExistingICUser5.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_And.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_And.qml8
-rw-r--r--tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_Or.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_Or.qml8
-rw-r--r--tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_And.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_And.qml8
-rw-r--r--tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_Or.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_Or.qml8
-rw-r--r--tests/auto/qml/qqmllanguage/data/requiredProperties.1.qml8
-rw-r--r--tests/auto/qml/qqmllanguage/data/requiredProperties.2.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/requiredProperties.4.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/requiredProperties.5.qml1
-rw-r--r--tests/auto/qml/qqmllanguage/data/requiredProperties.6.qml3
-rw-r--r--tests/auto/qml/qqmllanguage/data/requiredProperties.7.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/selfreferencingsingletonmodule/TestSingleton.qml7
-rw-r--r--tests/auto/qml/qqmllanguage/data/selfreferencingsingletonmodule/qmldir1
-rw-r--r--tests/auto/qml/qqmllanguage/data/singleton/SingletonTypeWithIC.qml16
-rw-r--r--tests/auto/qml/qqmllanguage/data/singleton/qmldir1
-rw-r--r--tests/auto/qml/qqmllanguage/data/singletonICTest.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/unsupportedProperty.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/unsupportedProperty.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/qqmllanguage.pro5
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp12
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h114
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp546
-rw-r--r--tests/auto/qml/qqmllistmodel/qqmllistmodel.pro2
-rw-r--r--tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp2
-rw-r--r--tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp213
-rw-r--r--tests/auto/qml/qqmllocale/tst_qqmllocale.cpp32
-rw-r--r--tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp4
-rw-r--r--tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp42
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton.qml7
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp4
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp4
-rw-r--r--tests/auto/qml/qqmlnotifier/data/connectnotify.qml3
-rw-r--r--tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp7
-rw-r--r--tests/auto/qml/qqmlparser/data/annotations/View1.qml76
-rw-r--r--tests/auto/qml/qqmlparser/data/noannotations/View1.qml76
-rw-r--r--tests/auto/qml/qqmlparser/qqmlparser.pro1
-rw-r--r--tests/auto/qml/qqmlparser/tst_qqmlparser.cpp147
-rw-r--r--tests/auto/qml/qqmlproperty/data/aliasToBinding.qml23
-rw-r--r--tests/auto/qml/qqmlproperty/data/assignEmptyVariantMap.qml1
-rw-r--r--tests/auto/qml/qqmlproperty/data/interfaceBinding2.qml27
-rw-r--r--tests/auto/qml/qqmlproperty/interfaces.h161
-rw-r--r--tests/auto/qml/qqmlproperty/qqmlproperty.pro8
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp158
-rw-r--r--tests/auto/qml/qqmlqt/data/formatting.qml5
-rw-r--r--tests/auto/qml/qqmlqt/data/formattingLocale.qml12
-rw-r--r--tests/auto/qml/qqmlqt/data/timeRoundtrip.qml2
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp71
-rw-r--r--tests/auto/qml/qqmltablemodel/qqmltablemodel.pro2
-rw-r--r--tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp32
-rw-r--r--tests/auto/qml/qqmltypeloader/data/declarativeCppType.qml6
-rw-r--r--tests/auto/qml/qqmltypeloader/declarativetesttype.h44
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp50
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro9
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/data/userType.qml1
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp6
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/qmlproperty_read.qml9
-rw-r--r--tests/auto/qml/qqmlvaluetypes/testtypes.h8
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp15
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/file_request.qml32
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp346
-rw-r--r--tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp17
-rw-r--r--tests/auto/qml/qquickworkerscript/data/BaseWorker.qml5
-rw-r--r--tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp18
-rw-r--r--tests/auto/qmltest/listview/data/MultiDelegate3.qml97
-rw-r--r--tests/auto/qmltest/listview/tst_listview.qml17
-rw-r--r--tests/auto/quick/drawingmodes/tst_drawingmodes.cpp14
-rw-r--r--tests/auto/quick/nodes/tst_nodestest.cpp9
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp4
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml5
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp114
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml12
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp46
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp60
-rw-r--r--tests/auto/quick/qquickanimatedsprite/data/finishBehavior.qml18
-rw-r--r--tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp63
-rw-r--r--tests/auto/quick/qquickanimations/data/signalorder.qml27
-rw-r--r--tests/auto/quick/qquickanimations/qquickanimations.pro1
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp270
-rw-r--r--tests/auto/quick/qquickbehaviors/data/targetProperty.qml16
-rw-r--r--tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp22
-rw-r--r--tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp2
-rw-r--r--tests/auto/quick/qquickboundaryrule/data/dragHandler.qml1
-rw-r--r--tests/auto/quick/qquickboundaryrule/qquickboundaryrule.pro2
-rw-r--r--tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp24
-rw-r--r--tests/auto/quick/qquickflickable/data/resize.qml1
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp7
-rw-r--r--tests/auto/quick/qquickimage/data/ProPhoto.jpgbin0 -> 30900 bytes
-rw-r--r--tests/auto/quick/qquickimage/data/image.qml5
-rw-r--r--tests/auto/quick/qquickimage/tst_qquickimage.cpp106
-rw-r--r--tests/auto/quick/qquickitem/data/hellotr_la.qmbin0 -> 237 bytes
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp35
-rw-r--r--tests/auto/quick/qquickitem2/data/mapCoordinates.qml20
-rw-r--r--tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml10
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp32
-rw-r--r--tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp8
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml6
-rw-r--r--tests/auto/quick/qquicklistview/data/delegatesWithRequiredProperties.qml47
-rw-r--r--tests/auto/quick/qquicklistview/data/listview-sections_delegate_required.qml77
-rw-r--r--tests/auto/quick/qquicklistview/data/requiredObjectListModel.qml15
-rw-r--r--tests/auto/quick/qquicklistview/data/reusedelegateitems.qml98
-rw-r--r--tests/auto/quick/qquicklistview/qquicklistview.pro3
-rw-r--r--tests/auto/quick/qquicklistview/reusemodel.h84
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp567
-rw-r--r--tests/auto/quick/qquickloader/data/RequiredPropertyValuesComponent.qml8
-rw-r--r--tests/auto/quick/qquickloader/data/initialPropertyValues.10.qml20
-rw-r--r--tests/auto/quick/qquickloader/data/initialPropertyValues.9.qml20
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp10
-rw-r--r--tests/auto/quick/qquickmousearea/data/dragreset.qml1
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp56
-rw-r--r--tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.2.qml59
-rw-r--r--tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.3.qml64
-rw-r--r--tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.qml53
-rw-r--r--tests/auto/quick/qquickpathview/data/delegatewithUnrelatedRequiredPreventsAccessToModel.qml52
-rw-r--r--tests/auto/quick/qquickpathview/tst_qquickpathview.cpp37
-rw-r--r--tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp6
-rw-r--r--tests/auto/quick/qquickpositioners/data/transitions-padding.qml10
-rw-r--r--tests/auto/quick/qquickpositioners/data/transitions.qml10
-rw-r--r--tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp63
-rw-r--r--tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp2
-rw-r--r--tests/auto/quick/qquickrendercontrol/data/rect.qml47
-rw-r--r--tests/auto/quick/qquickrendercontrol/qquickrendercontrol.pro12
-rw-r--r--tests/auto/quick/qquickrendercontrol/tst_qquickrendercontrol.cpp202
-rw-r--r--tests/auto/quick/qquickrepeater/data/contextProperty.qml13
-rw-r--r--tests/auto/quick/qquickrepeater/data/objlist_required.qml23
-rw-r--r--tests/auto/quick/qquickrepeater/data/package2.qml36
-rw-r--r--tests/auto/quick/qquickrepeater/data/requiredProperty.qml16
-rw-r--r--tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp59
-rw-r--r--tests/auto/quick/qquickshape/tst_qquickshape.cpp18
-rw-r--r--tests/auto/quick/qquickstates/data/parentChangeCorrectReversal.qml72
-rw-r--r--tests/auto/quick/qquickstates/tst_qquickstates.cpp17
-rw-r--r--tests/auto/quick/qquicktableview/data/delegateWithRequired.qml70
-rw-r--r--tests/auto/quick/qquicktableview/data/delegatewithRequiredUnset.qml71
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp45
-rw-r--r--tests/auto/quick/qquicktext/BLACKLIST2
-rw-r--r--tests/auto/quick/qquicktext/data/displaySuperscriptedTag.qml18
-rw-r--r--tests/auto/quick/qquicktext/data/lineLayout.qml9
-rw-r--r--tests/auto/quick/qquicktext/data/lineLayoutImplicitWidth.qml80
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp88
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp30
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp88
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/readFromProxyObject.qml23
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp16
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp18
-rw-r--r--tests/auto/quick/quick.pro5
-rw-r--r--tests/auto/quick/rendernode/tst_rendernode.cpp6
-rw-r--r--tests/auto/quick/scenegraph/tst_scenegraph.cpp2
-rw-r--r--tests/auto/quick/shared/viewtestutil.cpp22
-rw-r--r--tests/auto/quickwidgets/qquickwidget/data/resizeOverlay.qml15
-rw-r--r--tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp70
-rw-r--r--tests/auto/shared/astdump.pri7
-rw-r--r--tests/auto/shared/qqmljsastdumper.cpp1079
-rw-r--r--tests/auto/shared/qqmljsastdumper.h446
-rw-r--r--tests/benchmarks/qml/holistic/testtypes.h1
-rw-r--r--tests/libfuzzer/qml/jsapi/evaluate/evaluate.pro7
-rw-r--r--tests/manual/listview/listview.pro29
-rw-r--r--tests/manual/listview/main.cpp103
-rw-r--r--tests/manual/listview/main.qml171
-rw-r--r--tests/manual/listview/qml.qrc5
-rwxr-xr-xtests/manual/nodetypes_ng/compile.bat (renamed from tests/manual/nodetypes_ng/buildshaders.bat)0
-rw-r--r--tests/manual/nodetypes_ng/shadow_pass1.frag.qsbbin2218 -> 1822 bytes
-rw-r--r--tests/manual/nodetypes_ng/shadow_pass2.frag.qsbbin2131 -> 1745 bytes
-rw-r--r--tests/manual/nodetypes_ng/wobble.frag.qsbbin2013 -> 1627 bytes
-rw-r--r--tests/manual/nodetypes_ng/wobble.vert.qsbbin2001 -> 1641 bytes
-rw-r--r--tests/manual/pointer/main.qml3
-rw-r--r--tests/manual/pointer/pointerDrag.qml65
-rw-r--r--tests/manual/pointer/qml.qrc5
-rw-r--r--tests/manual/pointer/resources/cursor-airbrush.pngbin0 -> 823 bytes
-rw-r--r--tests/manual/pointer/resources/cursor-eraser.pngbin0 -> 1454 bytes
-rw-r--r--tests/manual/pointer/resources/cursor-felt-marker.pngbin0 -> 513 bytes
-rw-r--r--tests/manual/pointer/resources/cursor-pencil.pngbin0 -> 1307 bytes
-rw-r--r--tests/manual/pointer/sidebar.qml7
-rw-r--r--tests/manual/pointer/tabletCanvasDrawing.qml242
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/activity/activity.qml9
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/basic/basic.qml8
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/culling/culling_1.qml11
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/culling/culling_2.qml11
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/gridmesh/attributes.qml65
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_1.qml17
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_16.qml17
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_2.qml19
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_4.qml17
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_8.qml17
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/hiddensource/hiddensource_1.qml18
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/hiddensource/hiddensource_2.qml19
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/hiddensource/unhidden_1.qml18
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/hiddensource/unhidden_2.qml20
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/image/async.qml12
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/image/source.qml10
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/live/liveonce_1.qml9
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/live/liveonce_2.qml9
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/live/livetwice_1.qml20
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/live/livetwice_2.qml20
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/live/samesource.qml18
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/source/one-source.qml9
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/source/rect.qml9
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/source/switch_1.qml9
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/source/switch_2.qml9
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/source/switch_3.qml9
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/source/two-sources.qml10
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/source/visible_1.qml10
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/source/visible_2.qml10
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/texture/size.qml17
-rw-r--r--tests/manual/scenegraph_lancelot/data/shaders/wrap/modes.qml17
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_text.qml91
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/basic.fragbin0 -> 813 bytes
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/cmyk.fragbin0 -> 1923 bytes
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/culling.fragbin0 -> 1238 bytes
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/edge.fragbin0 -> 1831 bytes
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient.fragbin0 -> 1061 bytes
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient2.fragbin0 -> 1064 bytes
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient3.fragbin0 -> 1059 bytes
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient4.fragbin0 -> 1057 bytes
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient5.fragbin0 -> 1050 bytes
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/shadow.fragbin0 -> 2041 bytes
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/stencil.fragbin0 -> 1122 bytes
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/wave.vertbin0 -> 1799 bytes
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/basic.frag5
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/basic_rhi.frag8
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/cmyk.frag14
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/cmyk_rhi.frag18
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/compile.bat13
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/culling.frag9
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/culling_rhi.frag13
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/edge.frag14
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/edge_rhi.frag23
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/gradient.frag6
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/gradient2.frag6
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/gradient2_rhi.frag10
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/gradient3.frag6
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/gradient3_rhi.frag10
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/gradient4.frag6
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/gradient4_rhi.frag10
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/gradient5.frag6
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/gradient5_rhi.frag10
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/gradient_rhi.frag10
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/shadow.frag14
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/shadow_rhi.frag23
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/stencil.frag7
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/stencil_rhi.frag11
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/wave.vert12
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shaders/wave_rhi.vert18
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/shared.qrc28
-rw-r--r--tests/manual/scenegraph_lancelot/scenegrabber/scenegrabber.pro3
-rw-r--r--tests/manual/scenegraph_lancelot/scenegraph/tst_scenegraph.cpp2
-rw-r--r--tests/manual/tableview/abstracttablemodel/main.qml14
-rw-r--r--tests/manual/tableview/imagetiling/imageTiling.qml90
-rw-r--r--tests/manual/tableview/imagetiling/map.pdfbin0 -> 31904 bytes
-rw-r--r--tests/manual/tableview/imagetiling/map.pngbin0 -> 21101 bytes
-rw-r--r--tests/manual/tableview/imagetiling/map.svgzbin0 -> 27956 bytes
467 files changed, 11568 insertions, 1420 deletions
diff --git a/tests/auto/particles/qquickitemparticle/data/takeGive.qml b/tests/auto/particles/qquickitemparticle/data/takeGive.qml
new file mode 100644
index 0000000000..e95ae738bd
--- /dev/null
+++ b/tests/auto/particles/qquickitemparticle/data/takeGive.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Particles 2.0
+
+Rectangle {
+ id: testTakeGive
+ color: "black"
+ width: 320
+ height: 320
+
+ function takeItems()
+ {
+ for(var i = 0; i < imgList.count; i++) ip.take(imgList.itemAt(i));
+ }
+ function giveItems()
+ {
+ for(var i = 0; i < imgList.count; i++) ip.give(imgList.itemAt(i));
+ }
+
+ Repeater {
+ id: imgList
+ model: 100
+ delegate: Image {
+ ItemParticle.onAttached: sys.acc = sys.acc + 1
+ ItemParticle.onDetached: sys.acc = sys.acc - 1;
+ source: "../../shared/star.png"
+ }
+ }
+
+ ParticleSystem {
+ id: sys
+ objectName: "system"
+ anchors.fill: parent
+ property int acc: 0
+
+ ItemParticle {
+ id: ip
+ }
+
+ Emitter{
+ //0,0 position
+ size: 32
+ emitRate: 1000
+ lifeSpan: Emitter.InfiniteLife
+ }
+ }
+}
diff --git a/tests/auto/particles/qquickitemparticle/tst_qquickitemparticle.cpp b/tests/auto/particles/qquickitemparticle/tst_qquickitemparticle.cpp
index ea4e7a97a6..28ebbb3c05 100644
--- a/tests/auto/particles/qquickitemparticle/tst_qquickitemparticle.cpp
+++ b/tests/auto/particles/qquickitemparticle/tst_qquickitemparticle.cpp
@@ -45,6 +45,7 @@ private slots:
void test_basic();
void test_deletion();
void test_noDeletion();
+ void test_takeGive();
void test_noCrashOnReset();
void test_noLeakWhenDeleted();
};
@@ -109,6 +110,18 @@ void tst_qquickitemparticle::test_noDeletion()
delete view;
}
+void tst_qquickitemparticle::test_takeGive()
+{
+ QQuickView* view = createView(testFileUrl("takeGive.qml"), 500);
+ QQuickParticleSystem* system = view->rootObject()->findChild<QQuickParticleSystem*>("system");
+ QMetaObject::invokeMethod(view->rootObject(), "takeItems");
+ ensureAnimTime(1000, system->m_animation);
+ QVERIFY(system->property("acc").toInt() == 100);
+ QMetaObject::invokeMethod(view->rootObject(), "giveItems");
+ QTRY_VERIFY(system->property("acc").toInt() == 0);
+ delete view;
+}
+
void tst_qquickitemparticle::test_noCrashOnReset()
{
QQuickView* view = createView(testFileUrl("basic.qml"), 600);
diff --git a/tests/auto/qml/debugger/debugger.pro b/tests/auto/qml/debugger/debugger.pro
index 5c328fbfcc..890e722aa3 100644
--- a/tests/auto/qml/debugger/debugger.pro
+++ b/tests/auto/qml/debugger/debugger.pro
@@ -4,6 +4,7 @@ SUBDIRS += qqmldebugjsserver
PUBLICTESTS += \
qdebugmessageservice \
+ qqmldebugtranslationservice \
qqmlenginedebugservice \
qqmldebugjs \
qqmlinspector \
diff --git a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
index d2cfd3897a..ec7ee15d34 100644
--- a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
+++ b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
@@ -88,8 +88,7 @@ public:
QList<LogEntry> logBuffer;
protected:
- //inherited from QQmlDebugClient
- void messageReceived(const QByteArray &data);
+ void messageReceived(const QByteArray &data) override;
signals:
void debugOutput();
@@ -136,7 +135,7 @@ QList<QQmlDebugClient *> tst_QDebugMessageService::createClients()
void tst_QDebugMessageService::retrieveDebugOutput()
{
- QCOMPARE(QQmlDebugTest::connect(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml",
+ QCOMPARE(QQmlDebugTest::connectTo(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml",
QString(), testFile(QMLFILE), true), ConnectSuccess);
QTRY_VERIFY(m_client->logBuffer.size() >= 2);
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml b/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml
index deba24cf91..a7231df48b 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml
@@ -36,5 +36,9 @@ Item {
}
id: root
property int a: 10
+
+ Item {
+ property int b: 11
+ }
}
diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
index 5b6c43bc0c..91470e0651 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
@@ -180,7 +180,7 @@ QQmlDebugTest::ConnectResult tst_QQmlDebugJS::init(bool qmlscene, const QString
const QString executable = qmlscene
? QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene"
: debugJsServerPath("qqmldebugjs");
- return QQmlDebugTest::connect(
+ return QQmlDebugTest::connectTo(
executable, restrictServices ? QStringLiteral("V8Debugger") : QString(),
testFile(qmlFile), blockMode);
}
@@ -896,6 +896,16 @@ void tst_QQmlDebugJS::evaluateInContext()
QVERIFY(waitForClientSignal(SIGNAL(result())));
QTRY_COMPARE(responseBody(m_client).value("value").toInt(), 20);
+
+ auto childObjects = object.children;
+ QVERIFY(childObjects.count() > 0); // QQmlComponentAttached is also in there
+ QCOMPARE(childObjects[0].className, QString::fromLatin1("Item"));
+
+ // "b" accessible in context of surrounding (child) object
+ m_client->evaluate(QLatin1String("b"), -1, childObjects[0].debugId);
+ QVERIFY(waitForClientSignal(SIGNAL(result())));
+
+ QTRY_COMPARE(responseBody(m_client).value("value").toInt(), 11);
}
void tst_QQmlDebugJS::getScripts()
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml b/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml
new file mode 100644
index 0000000000..234496577a
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Controls 2.12
+
+Item {
+ width: 360
+ height: 360
+
+ Text {
+ text: qsTr("hello")
+ width: parent.width / 10
+ elide: Text.ElideRight
+ }
+}
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/qqmldebugtranslationservice.pro b/tests/auto/qml/debugger/qqmldebugtranslationservice/qqmldebugtranslationservice.pro
new file mode 100644
index 0000000000..32e60e306d
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/qqmldebugtranslationservice.pro
@@ -0,0 +1,12 @@
+CONFIG += testcase
+TARGET = tst_qdebugtranslationservice
+QT += network testlib gui-private core-private qmldebug-private
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_qqmldebugtranslationservice.cpp
+
+include(../shared/debugutil.pri)
+
+TESTDATA = data/*
+
+OTHER_FILES += data/test.qml
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp b/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp
new file mode 100644
index 0000000000..01ee805dee
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//QQmlDebugTest
+#include <debugutil_p.h>
+#include <qqmldebugprocess_p.h>
+
+#include <private/qqmldebugclient_p.h>
+#include <private/qqmldebugtranslationclient_p.h>
+#include <private/qqmldebugconnection_p.h>
+#include <private/qpacket_p.h>
+
+#include <QtCore/qstring.h>
+#include <QtCore/qlibraryinfo.h>
+#include <QtTest/qtest.h>
+
+const char *QMLFILE = "test.qml";
+
+class tst_QQmlDebugTranslationService : public QQmlDebugTest
+{
+ Q_OBJECT
+
+private slots:
+ void pluginConnection();
+
+private:
+ QList<QQmlDebugClient *> createClients() override;
+ QPointer<QQmlDebugTranslationClient> m_client;
+};
+
+QList<QQmlDebugClient *> tst_QQmlDebugTranslationService::createClients()
+{
+ m_client = new QQmlDebugTranslationClient(m_connection);
+
+ QObject::connect(m_client, &QQmlDebugClient::stateChanged, m_client, [this](QQmlDebugClient::State newState) {
+ QCOMPARE(newState, m_client->state());
+ });
+
+ return {m_client};
+}
+
+void tst_QQmlDebugTranslationService::pluginConnection()
+{
+ auto executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml";
+ auto services = "DebugTranslation";
+ auto extraArgs = testFile(QMLFILE);
+ auto block = true;
+
+ auto result = QQmlDebugTest::connectTo(executable, services, extraArgs, block);
+ QCOMPARE(result, ConnectSuccess);
+}
+
+QTEST_MAIN(tst_QQmlDebugTranslationService)
+
+#include "tst_qqmldebugtranslationservice.moc"
diff --git a/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp b/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
index a8c43b1c75..c8915fb840 100644
--- a/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
+++ b/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
@@ -66,7 +66,7 @@ class tst_QQmlEngineControl : public QQmlDebugTest
Q_OBJECT
private:
- ConnectResult connect(const QString &testFile, bool restrictServices);
+ ConnectResult connectTo(const QString &testFile, bool restrictServices);
QList<QQmlDebugClient *> createClients() override;
void engine_data();
@@ -79,10 +79,10 @@ private slots:
void stopEngine();
};
-QQmlDebugTest::ConnectResult tst_QQmlEngineControl::connect(const QString &file,
+QQmlDebugTest::ConnectResult tst_QQmlEngineControl::connectTo(const QString &file,
bool restrictServices)
{
- return QQmlDebugTest::connect(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene",
+ return QQmlDebugTest::connectTo(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene",
restrictServices ? QStringLiteral("EngineControl") : QString(),
testFile(file), true);
}
@@ -109,7 +109,7 @@ void tst_QQmlEngineControl::startEngine_data()
void tst_QQmlEngineControl::startEngine()
{
QFETCH(bool, restrictMode);
- QCOMPARE(connect("test.qml", restrictMode), ConnectSuccess);
+ QCOMPARE(connectTo("test.qml", restrictMode), ConnectSuccess);
QTRY_VERIFY(!m_client->blockedEngines().empty());
m_client->releaseEngine(m_client->blockedEngines().last());
@@ -130,7 +130,7 @@ void tst_QQmlEngineControl::stopEngine()
{
QFETCH(bool, restrictMode);
- QCOMPARE(connect("exit.qml", restrictMode), ConnectSuccess);
+ QCOMPARE(connectTo("exit.qml", restrictMode), ConnectSuccess);
QTRY_VERIFY(!m_client->blockedEngines().empty());
m_client->releaseEngine(m_client->blockedEngines().last());
diff --git a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
index 980e2be1f1..9830f1a9bd 100644
--- a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
@@ -87,7 +87,7 @@ QQmlEngineDebugObjectReference tst_QQmlEngineDebugInspectorIntegration::findRoot
QQmlDebugTest::ConnectResult tst_QQmlEngineDebugInspectorIntegration::init(bool restrictServices)
{
- return QQmlDebugTest::connect(
+ return QQmlDebugTest::connectTo(
QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml",
restrictServices ? QStringLiteral("QmlDebugger,QmlInspector") : QString(),
testFile("qtquick2.qml"), true);
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
index 0ebf43eb6f..12befeb1ec 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
@@ -280,11 +280,11 @@ void tst_QQmlEngineDebugService::recursiveObjectTest(
} else {
QCOMPARE(ref.name, QString("<unknown value>"));
}
- } else if (pmeta.type() < QVariant::UserType && pmeta.userType() != QMetaType::QVariant) {
+ } else if (pmeta.userType() < QMetaType::User && pmeta.userType() != QMetaType::QVariant) {
const QVariant expected = pmeta.read(o);
QVERIFY2(p.value == expected, QString::fromLatin1("%1 != %2. Details: %3/%4/%5/%6")
.arg(QTest::toString(p.value)).arg(QTest::toString(expected)).arg(p.name)
- .arg(p.valueTypeName).arg(pmeta.type()).arg(pmeta.userType()).toUtf8());
+ .arg(p.valueTypeName).arg(pmeta.userType()).arg(pmeta.userType()).toUtf8());
}
if (p.name == "parent")
diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
index 6685558bb5..b5f45f1eeb 100644
--- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
+++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
@@ -64,7 +64,7 @@ private slots:
QQmlDebugTest::ConnectResult tst_QQmlInspector::startQmlProcess(const QString &qmlFile,
bool restrictServices)
{
- return QQmlDebugTest::connect(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml",
+ return QQmlDebugTest::connectTo(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml",
restrictServices ? QStringLiteral("QmlInspector") : QString(),
testFile(qmlFile), true);
}
diff --git a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp
index f08f3c1da7..bfec776614 100644
--- a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp
+++ b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp
@@ -74,7 +74,7 @@ private slots:
QQmlDebugTest::ConnectResult tst_QQmlPreview::startQmlProcess(const QString &qmlFile)
{
- return QQmlDebugTest::connect(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml",
+ return QQmlDebugTest::connectTo(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml",
QStringLiteral("QmlPreview"), testFile(qmlFile), true);
}
@@ -122,7 +122,6 @@ void checkFiles(const QStringList &files)
{
QVERIFY(!files.contains("/etc/localtime"));
QVERIFY(!files.contains("/etc/timezome"));
- QVERIFY(!files.contains(":/qgradient/webgradients.binaryjson"));
}
void tst_QQmlPreview::cleanup()
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index 085eb7b87a..c2a774b42d 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -201,7 +201,7 @@ private:
CheckType = CheckMessageType | CheckDetailType | CheckLine | CheckColumn | CheckFileEndsWith
};
- ConnectResult connect(bool block, const QString &file, bool recordFromStart = true,
+ ConnectResult connectTo(bool block, const QString &file, bool recordFromStart = true,
uint flushInterval = 0, bool restrictServices = true,
const QString &executable
= QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene");
@@ -246,7 +246,7 @@ private:
#define VERIFY(type, position, expected, checks, numbers) \
QVERIFY(verify(type, position, expected, checks, numbers))
-QQmlDebugTest::ConnectResult tst_QQmlProfilerService::connect(
+QQmlDebugTest::ConnectResult tst_QQmlProfilerService::connectTo(
bool block, const QString &file, bool recordFromStart, uint flushInterval,
bool restrictServices, const QString &executable)
{
@@ -255,7 +255,7 @@ QQmlDebugTest::ConnectResult tst_QQmlProfilerService::connect(
m_isComplete = false;
// ### Still using qmlscene due to QTBUG-33377
- return QQmlDebugTest::connect(
+ return QQmlDebugTest::connectTo(
executable,
restrictServices ? "CanvasFrameRate,EngineControl,DebugMessages" : QString(),
testFile(file), block);
@@ -542,7 +542,7 @@ void tst_QQmlProfilerService::connect()
QFETCH(bool, restrictMode);
QFETCH(bool, traceEnabled);
- QCOMPARE(connect(blockMode, "test.qml", traceEnabled, 0, restrictMode), ConnectSuccess);
+ QCOMPARE(connectTo(blockMode, "test.qml", traceEnabled, 0, restrictMode), ConnectSuccess);
if (!traceEnabled)
m_client->client->setRecording(true);
@@ -556,7 +556,7 @@ void tst_QQmlProfilerService::connect()
void tst_QQmlProfilerService::pixmapCacheData()
{
- QCOMPARE(connect(true, "pixmapCacheTest.qml"), ConnectSuccess);
+ QCOMPARE(connectTo(true, "pixmapCacheTest.qml"), ConnectSuccess);
// Don't wait for readyReadStandardOutput before the loop. It may have already arrived.
while (m_process->output().indexOf(QLatin1String("image loaded")) == -1 &&
@@ -594,7 +594,7 @@ void tst_QQmlProfilerService::pixmapCacheData()
void tst_QQmlProfilerService::scenegraphData()
{
- QCOMPARE(connect(true, "scenegraphTest.qml"), ConnectSuccess);
+ QCOMPARE(connectTo(true, "scenegraphTest.qml"), ConnectSuccess);
while (!m_process->output().contains(QLatin1String("tick")))
QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
@@ -654,7 +654,7 @@ void tst_QQmlProfilerService::scenegraphData()
void tst_QQmlProfilerService::profileOnExit()
{
- QCOMPARE(connect(true, "exit.qml"), ConnectSuccess);
+ QCOMPARE(connectTo(true, "exit.qml"), ConnectSuccess);
checkProcessTerminated();
checkTraceReceived();
@@ -663,7 +663,7 @@ void tst_QQmlProfilerService::profileOnExit()
void tst_QQmlProfilerService::controlFromJS()
{
- QCOMPARE(connect(true, "controlFromJS.qml", false), ConnectSuccess);
+ QCOMPARE(connectTo(true, "controlFromJS.qml", false), ConnectSuccess);
QTRY_VERIFY(m_client->numLoadedEventTypes() > 0);
m_client->client->setRecording(false);
@@ -673,7 +673,7 @@ void tst_QQmlProfilerService::controlFromJS()
void tst_QQmlProfilerService::signalSourceLocation()
{
- QCOMPARE(connect(true, "signalSourceLocation.qml"), ConnectSuccess);
+ QCOMPARE(connectTo(true, "signalSourceLocation.qml"), ConnectSuccess);
while (!(m_process->output().contains(QLatin1String("500"))))
QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
@@ -694,7 +694,7 @@ void tst_QQmlProfilerService::signalSourceLocation()
void tst_QQmlProfilerService::javascript()
{
- QCOMPARE(connect(true, "javascript.qml"), ConnectSuccess);
+ QCOMPARE(connectTo(true, "javascript.qml"), ConnectSuccess);
while (!(m_process->output().contains(QLatin1String("done"))))
QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
@@ -722,7 +722,7 @@ void tst_QQmlProfilerService::javascript()
void tst_QQmlProfilerService::flushInterval()
{
- QCOMPARE(connect(true, "timer.qml", true, 1), ConnectSuccess);
+ QCOMPARE(connectTo(true, "timer.qml", true, 1), ConnectSuccess);
// Make sure we get multiple messages
QTRY_VERIFY(m_client->qmlMessages.length() > 0);
@@ -736,7 +736,7 @@ void tst_QQmlProfilerService::flushInterval()
void tst_QQmlProfilerService::translationBinding()
{
- QCOMPARE(connect(true, "qstr.qml"), ConnectSuccess);
+ QCOMPARE(connectTo(true, "qstr.qml"), ConnectSuccess);
checkProcessTerminated();
checkTraceReceived();
@@ -752,7 +752,7 @@ void tst_QQmlProfilerService::translationBinding()
void tst_QQmlProfilerService::memory()
{
- QCOMPARE(connect(true, "memory.qml"), ConnectSuccess);
+ QCOMPARE(connectTo(true, "memory.qml"), ConnectSuccess);
checkProcessTerminated();
checkTraceReceived();
@@ -781,7 +781,7 @@ static bool hasCompileEvents(const QVector<QQmlProfilerEventType> &types)
void tst_QQmlProfilerService::compile()
{
// Flush interval so that we actually get the events before we stop recording.
- connect(true, "test.qml", true, 100);
+ connectTo(true, "test.qml", true, 100);
QVERIFY(m_client);
@@ -820,7 +820,7 @@ void tst_QQmlProfilerService::compile()
void tst_QQmlProfilerService::multiEngine()
{
- QCOMPARE(connect(true, "quit.qml", true, 0, false, debugJsServerPath("qqmlprofilerservice")),
+ QCOMPARE(connectTo(true, "quit.qml", true, 0, false, debugJsServerPath("qqmlprofilerservice")),
ConnectSuccess);
QSignalSpy spy(m_client->client, SIGNAL(complete(qint64)));
@@ -837,7 +837,7 @@ void tst_QQmlProfilerService::multiEngine()
void tst_QQmlProfilerService::batchOverflow()
{
// The trace client checks that the events are received in order.
- QCOMPARE(connect(true, "batchOverflow.qml"), ConnectSuccess);
+ QCOMPARE(connectTo(true, "batchOverflow.qml"), ConnectSuccess);
checkProcessTerminated();
checkTraceReceived();
checkJsHeap();
diff --git a/tests/auto/qml/debugger/shared/debugutil.cpp b/tests/auto/qml/debugger/shared/debugutil.cpp
index 68446b53a4..3787f34bc2 100644
--- a/tests/auto/qml/debugger/shared/debugutil.cpp
+++ b/tests/auto/qml/debugger/shared/debugutil.cpp
@@ -120,7 +120,7 @@ void QQmlDebugTestClient::messageReceived(const QByteArray &ba)
emit serverMessage(ba);
}
-QQmlDebugTest::ConnectResult QQmlDebugTest::connect(
+QQmlDebugTest::ConnectResult QQmlDebugTest::connectTo(
const QString &executable, const QString &services, const QString &extraArgs,
bool block)
{
diff --git a/tests/auto/qml/debugger/shared/debugutil_p.h b/tests/auto/qml/debugger/shared/debugutil_p.h
index 1c32590305..190909dc44 100644
--- a/tests/auto/qml/debugger/shared/debugutil_p.h
+++ b/tests/auto/qml/debugger/shared/debugutil_p.h
@@ -53,7 +53,6 @@ public:
static QString clientStateString(const QQmlDebugClient *client);
static QString connectionStateString(const QQmlDebugConnection *connection);
-protected:
enum ConnectResult {
ConnectSuccess,
ProcessFailed,
@@ -64,7 +63,9 @@ protected:
RestrictFailed
};
- ConnectResult connect(const QString &executable, const QString &services,
+ Q_ENUM(ConnectResult)
+protected:
+ ConnectResult connectTo(const QString &executable, const QString &services,
const QString &extraArgs, bool block);
virtual QQmlDebugProcess *createProcess(const QString &executable);
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index 4c04afe886..6b743ba433 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -249,15 +249,6 @@ built-ins/String/prototype/toLocaleLowerCase/Final_Sigma_U180E.js fails
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/from/arylk-get-length-error.js fails
-built-ins/TypedArray/from/arylk-to-length-error.js fails
-built-ins/TypedArray/from/iter-access-error.js fails
-built-ins/TypedArray/from/iter-invoke-error.js fails
-built-ins/TypedArray/from/iter-next-error.js fails
-built-ins/TypedArray/from/iter-next-value-error.js fails
-built-ins/TypedArray/from/length.js fails
-built-ins/TypedArray/from/name.js fails
-built-ins/TypedArray/from/prop-desc.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
@@ -293,29 +284,6 @@ built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-not-cto
built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js fails
built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-throws.js fails
built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js fails
-built-ins/TypedArrays/from/arylk-get-length-error.js fails
-built-ins/TypedArrays/from/arylk-to-length-error.js fails
-built-ins/TypedArrays/from/custom-ctor-returns-other-instance.js fails
-built-ins/TypedArrays/from/custom-ctor.js fails
-built-ins/TypedArrays/from/iter-access-error.js fails
-built-ins/TypedArrays/from/iter-invoke-error.js fails
-built-ins/TypedArrays/from/iter-next-error.js fails
-built-ins/TypedArrays/from/iter-next-value-error.js fails
-built-ins/TypedArrays/from/mapfn-abrupt-completion.js fails
-built-ins/TypedArrays/from/mapfn-arguments.js fails
-built-ins/TypedArrays/from/mapfn-this-with-thisarg.js fails
-built-ins/TypedArrays/from/mapfn-this-without-thisarg-non-strict.js sloppyFails
-built-ins/TypedArrays/from/mapfn-this-without-thisarg-strict.js strictFails
-built-ins/TypedArrays/from/nan-conversion.js fails
-built-ins/TypedArrays/from/new-instance-empty.js fails
-built-ins/TypedArrays/from/new-instance-from-ordinary-object.js fails
-built-ins/TypedArrays/from/new-instance-from-sparse-array.js fails
-built-ins/TypedArrays/from/new-instance-from-zero.js fails
-built-ins/TypedArrays/from/new-instance-using-custom-ctor.js fails
-built-ins/TypedArrays/from/new-instance-with-mapfn.js fails
-built-ins/TypedArrays/from/new-instance-without-mapfn.js fails
-built-ins/TypedArrays/from/property-abrupt-completion.js fails
-built-ins/TypedArrays/from/set-value-abrupt-completion.js fails
built-ins/TypedArrays/internals/Get/key-is-not-integer.js fails
built-ins/TypedArrays/internals/Get/key-is-not-minus-zero.js fails
built-ins/TypedArrays/internals/Get/key-is-out-of-bounds.js fails
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 66a526fda8..26737e79c4 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -263,6 +263,9 @@ private slots:
void arrayIncludesWithLargeArray();
void printCircularArray();
void typedArraySet();
+ void dataViewCtor();
+
+ void uiLanguage();
public:
Q_INVOKABLE QJSValue throwingCppMethod1();
@@ -1543,7 +1546,7 @@ void tst_QJSEngine::valueConversion_QVariant()
{
QVariant tmp1;
QVariant tmp2(QMetaType::QVariant, &tmp1);
- QCOMPARE(QMetaType::Type(tmp2.type()), QMetaType::QVariant);
+ QCOMPARE(QMetaType::Type(tmp2.userType()), QMetaType::QVariant);
QJSValue val1 = eng.toScriptValue(tmp1);
QJSValue val2 = eng.toScriptValue(tmp2);
@@ -1558,9 +1561,9 @@ void tst_QJSEngine::valueConversion_QVariant()
QVariant tmp1(123);
QVariant tmp2(QMetaType::QVariant, &tmp1);
QVariant tmp3(QMetaType::QVariant, &tmp2);
- QCOMPARE(QMetaType::Type(tmp1.type()), QMetaType::Int);
- QCOMPARE(QMetaType::Type(tmp2.type()), QMetaType::QVariant);
- QCOMPARE(QMetaType::Type(tmp3.type()), QMetaType::QVariant);
+ QCOMPARE(QMetaType::Type(tmp1.userType()), QMetaType::Int);
+ QCOMPARE(QMetaType::Type(tmp2.userType()), QMetaType::QVariant);
+ QCOMPARE(QMetaType::Type(tmp3.userType()), QMetaType::QVariant);
QJSValue val1 = eng.toScriptValue(tmp2);
QJSValue val2 = eng.toScriptValue(tmp3);
@@ -3340,7 +3343,7 @@ void tst_QJSEngine::dateRoundtripJSQtJS()
#ifdef Q_OS_WIN
QSKIP("This test fails on Windows due to a bug in QDateTime.");
#endif
- qint64 secs = QDateTime(QDate(2009, 1, 1)).toUTC().toSecsSinceEpoch();
+ qint64 secs = QDate(2009, 1, 1).startOfDay(Qt::UTC).toSecsSinceEpoch();
QJSEngine eng;
for (int i = 0; i < 8000; ++i) {
QJSValue jsDate = eng.evaluate(QString::fromLatin1("new Date(%0)").arg(secs * 1000.0));
@@ -3357,7 +3360,7 @@ void tst_QJSEngine::dateRoundtripQtJSQt()
#ifdef Q_OS_WIN
QSKIP("This test fails on Windows due to a bug in QDateTime.");
#endif
- QDateTime qtDate = QDateTime(QDate(2009, 1, 1));
+ QDateTime qtDate = QDate(2009, 1, 1).startOfDay();
QJSEngine eng;
for (int i = 0; i < 8000; ++i) {
QJSValue jsDate = eng.toScriptValue(qtDate);
@@ -3373,7 +3376,7 @@ void tst_QJSEngine::dateConversionJSQt()
#ifdef Q_OS_WIN
QSKIP("This test fails on Windows due to a bug in QDateTime.");
#endif
- qint64 secs = QDateTime(QDate(2009, 1, 1)).toUTC().toSecsSinceEpoch();
+ qint64 secs = QDate(2009, 1, 1).startOfDay(Qt::UTC).toSecsSinceEpoch();
QJSEngine eng;
for (int i = 0; i < 8000; ++i) {
QJSValue jsDate = eng.evaluate(QString::fromLatin1("new Date(%0)").arg(secs * 1000.0));
@@ -3389,7 +3392,7 @@ void tst_QJSEngine::dateConversionJSQt()
void tst_QJSEngine::dateConversionQtJS()
{
- QDateTime qtDate = QDateTime(QDate(2009, 1, 1));
+ QDateTime qtDate = QDate(2009, 1, 1).startOfDay();
QJSEngine eng;
for (int i = 0; i < 8000; ++i) {
QJSValue jsDate = eng.toScriptValue(qtDate);
@@ -5143,6 +5146,48 @@ void tst_QJSEngine::typedArraySet()
}
}
+void tst_QJSEngine::dataViewCtor()
+{
+ QJSEngine engine;
+ const auto error = engine.evaluate(R"(
+ (function() { try {
+ var buf = new ArrayBuffer(0x200);
+ var vuln = new DataView(buf, 8, 0xfffffff8);
+ } catch (e) {
+ return e;
+ }})()
+ )");
+ QVERIFY(error.isError());
+ QCOMPARE(error.toString(), "RangeError: DataView: constructor arguments out of range");
+}
+
+void tst_QJSEngine::uiLanguage()
+{
+ {
+ QJSEngine engine;
+
+ QVERIFY(!engine.globalObject().hasProperty("Qt"));
+
+ engine.installExtensions(QJSEngine::TranslationExtension);
+ QVERIFY(engine.globalObject().hasProperty("Qt"));
+ QVERIFY(engine.globalObject().property("Qt").hasProperty("uiLanguage"));
+
+ engine.setUiLanguage("Blah");
+ QCOMPARE(engine.globalObject().property("Qt").property("uiLanguage").toString(), "Blah");
+
+ engine.evaluate("Qt.uiLanguage = \"another\"");
+ QCOMPARE(engine.globalObject().property("Qt").property("uiLanguage").toString(), "another");
+ }
+
+ {
+ QQmlEngine qmlEngine;
+ QVERIFY(qmlEngine.globalObject().hasProperty("Qt"));
+ QVERIFY(qmlEngine.globalObject().property("Qt").hasProperty("uiLanguage"));
+ qmlEngine.setUiLanguage("Blah");
+ QCOMPARE(qmlEngine.globalObject().property("Qt").property("uiLanguage").toString(), "Blah");
+ }
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"
diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
index cab4686c37..0d0bd2ae7e 100644
--- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
+++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
@@ -1067,7 +1067,7 @@ void tst_QJSValue::toVariant()
}
{
- QDateTime dateTime = QDateTime(QDate(1980, 10, 4));
+ QDateTime dateTime = QDate(1980, 10, 4).startOfDay();
QJSValue dateObject = eng.toScriptValue(dateTime);
QVariant var = dateObject.toVariant();
QCOMPARE(var, QVariant(dateTime));
@@ -1081,7 +1081,7 @@ void tst_QJSValue::toVariant()
// We can't roundtrip a QRegExp this way, as toVariant() has no information on whether we
// want QRegExp or QRegularExpression. It will always create a QRegularExpression.
- QCOMPARE(var.type(), QMetaType::QRegularExpression);
+ QCOMPARE(var.userType(), QMetaType::QRegularExpression);
QRegularExpression result = var.toRegularExpression();
QCOMPARE(result.pattern(), rx.pattern());
QCOMPARE(result.patternOptions() & QRegularExpression::CaseInsensitiveOption, 0);
@@ -1138,7 +1138,7 @@ void tst_QJSValue::toVariant()
QVERIFY(array.isArray());
QCOMPARE(array.property("length").toInt(), 2);
QVariant ret = array.toVariant();
- QCOMPARE(ret.type(), QVariant::List);
+ QCOMPARE(ret.userType(), QVariant::List);
QVariantList listOut = ret.toList();
QCOMPARE(listOut.size(), listIn.size());
for (int i = 0; i < listIn.size(); ++i)
@@ -1222,7 +1222,7 @@ void tst_QJSValue::toDateTime()
QDateTime dt = eng.evaluate("new Date(0)").toDateTime();
QVERIFY(dt.isValid());
QCOMPARE(dt.timeSpec(), Qt::LocalTime);
- QCOMPARE(dt.toUTC(), QDateTime(QDate(1970, 1, 1), QTime(0, 0, 0), Qt::UTC));
+ QCOMPARE(dt.toUTC(), QDate(1970, 1, 1).startOfDay(Qt::UTC));
QVERIFY(!eng.evaluate("[]").toDateTime().isValid());
QVERIFY(!eng.evaluate("{}").toDateTime().isValid());
@@ -2145,8 +2145,8 @@ void tst_QJSValue::equals()
QCOMPARE(str2.equals(QJSValue(321)), false);
QCOMPARE(str2.equals(QJSValue()), false);
- QJSValue date1 = eng.toScriptValue(QDateTime(QDate(2000, 1, 1)));
- QJSValue date2 = eng.toScriptValue(QDateTime(QDate(1999, 1, 1)));
+ QJSValue date1 = eng.toScriptValue(QDate(2000, 1, 1).startOfDay());
+ QJSValue date2 = eng.toScriptValue(QDate(1999, 1, 1).startOfDay());
QCOMPARE(date1.equals(date2), false);
QCOMPARE(date1.equals(date1), true);
QCOMPARE(date2.equals(date2), true);
@@ -2278,8 +2278,8 @@ void tst_QJSValue::strictlyEquals()
QCOMPARE(str2.strictlyEquals(QJSValue(321)), false);
QVERIFY(!str2.strictlyEquals(QJSValue()));
- QJSValue date1 = eng.toScriptValue(QDateTime(QDate(2000, 1, 1)));
- QJSValue date2 = eng.toScriptValue(QDateTime(QDate(1999, 1, 1)));
+ QJSValue date1 = eng.toScriptValue(QDate(2000, 1, 1).startOfDay());
+ QJSValue date2 = eng.toScriptValue(QDate(1999, 1, 1).startOfDay());
QCOMPARE(date1.strictlyEquals(date2), false);
QCOMPARE(date1.strictlyEquals(date1), true);
QCOMPARE(date2.strictlyEquals(date2), true);
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index db9bb52010..621e8bb437 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -91,7 +91,7 @@ SUBDIRS += $$METATYPETESTS
qtConfig(process) {
qtConfig(qml-debug): SUBDIRS += debugger
!boot2qt {
- SUBDIRS += qmllint qmlplugindump
+ SUBDIRS += qmlformat qmllint qmlplugindump
}
}
@@ -105,3 +105,6 @@ qtConfig(private_tests): \
qtNomakeTools( \
qmlplugindump \
)
+
+!cross_compile: \
+ SUBDIRS += qmltyperegistrar
diff --git a/tests/auto/qml/qmlcachegen/retain.qrc b/tests/auto/qml/qmlcachegen/data/retain.qrc
index e5eed9b12f..e1b9045fbe 100644
--- a/tests/auto/qml/qmlcachegen/retain.qrc
+++ b/tests/auto/qml/qmlcachegen/data/retain.qrc
@@ -1,5 +1,5 @@
<RCC>
<qresource prefix="/">
- <file alias="Retain.qml">data/Retain.qml</file>
+ <file alias="Retain.qml">Retain.qml</file>
</qresource>
</RCC>
diff --git a/tests/auto/qml/qmlcachegen/qmlcachegen.pro b/tests/auto/qml/qmlcachegen/qmlcachegen.pro
index 4daf1d35c3..452bd7d04a 100644
--- a/tests/auto/qml/qmlcachegen/qmlcachegen.pro
+++ b/tests/auto/qml/qmlcachegen/qmlcachegen.pro
@@ -28,7 +28,7 @@ workerscripts_test.prefix = /workerscripts
RESOURCES += \
workerscripts_test \
trickypaths.qrc \
- retain.qrc
+ data/retain.qrc
# QTBUG-46375
!win32: RESOURCES += trickypaths_umlaut.qrc
diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
index 4a1f5378a6..f940f9c476 100644
--- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
+++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
@@ -363,7 +363,7 @@ static QQmlPrivate::CachedQmlUnit *temporaryModifiedCachedUnit = nullptr;
void tst_qmlcachegen::versionChecksForAheadOfTimeUnits()
{
QVERIFY(QFile::exists(":/data/versionchecks.qml"));
- QCOMPARE(QFileInfo(":/data/versionchecks.qml").size(), 0);
+ QVERIFY(QFileInfo(":/data/versionchecks.qml").size() > 0);
Q_ASSERT(!temporaryModifiedCachedUnit);
QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
@@ -390,12 +390,8 @@ void tst_qmlcachegen::versionChecksForAheadOfTimeUnits()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl("qrc:/data/versionchecks.qml"));
- QCOMPARE(component.status(), QQmlComponent::Error);
- QCOMPARE(component.errorString(),
- QString("qrc:/data/versionchecks.qml:-1 File was compiled ahead of time with an "
- "incompatible version of Qt and the original file cannot be found. Please "
- "recompile\n"));
+ CleanlyLoadingComponent component(&engine, QUrl("qrc:/data/versionchecks.qml"));
+ QCOMPARE(component.status(), QQmlComponent::Ready);
}
Q_ASSERT(temporaryModifiedCachedUnit);
@@ -417,7 +413,7 @@ void tst_qmlcachegen::workerScripts()
{
QVERIFY(QFile::exists(":/workerscripts/data/worker.js"));
QVERIFY(QFile::exists(":/workerscripts/data/worker.qml"));
- QCOMPARE(QFileInfo(":/workerscripts/data/worker.js").size(), 0);
+ QVERIFY(QFileInfo(":/workerscripts/data/worker.js").size() > 0);
QQmlEngine engine;
CleanlyLoadingComponent component(&engine, QUrl("qrc:///workerscripts/data/worker.qml"));
@@ -506,7 +502,7 @@ void tst_qmlcachegen::trickyPaths()
{
QFETCH(QString, filePath);
QVERIFY2(QFile::exists(filePath), qPrintable(filePath));
- QCOMPARE(QFileInfo(filePath).size(), 0);
+ QVERIFY(QFileInfo(filePath).size() > 0);
QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc" + filePath));
QScopedPointer<QObject> obj(component.create());
@@ -587,7 +583,7 @@ void tst_qmlcachegen::moduleScriptImport()
QTRY_VERIFY(obj->property("ok").toBool());
QVERIFY(QFile::exists(":/data/script.mjs"));
- QCOMPARE(QFileInfo(":/data/script.mjs").size(), 0);
+ QVERIFY(QFileInfo(":/data/script.mjs").size() > 0);
{
auto componentPrivate = QQmlComponentPrivate::get(&component);
@@ -610,7 +606,6 @@ void tst_qmlcachegen::moduleScriptImport()
void tst_qmlcachegen::esModulesViaQJSEngine()
{
- QCOMPARE(QFileInfo(":/data/module.mjs").size(), 0);
QJSEngine engine;
QJSValue module = engine.importModule(":/data/module.mjs");
QJSValue result = module.property("entry").call();
@@ -629,7 +624,7 @@ void tst_qmlcachegen::enums()
void tst_qmlcachegen::sourceFileIndices()
{
QVERIFY(QFile::exists(":/data/versionchecks.qml"));
- QCOMPARE(QFileInfo(":/data/versionchecks.qml").size(), 0);
+ QVERIFY(QFileInfo(":/data/versionchecks.qml").size() > 0);
QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
const QV4::CompiledData::Unit *unitFromResources = QQmlMetaType::findCachedCompilationUnit(
@@ -644,8 +639,7 @@ void tst_qmlcachegen::reproducibleCache_data()
QTest::addColumn<QString>("filePath");
QDir dir(dataDirectory());
- for (const QString &entry : dir.entryList(QDir::Files)) {
- QVERIFY(entry.endsWith(".qml") || entry.endsWith(".js") || entry.endsWith(".mjs"));
+ for (const QString &entry : dir.entryList((QStringList() << "*.qml" << "*.js" << "*.mjs"), QDir::Files)) {
QTest::newRow(entry.toUtf8().constData()) << dir.filePath(entry);
}
}
diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
index 1f0115b926..d0c8390a74 100644
--- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
+++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
@@ -87,7 +87,9 @@ public:
void waitForLoad()
{
- QTRY_VERIFY(status() == QQmlComponent::Ready || status() == QQmlComponent::Error);
+ QTRY_VERIFY_WITH_TIMEOUT(
+ status() == QQmlComponent::Ready || status() == QQmlComponent::Error,
+ 32768);
}
};
diff --git a/tests/auto/qml/qmlformat/data/Annotations.formatted.nosort.qml b/tests/auto/qml/qmlformat/data/Annotations.formatted.nosort.qml
new file mode 100644
index 0000000000..a05c2125dc
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/Annotations.formatted.nosort.qml
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Charts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//![2]
+import QtQuick 2.0
+//![2]
+import QtCharts 2.0
+
+@Pippo {
+ atg1: 3
+}
+@Annotation2 {
+}
+Item {
+ //![1]
+
+ @AnnotateMore {
+ property int x: 5
+ }
+ @AnnotateALot {
+ }
+
+ property variant othersSlice: 0
+ @Annotate {
+ }
+
+ anchors.fill: parent
+ @SuperComplete {
+ binding: late
+ }
+ Component.onCompleted: {
+ // You can also manipulate slices dynamically, like append a slice or set a slice exploded
+ othersSlice = pieSeries.append("Others", 52);
+ pieSeries.find("Volkswagen").exploded = true;
+ }
+ //![1]
+ ChartView {
+ id: chart
+
+ title: "Top-5 car brand shares in Finland"
+ anchors.fill: parent
+ legend.alignment: Qt.AlignBottom
+ antialiasing: true
+
+ @ExtraAnnotation {
+ signal pippo()
+ }
+ PieSeries {
+ id: pieSeries
+
+ PieSlice {
+ label: "Volkswagen"
+ value: 13.5
+ }
+
+ PieSlice {
+ label: "Toyota"
+ value: 10.9
+ }
+
+ PieSlice {
+ label: "Ford"
+ value: 8.6
+ }
+
+ PieSlice {
+ label: "Skoda"
+ value: 8.2
+ }
+
+ PieSlice {
+ label: "Volvo"
+ value: 6.8
+ }
+
+ }
+
+ }
+
+}
diff --git a/tests/auto/qml/qmlformat/data/Annotations.formatted.qml b/tests/auto/qml/qmlformat/data/Annotations.formatted.qml
new file mode 100644
index 0000000000..a142d4cb74
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/Annotations.formatted.qml
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Charts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//![2]
+import QtCharts 2.0
+//![2]
+import QtQuick 2.0
+
+@Pippo {
+ atg1: 3
+}
+@Annotation2 {
+}
+Item {
+ //![1]
+
+ @AnnotateMore {
+ property int x: 5
+ }
+ @AnnotateALot {
+ }
+
+ property variant othersSlice: 0
+ @Annotate {
+ }
+
+ anchors.fill: parent
+ @SuperComplete {
+ binding: late
+ }
+ Component.onCompleted: {
+ // You can also manipulate slices dynamically, like append a slice or set a slice exploded
+ othersSlice = pieSeries.append("Others", 52);
+ pieSeries.find("Volkswagen").exploded = true;
+ }
+ //![1]
+ ChartView {
+ id: chart
+
+ title: "Top-5 car brand shares in Finland"
+ anchors.fill: parent
+ legend.alignment: Qt.AlignBottom
+ antialiasing: true
+
+ @ExtraAnnotation {
+ signal pippo()
+ }
+ PieSeries {
+ id: pieSeries
+
+ PieSlice {
+ label: "Volkswagen"
+ value: 13.5
+ }
+
+ PieSlice {
+ label: "Toyota"
+ value: 10.9
+ }
+
+ PieSlice {
+ label: "Ford"
+ value: 8.6
+ }
+
+ PieSlice {
+ label: "Skoda"
+ value: 8.2
+ }
+
+ PieSlice {
+ label: "Volvo"
+ value: 6.8
+ }
+
+ }
+
+ }
+
+}
diff --git a/tests/auto/qml/qmlformat/data/Annotations.qml b/tests/auto/qml/qmlformat/data/Annotations.qml
new file mode 100644
index 0000000000..2d3d7d2cfd
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/Annotations.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Charts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//![2]
+import QtQuick 2.0
+//![2]
+import QtCharts 2.0
+
+@Pippo{ atg1:3 }
+@Annotation2{}
+Item {
+ @Annotate{}
+ anchors.fill: parent
+ @AnnotateMore{
+ property int x: 5
+ }
+ @AnnotateALot{}
+ property variant othersSlice: 0
+
+ //![1]
+ ChartView {
+ id: chart
+ title: "Top-5 car brand shares in Finland"
+ anchors.fill: parent
+ legend.alignment: Qt.AlignBottom
+ antialiasing: true
+
+@ExtraAnnotation{
+ signal pippo
+}
+ PieSeries {
+ id: pieSeries
+ PieSlice { label: "Volkswagen"; value: 13.5 }
+ PieSlice { label: "Toyota"; value: 10.9 }
+ PieSlice { label: "Ford"; value: 8.6 }
+ PieSlice { label: "Skoda"; value: 8.2 }
+ PieSlice { label: "Volvo"; value: 6.8 }
+ }
+ }
+
+@SuperComplete{
+binding: late
+}
+ Component.onCompleted: {
+ // You can also manipulate slices dynamically, like append a slice or set a slice exploded
+ othersSlice = pieSeries.append("Others", 52.0);
+ pieSeries.find("Volkswagen").exploded = true;
+ }
+ //![1]
+}
diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.nosort.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.nosort.qml
new file mode 100644
index 0000000000..34d58cf571
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/Example1.formatted.nosort.qml
@@ -0,0 +1,152 @@
+/* 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 {
+ // Orphan comment
+ // Another orphan
+ // More orphans
+
+ // 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
+ }
+
+ property bool some_bool: false
+ property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
+ property bool something_computed: function(x) {
+ // This is an orphan inside something_computed
+ // Are these getting duplicated?
+ // Another orphan inside something_computed
+
+ const PI = 3, DAYS_PER_YEAR = 365.25;
+ var x = 3 + 2;
+ x["bla"] = 50;
+ // 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 {
+ dangerous();
+ }
+ 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");
+ }
+ return "foobar";
+ }()
+ 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
+
+ signal say(string name, bool caps)
+
+ // This one to aFunc()
+ function aFunc() {
+ var x = 3;
+ return x;
+ }
+
+ x: 3 // Very cool
+ Component.onCompleted: console.log("Foo!")
+ myFavouriteThings: [
+ // This is an orphan
+
+ // This is a cool text
+ Text {
+ },
+ // This is a cool rectangle
+ Rectangle {
+ }
+ ]
+
+ Text {
+ required property string batman
+
+ signal boo(int count, int times, real duration)
+
+ text: "Bla"
+ }
+
+ // This comment is related to the property animation
+ PropertyAnimation on x {
+ id: foo
+
+ x: 3
+ y: x + 3
+ }
+
+}
diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.qml
new file mode 100644
index 0000000000..b06734eb0b
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/Example1.formatted.qml
@@ -0,0 +1,152 @@
+/* This file is licensed under the not a license license
+ 1. You may not comply
+ 2. Goodbye
+*/
+
+import A.B.B.A
+import A.LLOHA
+// Importing this is very important
+import QtQuick 5.15
+// Muddling the waters!
+import QtQuick.Models 3.14 as muddle
+import That
+import This // THIS IS VERY IMPORTANT!
+import X.Y
+import X.Z
+import Y
+// Importing that is important too
+import Z
+
+// This comment is related to Item
+Item {
+ // Orphan comment
+ // Another orphan
+ // More orphans
+
+ // 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
+ }
+
+ property bool some_bool: false
+ property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
+ property bool something_computed: function(x) {
+ // This is an orphan inside something_computed
+ // Are these getting duplicated?
+ // Another orphan inside something_computed
+
+ const PI = 3, DAYS_PER_YEAR = 365.25;
+ var x = 3 + 2;
+ x["bla"] = 50;
+ // 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 {
+ dangerous();
+ }
+ 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");
+ }
+ return "foobar";
+ }()
+ 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
+
+ signal say(string name, bool caps)
+
+ // This one to aFunc()
+ function aFunc() {
+ var x = 3;
+ return x;
+ }
+
+ x: 3 // Very cool
+ Component.onCompleted: console.log("Foo!")
+ myFavouriteThings: [
+ // This is an orphan
+
+ // This is a cool text
+ Text {
+ },
+ // This is a cool rectangle
+ Rectangle {
+ }
+ ]
+
+ Text {
+ required property string batman
+
+ signal boo(int count, int times, real duration)
+
+ text: "Bla"
+ }
+
+ // This comment is related to the property animation
+ PropertyAnimation on x {
+ id: foo
+
+ x: 3
+ y: x + 3
+ }
+
+}
diff --git a/tests/auto/qml/qmlformat/data/Example1.qml b/tests/auto/qml/qmlformat/data/Example1.qml
new file mode 100644
index 0000000000..0fb9053e3a
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/Example1.qml
@@ -0,0 +1,105 @@
+
+
+/* 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 {
+ x: 3 // Very cool
+
+ // This to enum
+ enum Foo {
+ A = 3, // This is A
+ B, // This is B
+ C = 4, // This is C
+ D // This is D
+ }
+
+ // This one to aFunc()
+ function aFunc() {
+ var x = 3;
+ return x;
+ }
+
+ property bool some_bool : false
+ // This comment is related to the property animation
+ PropertyAnimation on x {
+ id: foo; x: 3; y: x + 3
+ }
+
+ // Orphan comment
+
+ // 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; 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"; }();
+
+ default property bool some_default_bool : 500 % 5 !== 0 // some_default_bool
+
+ myFavouriteThings: [
+ // This is an orphan
+
+ // This is a cool text
+ Text {},
+ // This is a cool rectangle
+ Rectangle {}]
+
+ // some_read_only_bool
+ readonly property bool some_read_only_bool : Math.sin(3) && (aFunc()[30] + 5) | 2 != 0
+
+ signal say(string name, bool caps);
+
+ Text { text: "Bla"; signal boo(int count, int times, real duration); required property string batman; }
+
+ Component.onCompleted: console.log("Foo!");
+
+ // This to id
+ // Also id. (line 2)
+ // This is the third id
+ // fourth id comment
+ id: foo
+
+}
diff --git a/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml b/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml
new file mode 100644
index 0000000000..620fbf4120
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml
@@ -0,0 +1,3 @@
+// This comment should be directly above Item after formatting
+Item {
+}
diff --git a/tests/auto/qml/qmlformat/data/FrontInline.qml b/tests/auto/qml/qmlformat/data/FrontInline.qml
new file mode 100644
index 0000000000..c63265481c
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/FrontInline.qml
@@ -0,0 +1,2 @@
+Item { // This comment should be directly above Item after formatting
+}
diff --git a/tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml b/tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml
new file mode 100644
index 0000000000..b8e77ec23a
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml
@@ -0,0 +1,63 @@
+Item {
+
+ function test() {
+ //// The following if blocks should NOT HAVE braces
+ // Single branch, no braces
+ if (true)
+ console.log("foo");
+
+ // Single branch, no braces
+ if (true)
+ console.log("foo");
+
+ // Multiple branches, No braces
+ if (true)
+ console.log("foo");
+ else if (false)
+ console.log("bar");
+ else
+ console.log("baz");
+ // Multiple branches, all braces
+ if (true)
+ console.log("foo");
+ else if (false)
+ console.log("bar");
+ else
+ console.log("baz");
+
+ //// The following if blocks should HAVE braces
+ // Single branch, braces
+ if (true) {
+ console.log("foo");
+ console.log("bar");
+ }
+ // Multiple branches, some braces
+ if (true) {
+ console.log("foo");
+ console.log("foo2");
+ } else if (false) {
+ console.log("bar");
+ } else {
+ console.log("baz");
+ }
+ // Multiple branches, some braces
+ if (true) {
+ console.log("foo");
+ } else if (false) {
+ console.log("bar");
+ console.log("bar2");
+ } else {
+ console.log("baz");
+ }
+ // Multiple branches, some braces
+ if (true) {
+ console.log("foo");
+ } else if (false) {
+ console.log("bar");
+ } else {
+ console.log("baz");
+ console.log("baz2");
+ }
+ }
+
+}
diff --git a/tests/auto/qml/qmlformat/data/IfBlocks.qml b/tests/auto/qml/qmlformat/data/IfBlocks.qml
new file mode 100644
index 0000000000..505988b238
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/IfBlocks.qml
@@ -0,0 +1,66 @@
+Item {
+ function test() {
+ //// The following if blocks should NOT HAVE braces
+ // Single branch, no braces
+ if (true)
+ console.log("foo");
+
+ // Single branch, no braces
+ if (true) {
+ console.log("foo");
+ }
+
+
+ // Multiple branches, No braces
+ if (true)
+ console.log("foo");
+ else if (false)
+ console.log("bar");
+ else
+ console.log("baz");
+
+ // Multiple branches, all braces
+ if (true) {
+ console.log("foo");
+ } else if (false) {
+ console.log("bar");
+ } else {
+ console.log("baz");
+ }
+
+ //// The following if blocks should HAVE braces
+ // Single branch, braces
+ if (true) {
+ console.log("foo");
+ console.log("bar");
+ }
+
+ // Multiple branches, some braces
+ if (true) {
+ console.log("foo");
+ console.log("foo2");
+ } else if (false)
+ console.log("bar");
+ else
+ console.log("baz");
+
+ // Multiple branches, some braces
+ if (true)
+ console.log("foo");
+ else if (false) {
+ console.log("bar");
+ console.log("bar2");
+ } else
+ console.log("baz");
+
+ // Multiple branches, some braces
+ if (true)
+ console.log("foo");
+ else if (false)
+ console.log("bar");
+ else {
+ console.log("baz");
+ console.log("baz2");
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/readOnlyProps.formatted.qml b/tests/auto/qml/qmlformat/data/readOnlyProps.formatted.qml
new file mode 100644
index 0000000000..6e7cc31dcf
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/readOnlyProps.formatted.qml
@@ -0,0 +1,29 @@
+import QtQuick 2.0
+
+QtObject {
+ // Testing UiObjectBinding
+ readonly property Item
+ item: Item {
+ id: test
+
+ signal foo()
+ }
+ // End comment
+
+ // Testing UiArrayBinding
+ readonly property list<Item> array: [
+ Item {
+ id: test1
+
+ signal foo()
+ },
+ Item {
+ id: test2
+
+ signal bar()
+ }
+ ]
+ // Testing UiScriptBinding
+ readonly property int script: Math.sin(Math.PI)
+ property bool normalProperty: true
+}
diff --git a/tests/auto/qml/qmlformat/data/readOnlyProps.qml b/tests/auto/qml/qmlformat/data/readOnlyProps.qml
new file mode 100644
index 0000000000..8a32dd131e
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/readOnlyProps.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.0
+
+QtObject {
+ // Testing UiObjectBinding
+ readonly property Item item: Item { id: test; signal foo() }
+ // End comment
+
+ // Testing UiArrayBinding
+ readonly property list<Item> array: [ Item { id: test1; signal foo() }, Item { id: test2; signal bar() } ]
+
+ // Testing UiScriptBinding
+ readonly property int script: Math.sin(Math.PI)
+
+ property bool normalProperty: true
+}
diff --git a/tests/auto/qml/qmlformat/qmlformat.pro b/tests/auto/qml/qmlformat/qmlformat.pro
new file mode 100644
index 0000000000..a6ae391711
--- /dev/null
+++ b/tests/auto/qml/qmlformat/qmlformat.pro
@@ -0,0 +1,12 @@
+CONFIG += testcase
+TARGET = tst_qmlformat
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_qmlformat.cpp
+DEFINES += SRCDIR=\\\"$$PWD\\\"
+
+include (../../shared/util.pri)
+
+TESTDATA = data/*
+
+QT += testlib
diff --git a/tests/auto/qml/qmlformat/tst_qmlformat.cpp b/tests/auto/qml/qmlformat/tst_qmlformat.cpp
new file mode 100644
index 0000000000..5a8974b907
--- /dev/null
+++ b/tests/auto/qml/qmlformat/tst_qmlformat.cpp
@@ -0,0 +1,300 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QDir>
+#include <QFile>
+#include <QProcess>
+#include <QString>
+#include <QTemporaryDir>
+
+#include <util.h>
+
+class TestQmlformat: public QQmlDataTest
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void initTestCase() override;
+
+ void testFormat();
+ void testFormatNoSort();
+ void testAnnotations();
+ void testAnnotationsNoSort();
+ void testLineEndings();
+ void testFrontInline();
+ void testIfBlocks();
+
+ void testReadOnlyProps();
+
+#if !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled
+ void testExample();
+ void testExample_data();
+#endif
+
+private:
+ QString readTestFile(const QString &path);
+ QString runQmlformat(const QString &fileToFormat, bool sortImports, bool shouldSucceed, const QString &newlineFormat = "native");
+
+ QString m_qmlformatPath;
+ QStringList m_excludedDirs;
+ QStringList m_invalidFiles;
+
+ QStringList findFiles(const QDir &);
+ bool isInvalidFile(const QFileInfo &fileName) const;
+};
+
+void TestQmlformat::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ m_qmlformatPath = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QLatin1String("/qmlformat");
+#ifdef Q_OS_WIN
+ m_qmlformatPath += QLatin1String(".exe");
+#endif
+ if (!QFileInfo(m_qmlformatPath).exists()) {
+ QString message = QStringLiteral("qmlformat executable not found (looked for %0)").arg(m_qmlformatPath);
+ QFAIL(qPrintable(message));
+ }
+
+ // Add directories you want excluded here
+
+ // These snippets are not expected to run on their own.
+ m_excludedDirs << "doc/src/snippets/qml/visualdatamodel_rootindex";
+ m_excludedDirs << "doc/src/snippets/qml/qtbinding";
+ m_excludedDirs << "doc/src/snippets/qml/imports";
+ m_excludedDirs << "doc/src/snippets/qtquick1/visualdatamodel_rootindex";
+ m_excludedDirs << "doc/src/snippets/qtquick1/qtbinding";
+ m_excludedDirs << "doc/src/snippets/qtquick1/imports";
+ m_excludedDirs << "tests/manual/v4";
+ m_excludedDirs << "tests/auto/qml/ecmascripttests";
+ m_excludedDirs << "tests/auto/qml/qmllint";
+
+ // Add invalid files (i.e. files with syntax errors)
+ m_invalidFiles << "tests/auto/quick/qquickloader/data/InvalidSourceComponent.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/signal.2.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/signal.3.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/signal.5.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/property.4.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/empty.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/missingObject.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/insertedSemicolon.1.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/nonexistantProperty.5.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/invalidRoot.1.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/invalidQmlEnumValue.1.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/invalidQmlEnumValue.2.qml";
+ m_invalidFiles << "tests/auto/qml/qquickfolderlistmodel/data/dummy.qml";
+ m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.1.qml";
+ m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.2.qml";
+ m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.3.qml";
+ m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.4.qml";
+ m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.5.qml";
+ m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.6.qml";
+ m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/numberParsing_error.1.qml";
+ m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/numberParsing_error.2.qml";
+ m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon_error1.qml";
+ m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon_error1.qml";
+ m_invalidFiles << "tests/auto/qml/debugger/qqmlpreview/data/broken.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.2.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.3.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/requiredProperties.2.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_And.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_And.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_Or.qml";
+ m_invalidFiles << "tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_And.qml";
+ 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";
+
+ // These files rely on exact formatting
+ 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";
+}
+
+QStringList TestQmlformat::findFiles(const QDir &d)
+{
+ for (int ii = 0; ii < m_excludedDirs.count(); ++ii) {
+ QString s = m_excludedDirs.at(ii);
+ if (d.absolutePath().endsWith(s))
+ return QStringList();
+ }
+
+ QStringList rv;
+
+ QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
+ QDir::Files);
+ foreach (const QString &file, files) {
+ rv << d.absoluteFilePath(file);
+ }
+
+ QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
+ QDir::NoSymLinks);
+ foreach (const QString &dir, dirs) {
+ QDir sub = d;
+ sub.cd(dir);
+ rv << findFiles(sub);
+ }
+
+ return rv;
+}
+
+bool TestQmlformat::isInvalidFile(const QFileInfo &fileName) const
+{
+ for (const QString &invalidFile : m_invalidFiles) {
+ if (fileName.absoluteFilePath().endsWith(invalidFile))
+ return true;
+ }
+ return false;
+}
+
+QString TestQmlformat::readTestFile(const QString &path)
+{
+ QFile file(testFile(path));
+
+ if (!file.open(QIODevice::ReadOnly))
+ return "";
+
+ return QString::fromUtf8(file.readAll());
+}
+
+void TestQmlformat::testFormat()
+{
+ QCOMPARE(runQmlformat(testFile("Example1.qml"), true, true), readTestFile("Example1.formatted.qml"));
+}
+
+void TestQmlformat::testFormatNoSort()
+{
+ QCOMPARE(runQmlformat(testFile("Example1.qml"), false, true), readTestFile("Example1.formatted.nosort.qml"));
+}
+
+void TestQmlformat::testAnnotations()
+{
+ QCOMPARE(runQmlformat(testFile("Annotations.qml"), true, true), readTestFile("Annotations.formatted.qml"));
+}
+
+void TestQmlformat::testAnnotationsNoSort()
+{
+ QCOMPARE(runQmlformat(testFile("Annotations.qml"), false, true), readTestFile("Annotations.formatted.nosort.qml"));
+}
+
+void TestQmlformat::testFrontInline()
+{
+ QCOMPARE(runQmlformat(testFile("FrontInline.qml"), false, true), readTestFile("FrontInline.formatted.qml"));
+}
+
+void TestQmlformat::testIfBlocks()
+{
+ QCOMPARE(runQmlformat(testFile("IfBlocks.qml"), false, true), readTestFile("IfBlocks.formatted.qml"));
+}
+
+void TestQmlformat::testReadOnlyProps()
+{
+ QCOMPARE(runQmlformat(testFile("readOnlyProps.qml"), false, true), readTestFile("readOnlyProps.formatted.qml"));
+}
+
+void TestQmlformat::testLineEndings()
+{
+ // macos
+ const QString macosContents = runQmlformat(testFile("Example1.formatted.qml"), false, true, "macos");
+ QVERIFY(!macosContents.contains("\n"));
+ QVERIFY(macosContents.contains("\r"));
+
+ // windows
+ const QString windowsContents = runQmlformat(testFile("Example1.formatted.qml"), false, true, "windows");
+ QVERIFY(windowsContents.contains("\r\n"));
+
+ // unix
+ const QString unixContents = runQmlformat(testFile("Example1.formatted.qml"), false, true, "unix");
+ QVERIFY(unixContents.contains("\n"));
+ QVERIFY(!unixContents.contains("\r"));
+}
+
+#if !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled
+void TestQmlformat::testExample_data()
+{
+ QTest::addColumn<QString>("file");
+
+ QString examples = QLatin1String(SRCDIR) + "/../../../../examples/";
+ QString tests = QLatin1String(SRCDIR) + "/../../../../tests/";
+
+ QStringList files;
+ files << findFiles(QDir(examples));
+ files << findFiles(QDir(tests));
+
+ for (const QString &file : files)
+ QTest::newRow(qPrintable(file)) << file;
+}
+#endif
+
+#if !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled
+void TestQmlformat::testExample()
+{
+ QFETCH(QString, file);
+ QString output = runQmlformat(file, true, !isInvalidFile(file));
+
+ if (!isInvalidFile(file))
+ QVERIFY(!output.isEmpty());
+}
+#endif
+
+QString TestQmlformat::runQmlformat(const QString &fileToFormat, bool sortImports, bool shouldSucceed, const QString &newlineFormat)
+{
+ // Copy test file to temporary location
+ QTemporaryDir tempDir;
+ const QString tempFile = tempDir.path() + QDir::separator() + "to_format.qml";
+ QFile::copy(fileToFormat, tempFile);
+
+ QStringList args;
+ args << "-i";
+ args << tempFile;
+
+ if (!sortImports)
+ args << "-n";
+
+ args << "-l" << newlineFormat;
+
+ auto verify = [&]() {
+ QProcess process;
+ process.start(m_qmlformatPath, args);
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ if (shouldSucceed)
+ QCOMPARE(process.exitCode(), 0);
+ };
+ verify();
+
+ QFile temp(tempFile);
+
+ temp.open(QIODevice::ReadOnly);
+ QString formatted = QString::fromUtf8(temp.readAll());
+
+ return formatted;
+}
+
+QTEST_MAIN(TestQmlformat)
+#include "tst_qmlformat.moc"
diff --git a/tests/auto/qml/qmllint/data/AttachedProps.qml b/tests/auto/qml/qmllint/data/AttachedProps.qml
new file mode 100644
index 0000000000..01be66f866
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/AttachedProps.qml
@@ -0,0 +1,6 @@
+import QtQml 2.0
+
+QtObject {
+ id: self
+ property var foo: self.Component.completed
+}
diff --git a/tests/auto/qml/qmllint/data/AutomatchedSignalHandler.qml b/tests/auto/qml/qmllint/data/AutomatchedSignalHandler.qml
new file mode 100644
index 0000000000..064444e182
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/AutomatchedSignalHandler.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.12
+
+Item {
+ width: 640
+ height: 480
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: console.log("okok")
+
+ Connections {
+ onClicked: console.log(mouse.x)
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/ButtonLoader.qml b/tests/auto/qml/qmllint/data/ButtonLoader.qml
new file mode 100644
index 0000000000..2721614735
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/ButtonLoader.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.12
+
+Item {
+ Text {
+ id: roundButton
+ Text {
+ font.pixelSize: roundButton.font.pixelSize * 0.5
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/Cycle1.qml b/tests/auto/qml/qmllint/data/Cycle1.qml
new file mode 100644
index 0000000000..8095e9f732
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Cycle1.qml
@@ -0,0 +1,2 @@
+import QtQml 2.0
+Cycle2 {}
diff --git a/tests/auto/qml/qmllint/data/Cycle2.qml b/tests/auto/qml/qmllint/data/Cycle2.qml
new file mode 100644
index 0000000000..90c376fcda
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Cycle2.qml
@@ -0,0 +1,2 @@
+import QtQml 2.0
+Cycle3 {}
diff --git a/tests/auto/qml/qmllint/data/Cycle3.qml b/tests/auto/qml/qmllint/data/Cycle3.qml
new file mode 100644
index 0000000000..f4cba68653
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Cycle3.qml
@@ -0,0 +1,2 @@
+import QtQml 2.0
+Cycle1 {}
diff --git a/tests/auto/qml/qmllint/data/Dialog.qml b/tests/auto/qml/qmllint/data/Dialog.qml
new file mode 100644
index 0000000000..bde8eae18b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Dialog.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.12
+
+Item {
+ id: control
+ property Text header
+ header: Text {
+ font.bold: true
+ padding: 12
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/Drawer.qml b/tests/auto/qml/qmllint/data/Drawer.qml
new file mode 100644
index 0000000000..db1d785c6c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Drawer.qml
@@ -0,0 +1,5 @@
+import QtQml 2.12 as T
+
+T.QtObject {
+ objectName: T.Component.objectName
+}
diff --git a/tests/auto/qml/qmllint/data/Form.ui.qml b/tests/auto/qml/qmllint/data/Form.ui.qml
new file mode 100644
index 0000000000..459c82afbb
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Form.ui.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.0
+
+Item {
+}
diff --git a/tests/auto/qml/qmllint/data/FormUser.qml b/tests/auto/qml/qmllint/data/FormUser.qml
new file mode 100644
index 0000000000..ea3621586f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/FormUser.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+
+Form {
+ x: 12
+ y: 13
+ objectName: "horst"
+}
diff --git a/tests/auto/qml/qmllint/data/ImportWithPrefix.qml b/tests/auto/qml/qmllint/data/ImportWithPrefix.qml
new file mode 100644
index 0000000000..6d070da21a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/ImportWithPrefix.qml
@@ -0,0 +1,5 @@
+import "." as MyStuff
+
+MyStuff.Simple {
+ property bool something: contains(Qt.point(12, 34))
+}
diff --git a/tests/auto/qml/qmllint/data/MethodInItem.qml b/tests/auto/qml/qmllint/data/MethodInItem.qml
new file mode 100644
index 0000000000..dbdaf8bcc1
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MethodInItem.qml
@@ -0,0 +1,5 @@
+import QtQml 2.0
+
+QtObject {
+ function doThings() { console.log("things") }
+}
diff --git a/tests/auto/qml/qmllint/data/MethodInScope.qml b/tests/auto/qml/qmllint/data/MethodInScope.qml
new file mode 100644
index 0000000000..7ba0829f61
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MethodInScope.qml
@@ -0,0 +1,5 @@
+import QtQml 2.0
+
+MethodInItem {
+ Component.onCompleted: doThings()
+}
diff --git a/tests/auto/qml/qmllint/data/Methods.js b/tests/auto/qml/qmllint/data/Methods.js
new file mode 100644
index 0000000000..52ab857e38
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Methods.js
@@ -0,0 +1,3 @@
+function foo() {
+ return "ttt"
+}
diff --git a/tests/auto/qml/qmllint/data/Text.qml b/tests/auto/qml/qmllint/data/Text.qml
new file mode 100644
index 0000000000..130578d1e3
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Text.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.12 as T
+
+T.Text {
+ id: control
+ text: "'ello"
+}
diff --git a/tests/auto/qml/qmllint/data/Things/SomethingElse.qml b/tests/auto/qml/qmllint/data/Things/SomethingElse.qml
new file mode 100644
index 0000000000..0e69012662
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Things/SomethingElse.qml
@@ -0,0 +1,2 @@
+import QtQml 2.0
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/Things/plugins.qmltypes b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes
new file mode 100644
index 0000000000..9d81c21070
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes
@@ -0,0 +1,17 @@
+import QtQuick.tooling 1.2
+Module {
+ dependencies: []
+ Component {
+ name: "SomethingEntirelyStrange"
+ prototype: "QObject"
+ Enum {
+ name: "AnEnum"
+ values: {
+ "AAA": 0,
+ "BBB": 1,
+ "CCC": 2
+ }
+ }
+ Property { name: "palette"; type: "QPalette" }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/Things/qmldir b/tests/auto/qml/qmllint/data/Things/qmldir
new file mode 100644
index 0000000000..c53af3a340
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Things/qmldir
@@ -0,0 +1,3 @@
+module Things
+Something 1.0 SomethingElse.qml
+plugin doesNotExistPlugin
diff --git a/tests/auto/qml/qmllint/data/badAlias.qml b/tests/auto/qml/qmllint/data/badAlias.qml
new file mode 100644
index 0000000000..2dd7d1a7e0
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badAlias.qml
@@ -0,0 +1,5 @@
+import QtQml 2.0
+
+QtObject {
+ property alias wrong: nowhere
+}
diff --git a/tests/auto/qml/qmllint/data/badAliasProperty.qml b/tests/auto/qml/qmllint/data/badAliasProperty.qml
new file mode 100644
index 0000000000..9483c52cd0
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badAliasProperty.qml
@@ -0,0 +1,6 @@
+import QtQml 2.0
+
+QtObject {
+ id: self
+ property alias wrong: self.nowhere
+}
diff --git a/tests/auto/qml/qmllint/data/badParent.qml b/tests/auto/qml/qmllint/data/badParent.qml
new file mode 100644
index 0000000000..f381f059cc
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badParent.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+
+Item {
+ Item {
+ property int yyy: parent.rrr
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/badTypeAssertion.qml b/tests/auto/qml/qmllint/data/badTypeAssertion.qml
new file mode 100644
index 0000000000..717fc1b1bb
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badTypeAssertion.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.0
+
+Item {
+ property QtObject foo: Item { x: 4 }
+ property real foox: (foo as Item).rrr
+}
diff --git a/tests/auto/qml/qmllint/data/esmodule.mjs b/tests/auto/qml/qmllint/data/esmodule.mjs
new file mode 100644
index 0000000000..50a53be2b1
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/esmodule.mjs
@@ -0,0 +1,2 @@
+
+export function test() { console.log("hello world"); }
diff --git a/tests/auto/qml/qmllint/data/forLoop.qml b/tests/auto/qml/qmllint/data/forLoop.qml
new file mode 100644
index 0000000000..be8b12409b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/forLoop.qml
@@ -0,0 +1,9 @@
+import QtQml 2.0
+
+QtObject {
+ Component.onCompleted: {
+ var stuff = [1, 2, 3, 4]
+ for (var a in stuff)
+ console.log(a);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/goodAlias.qml b/tests/auto/qml/qmllint/data/goodAlias.qml
new file mode 100644
index 0000000000..d2fa4485ec
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/goodAlias.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.0
+
+Item {
+ id: self
+
+ QtObject {
+ id: inner
+ }
+
+ property alias innerObj: inner
+ property alias name: self.objectName
+}
diff --git a/tests/auto/qml/qmllint/data/goodParent.qml b/tests/auto/qml/qmllint/data/goodParent.qml
new file mode 100644
index 0000000000..413337713a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/goodParent.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+Item {
+ property int rrr: 5
+ Item {
+ property int yyy: parent.rrr
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/goodTypeAssertion.qml b/tests/auto/qml/qmllint/data/goodTypeAssertion.qml
new file mode 100644
index 0000000000..6f5f52eb6b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/goodTypeAssertion.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.0
+
+Item {
+ property QtObject foo: Item { x: 4 }
+ property real foox: (foo as Item).x
+}
diff --git a/tests/auto/qml/qmllint/data/incompleteQmltypes.qml b/tests/auto/qml/qmllint/data/incompleteQmltypes.qml
new file mode 100644
index 0000000000..ab06bbd8b0
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/incompleteQmltypes.qml
@@ -0,0 +1,6 @@
+import Things 1.0
+
+SomethingEntirelyStrange {
+ id: self
+ property var a: self.palette.weDontKnowIt
+}
diff --git a/tests/auto/qml/qmllint/data/javascriptMethods.qml b/tests/auto/qml/qmllint/data/javascriptMethods.qml
new file mode 100644
index 0000000000..62ddcfda60
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/javascriptMethods.qml
@@ -0,0 +1,6 @@
+import QtQml 2.0
+import "Methods.js" as Methods
+
+QtObject {
+ objectName: Methods.foo()
+}
diff --git a/tests/auto/qml/qmllint/data/memberNotFound.qml b/tests/auto/qml/qmllint/data/memberNotFound.qml
new file mode 100644
index 0000000000..da2e353227
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/memberNotFound.qml
@@ -0,0 +1,7 @@
+import QtQml 2.0
+
+QtObject {
+ id: self
+ property string n: self.objectName
+ property string not: self.foo
+}
diff --git a/tests/auto/qml/qmllint/data/parentIsComponent.qml b/tests/auto/qml/qmllint/data/parentIsComponent.qml
new file mode 100644
index 0000000000..a74bf9e4e8
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/parentIsComponent.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.0
+
+Item {
+ Component {
+ id: foo
+ Item {
+ property real yyy: parent.progress
+ Component.onCompleted: console.log(yyy)
+ }
+ }
+
+ property var stuff: foo.createObject()
+}
diff --git a/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml b/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml
new file mode 100644
index 0000000000..4847fc9196
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml
@@ -0,0 +1,6 @@
+import Things 1.0
+
+Something {
+ property var a: SomethingEntirelyStrange {}
+ property var b: SomethingEntirelyStrange.AAA
+}
diff --git a/tests/auto/qml/qmllint/data/spuriousParentWarning.qml b/tests/auto/qml/qmllint/data/unknownElement.qml
index 1323593031..1323593031 100644
--- a/tests/auto/qml/qmllint/data/spuriousParentWarning.qml
+++ b/tests/auto/qml/qmllint/data/unknownElement.qml
diff --git a/tests/auto/qml/qmllint/data/unknownJavascriptMethod.qml b/tests/auto/qml/qmllint/data/unknownJavascriptMethod.qml
new file mode 100644
index 0000000000..2718e07c60
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/unknownJavascriptMethod.qml
@@ -0,0 +1,6 @@
+import QtQml 2.0
+import "Methods.js" as Methods
+
+QtObject {
+ objectName: Methods.foo2()
+}
diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp
index 582f146dca..8697495a6f 100644
--- a/tests/auto/qml/qmllint/tst_qmllint.cpp
+++ b/tests/auto/qml/qmllint/tst_qmllint.cpp
@@ -38,13 +38,21 @@ class TestQmllint: public QQmlDataTest
private Q_SLOTS:
void initTestCase() override;
- void test();
- void test_data();
+
void testUnqualified();
void testUnqualified_data();
- void testUnqualifiedNoSpuriousParentWarning();
- void catchIdentifierNoFalsePositive();
+
+ void cleanQmlCode_data();
+ void cleanQmlCode();
+
+ void dirtyQmlCode_data();
+ void dirtyQmlCode();
+
+ void testUnknownCausesFail();
+
private:
+ QString runQmllint(const QString &fileToLint, bool shouldSucceed);
+
QString m_qmllintPath;
};
@@ -61,37 +69,14 @@ void TestQmllint::initTestCase()
}
}
-void TestQmllint::test_data()
-{
- QTest::addColumn<QString>("filename");
- QTest::addColumn<bool>("isValid");
-
- // Valid files:
- QTest::newRow("Simple_QML") << QStringLiteral("Simple.qml") << true;
- QTest::newRow("QML_importing_JS") << QStringLiteral("importing_js.qml") << true;
- QTest::newRow("QTBUG-45916_JS_with_pragma_and_import") << QStringLiteral("QTBUG-45916.js") << true;
-
- // Invalid files:
- QTest::newRow("Invalid_syntax_QML") << QStringLiteral("failure1.qml") << false;
- QTest::newRow("Invalid_syntax_JS") << QStringLiteral("failure1.js") << false;
-}
-
void TestQmllint::testUnqualified()
{
- auto qmlImportDir = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);
QFETCH(QString, filename);
QFETCH(QString, warningMessage);
QFETCH(int, warningLine);
QFETCH(int, warningColumn);
- QStringList args;
- args << QStringLiteral("-U") << testFile(filename) << QStringLiteral("-I") << qmlImportDir;
-
- QProcess process;
- process.start(m_qmllintPath, args);
- QVERIFY(process.waitForFinished());
- QVERIFY(process.exitStatus() == QProcess::NormalExit);
- QVERIFY(process.exitCode());
- QString output = process.readAllStandardError();
+
+ const QString output = runQmllint(filename, false);
QVERIFY(output.contains(QString::asprintf("Warning: unqualified access at %d:%d", warningLine, warningColumn)));
QVERIFY(output.contains(warningMessage));
}
@@ -118,56 +103,142 @@ void TestQmllint::testUnqualified_data()
QTest::newRow("SignalHandlerShort2") << QStringLiteral("SignalHandler.qml") << QStringLiteral("onPressAndHold: (mouse) => {...") << 12 << 34;
// access catch identifier outside catch block
QTest::newRow("CatchStatement") << QStringLiteral("CatchStatement.qml") << QStringLiteral("err") << 6 << 21;
+
+ QTest::newRow("NonSpuriousParent") << QStringLiteral("nonSpuriousParentWarning.qml") << QStringLiteral("property int x: <id>.parent.x") << 6 << 25;
}
-void TestQmllint::testUnqualifiedNoSpuriousParentWarning()
+void TestQmllint::testUnknownCausesFail()
{
- auto qmlImportDir = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);
- {
- QString filename = testFile("spuriousParentWarning.qml");
- QStringList args;
- args << QStringLiteral("-U") << filename << QStringLiteral("-I") << qmlImportDir;
- QProcess process;
- process.start(m_qmllintPath, args);
- QVERIFY(process.waitForFinished());
- QVERIFY(process.exitStatus() == QProcess::NormalExit);
- QVERIFY(process.exitCode() == 0);
- }
- {
- QString filename = testFile("nonSpuriousParentWarning.qml");
- QStringList args;
- args << QStringLiteral("-U") << filename << QStringLiteral("-I") << qmlImportDir;
- QProcess process;
- process.start(m_qmllintPath, args);
- QVERIFY(process.waitForFinished());
- QVERIFY(process.exitStatus() == QProcess::NormalExit);
- QVERIFY(process.exitCode());
- }
+ const QString unknownNotFound = runQmllint("unknownElement.qml", false);
+ QVERIFY(unknownNotFound.contains(
+ QStringLiteral("warning: Unknown was not found. Did you add all import paths?")));
}
-void TestQmllint::catchIdentifierNoFalsePositive()
+void TestQmllint::dirtyQmlCode_data()
{
- auto qmlImportDir = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);
- QString filename = QLatin1String("catchIdentifierNoWarning.qml");
- filename.prepend(QStringLiteral("data/"));
- QStringList args;
- args << QStringLiteral("-U") << filename << QStringLiteral("-I") << qmlImportDir;
- QProcess process;
- process.start(m_qmllintPath, args);
- QVERIFY(process.waitForFinished());
- QVERIFY(process.exitStatus() == QProcess::NormalExit);
- QVERIFY(process.exitCode() == 0);
+ QTest::addColumn<QString>("filename");
+ QTest::addColumn<QString>("warningMessage");
+ QTest::addColumn<QString>("notContained");
+
+ QTest::newRow("Invalid_syntax_QML")
+ << QStringLiteral("failure1.qml")
+ << QStringLiteral("failure1.qml:4 : Expected token `:'")
+ << QString();
+ QTest::newRow("Invalid_syntax_JS")
+ << QStringLiteral("failure1.js")
+ << QStringLiteral("failure1.js:4 : Expected token `;'")
+ << QString();
+ QTest::newRow("AutomatchedSignalHandler")
+ << QStringLiteral("AutomatchedSignalHandler.qml")
+ << QString("Warning: unqualified access at 12:36")
+ << QStringLiteral("no matching signal found");
+ QTest::newRow("MemberNotFound")
+ << QStringLiteral("memberNotFound.qml")
+ << QString("Warning: Property \"foo\" not found on type \"QtObject\" at 6:31")
+ << QString();
+ QTest::newRow("UnknownJavascriptMethd")
+ << QStringLiteral("unknownJavascriptMethod.qml")
+ << QString("Warning: Property \"foo2\" not found on type \"Methods\" at 5:25")
+ << QString();
+ QTest::newRow("badAlias")
+ << QStringLiteral("badAlias.qml")
+ << QString("Warning: unqualified access at 4:27")
+ << QString();
+ QTest::newRow("badAliasProperty")
+ << QStringLiteral("badAliasProperty.qml")
+ << QString("Warning: Property \"nowhere\" not found on type \"QtObject\" at 5:32")
+ << QString();
+ QTest::newRow("badParent")
+ << QStringLiteral("badParent.qml")
+ << QString("Warning: Property \"rrr\" not found on type \"Item\" at 5:34")
+ << QString();
+ QTest::newRow("parentIsComponent")
+ << QStringLiteral("parentIsComponent.qml")
+ << QString("Warning: Property \"progress\" not found on type \"QQuickItem\" at 7:39")
+ << QString();
+ QTest::newRow("badTypeAssertion")
+ << QStringLiteral("badTypeAssertion.qml")
+ << QString("Warning: Property \"rrr\" not found on type \"Item\" at 5:39")
+ << QString();
+ QTest::newRow("incompleteQmltypes")
+ << QStringLiteral("incompleteQmltypes.qml")
+ << QString("Warning: Type \"QPalette\" of member \"palette\" not found at 5:26")
+ << QString();
+ QTest::newRow("inheritanceCylce")
+ << QStringLiteral("Cycle1.qml")
+ << QString("Warning: Cycle2 is part of an inheritance cycle: Cycle2 -> Cycle3 -> Cycle1 -> Cycle2")
+ << QString();
}
-void TestQmllint::test()
+void TestQmllint::dirtyQmlCode()
{
QFETCH(QString, filename);
- QFETCH(bool, isValid);
- QStringList args;
- args << QStringLiteral("--silent") << testFile(filename);
+ QFETCH(QString, warningMessage);
+ QFETCH(QString, notContained);
+
+ const QString output = runQmllint(filename, false);
+ QVERIFY(output.contains(warningMessage));
+ if (!notContained.isEmpty())
+ QVERIFY(!output.contains(notContained));
+}
+
+void TestQmllint::cleanQmlCode_data()
+{
+ QTest::addColumn<QString>("filename");
+ QTest::newRow("Simple_QML") << QStringLiteral("Simple.qml");
+ QTest::newRow("QML_importing_JS") << QStringLiteral("importing_js.qml");
+ QTest::newRow("JS_with_pragma_and_import") << QStringLiteral("QTBUG-45916.js");
+ QTest::newRow("uiQml") << QStringLiteral("FormUser.qml");
+ QTest::newRow("methodInScope") << QStringLiteral("MethodInScope.qml");
+ QTest::newRow("importWithPrefix") << QStringLiteral("ImportWithPrefix.qml");
+ QTest::newRow("catchIdentifier") << QStringLiteral("catchIdentifierNoWarning.qml");
+ QTest::newRow("qmldirAndQmltypes") << QStringLiteral("qmldirAndQmltypes.qml");
+ QTest::newRow("forLoop") << QStringLiteral("forLoop.qml");
+ QTest::newRow("esmodule") << QStringLiteral("esmodule.mjs");
+ QTest::newRow("methodsInJavascript") << QStringLiteral("javascriptMethods.qml");
+ QTest::newRow("goodAlias") << QStringLiteral("goodAlias.qml");
+ QTest::newRow("goodParent") << QStringLiteral("goodParent.qml");
+ QTest::newRow("goodTypeAssertion") << QStringLiteral("goodTypeAssertion.qml");
+ QTest::newRow("AttachedProps") << QStringLiteral("AttachedProps.qml");
+ QTest::newRow("unknownBuiltinFont") << QStringLiteral("ButtonLoader.qml");
+ QTest::newRow("confusingImport") << QStringLiteral("Dialog.qml");
+ QTest::newRow("qualifiedAttached") << QStringLiteral("Drawer.qml");
+}
+
+void TestQmllint::cleanQmlCode()
+{
+ QFETCH(QString, filename);
+ const QString warnings = runQmllint(filename, true);
+ QVERIFY(warnings.isEmpty());
+}
- bool success = QProcess::execute(m_qmllintPath, args) == 0;
- QCOMPARE(success, isValid);
+QString TestQmllint::runQmllint(const QString &fileToLint, bool shouldSucceed)
+{
+ auto qmlImportDir = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);
+ QStringList args;
+ args << QStringLiteral("-U") << testFile(fileToLint)
+ << QStringLiteral("-I") << qmlImportDir
+ << QStringLiteral("-I") << dataDirectory()
+ << QStringLiteral("--silent");
+ QString errors;
+ auto verify = [&](bool isSilent) {
+ QProcess process;
+ process.start(m_qmllintPath, args);
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ if (shouldSucceed)
+ QCOMPARE(process.exitCode(), 0);
+ else
+ QVERIFY(process.exitCode() != 0);
+ errors = process.readAllStandardError();
+
+ if (isSilent)
+ QVERIFY(errors.isEmpty());
+ };
+ verify(true);
+ args.removeLast();
+ verify(false);
+ return errors;
}
QTEST_MAIN(TestQmllint)
diff --git a/tests/auto/qml/qmlmin/tst_qmlmin.cpp b/tests/auto/qml/qmlmin/tst_qmlmin.cpp
index e244369581..0501a8112a 100644
--- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp
+++ b/tests/auto/qml/qmlmin/tst_qmlmin.cpp
@@ -131,6 +131,7 @@ void tst_qmlmin::initTestCase()
invalidFiles << "tests/auto/qml/debugger/qqmlpreview/data/broken.qml";
invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.2.qml";
invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.3.qml";
+ invalidFiles << "tests/auto/qml/qqmllanguage/data/requiredProperties.2.qml";
// generatorFunction.qml is not invalid per se, but the minifier cannot handle yield statements
invalidFiles << "tests/auto/qml/qqmlecmascript/data/generatorFunction.qml";
#endif
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp b/tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp
new file mode 100644
index 0000000000..db080a5cad
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foreign.h"
+
+int Foreign::things() const
+{
+ return m_things;
+}
+
+void Foreign::setThings(int things)
+{
+ if (m_things == things)
+ return;
+
+ m_things = things;
+ emit thingsChanged(m_things);
+}
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/foreign.h b/tests/auto/qml/qmltyperegistrar/foreign/foreign.h
new file mode 100644
index 0000000000..dc9fbc84a8
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/foreign/foreign.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FOREIGN_H
+#define FOREIGN_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qsize.h>
+
+class Foreign : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int things READ things WRITE setThings NOTIFY thingsChanged)
+
+public:
+ int things() const;
+
+public slots:
+ void setThings(int things);
+
+signals:
+ void thingsChanged(int things);
+
+private:
+ int m_things = 0;
+};
+
+class SizeGadget : public QSize
+{
+ Q_GADGET
+ Q_PROPERTY(int height READ height WRITE setHeight FINAL)
+};
+
+#endif // FOREIGN_H
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/foreign.pro b/tests/auto/qml/qmltyperegistrar/foreign/foreign.pro
new file mode 100644
index 0000000000..87521eac43
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/foreign/foreign.pro
@@ -0,0 +1,10 @@
+TEMPLATE = lib
+QT = core
+
+macos:CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+
+SOURCES = foreign.cpp
+HEADERS = foreign.h
+
+CONFIG += metatypes static
diff --git a/tests/auto/qml/qmltyperegistrar/hppheader.hpp b/tests/auto/qml/qmltyperegistrar/hppheader.hpp
new file mode 100644
index 0000000000..f5fc881b77
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/hppheader.hpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef HPPHEADER_HPP
+#define HPPHEADER_HPP
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+class HppClass : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(int eieiei READ eieiei WRITE setEieiei NOTIFY eieieiChanged)
+
+public:
+ int eieiei() const
+ {
+ return m_eieiei;
+ }
+
+public slots:
+ void setEieiei(int eieiei)
+ {
+ if (m_eieiei == eieiei)
+ return;
+
+ m_eieiei = eieiei;
+ emit eieieiChanged(m_eieiei);
+ }
+
+signals:
+ void eieieiChanged(int eieiei);
+
+private:
+ int m_eieiei;
+};
+
+#endif // HPPHEADER_HPP
diff --git a/tests/auto/qml/qmltyperegistrar/noextheader b/tests/auto/qml/qmltyperegistrar/noextheader
new file mode 100644
index 0000000000..3b6cb6d72c
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/noextheader
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef NOEXTHEADER
+#define NOEXTHEADER
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+class Noext : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(int gagaga READ gagaga WRITE setGagaga NOTIFY gagagaChanged)
+
+public:
+ int gagaga() const
+ {
+ return m_gagaga;
+ }
+
+public slots:
+ void setGagaga(int gagaga)
+ {
+ if (m_gagaga == gagaga)
+ return;
+
+ m_gagaga = gagaga;
+ emit gagagaChanged(m_gagaga);
+ }
+
+signals:
+ void gagagaChanged(int gagaga);
+
+private:
+ int m_gagaga;
+};
+
+#endif // NOEXTHEADER
diff --git a/tests/auto/qml/qmltyperegistrar/qmltyperegistrar.pro b/tests/auto/qml/qmltyperegistrar/qmltyperegistrar.pro
new file mode 100644
index 0000000000..738d099123
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/qmltyperegistrar.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+SUBDIRS = foreign tst_qmltyperegistrar.pro
+
+tst_qmltyperegistrar_pro.depends = foreign
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
new file mode 100644
index 0000000000..1cfcd689c6
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tst_qmltyperegistrar.h"
+#include <QtTest/qtest.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qfile.h>
+
+void tst_qmltyperegistrar::initTestCase()
+{
+ QFile file(QCoreApplication::applicationDirPath() + "/tst_qmltyperegistrar.qmltypes");
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ qmltypesData = file.readAll();
+ QVERIFY(file.atEnd());
+ QCOMPARE(file.error(), QFile::NoError);
+}
+
+void tst_qmltyperegistrar::qmltypesHasForeign()
+{
+ QVERIFY(qmltypesData.contains("things"));
+}
+
+void tst_qmltyperegistrar::qmltypesHasHppClassAndNoext()
+{
+ QVERIFY(qmltypesData.contains("HppClass"));
+ QVERIFY(qmltypesData.contains("Noext"));
+}
+
+void tst_qmltyperegistrar::qmltypesHasFileNames()
+{
+ QVERIFY(qmltypesData.contains("file: \"hppheader.hpp\""));
+ QVERIFY(qmltypesData.contains("file: \"noextheader\""));
+ QVERIFY(qmltypesData.contains("file: \"tst_qmltyperegistrar.h\""));
+}
+
+void tst_qmltyperegistrar::qmltypesHasFlags()
+{
+ QVERIFY(qmltypesData.contains("name: \"Flags\""));
+ QVERIFY(qmltypesData.contains("alias: \"Flag\""));
+ QVERIFY(qmltypesData.contains("isFlag: true"));
+}
+
+void tst_qmltyperegistrar::superAndForeignTypes()
+{
+ QVERIFY(qmltypesData.contains("values: [\"Pixel\", \"Centimeter\", \"Inch\", \"Point\"]"));
+ QVERIFY(qmltypesData.contains("name: \"SizeGadget\""));
+ QVERIFY(qmltypesData.contains("prototype: \"SizeEnums\""));
+ QVERIFY(qmltypesData.contains("Property { name: \"height\"; type: \"int\" }"));
+ QVERIFY(qmltypesData.contains("Property { name: \"width\"; type: \"int\" }"));
+ QVERIFY(qmltypesData.contains("Method { name: \"sizeToString\"; type: \"string\" }"));
+}
+
+QTEST_MAIN(tst_qmltyperegistrar)
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
new file mode 100644
index 0000000000..09485ab0b6
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TST_QMLTYPEREGISTRAR_H
+#define TST_QMLTYPEREGISTRAR_H
+
+#include "foreign.h"
+
+#include <QtQml/qqml.h>
+
+class SizeEnums
+{
+ Q_GADGET
+ QML_NAMED_ELEMENT(SizeEnums)
+ QML_UNCREATABLE("Element is not creatable.")
+
+public:
+ enum Unit { Pixel, Centimeter, Inch, Point };
+ Q_ENUM(Unit)
+};
+
+class SizeValueType : public SizeEnums
+{
+ QSize v;
+ Q_GADGET
+ Q_PROPERTY(int width READ width WRITE setWidth FINAL)
+ QML_NAMED_ELEMENT(MySize)
+ QML_FOREIGN(SizeGadget)
+
+public:
+ Q_INVOKABLE QString sizeToString() const
+ {
+ return QString::fromLatin1("%1x%2").arg(v.width()).arg(v.height());
+ }
+
+ int width() const { return v.width(); }
+ void setWidth(int width) { v.setWidth(width); }
+};
+
+class Local : public Foreign
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ enum Flag {
+ Flag1 = 0x1,
+ Flag2 = 0x2,
+ Flag3 = 0x4,
+ Flag4 = 0x8
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+ Q_FLAG(Flags)
+};
+
+class tst_qmltyperegistrar : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void qmltypesHasForeign();
+ void qmltypesHasHppClassAndNoext();
+ void qmltypesHasFileNames();
+ void qmltypesHasFlags();
+ void superAndForeignTypes();
+
+private:
+ QByteArray qmltypesData;
+};
+
+#endif // TST_QMLTYPEREGISTRAR_H
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.pro b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.pro
new file mode 100644
index 0000000000..fe21b122c2
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.pro
@@ -0,0 +1,20 @@
+TEMPLATE = app
+
+QT = core qml testlib
+CONFIG += testcase qmltypes
+CONFIG -= debug_and_release_target
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_qmltyperegistrar.cpp
+HEADERS += \
+ hppheader.hpp \
+ noextheader \
+ tst_qmltyperegistrar.h
+
+QMLTYPES_FILENAME = tst_qmltyperegistrar.qmltypes
+QML_FOREIGN_METATYPES += foreign/foreign_metatypes.json
+QML_IMPORT_NAME = QmlTypeRegistrarTest
+QML_IMPORT_VERSION = 1.0
+
+INCLUDEPATH += foreign
+LIBS += -Lforeign -lforeign
diff --git a/tests/auto/qml/qqmlapplicationengine/data/i18n/qml_de_CH.qm b/tests/auto/qml/qqmlapplicationengine/data/i18n/qml_de_CH.qm
new file mode 100644
index 0000000000..926d74f905
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/data/i18n/qml_de_CH.qm
Binary files differ
diff --git a/tests/auto/qml/qqmlapplicationengine/data/i18n/qml_de_CH.ts b/tests/auto/qml/qqmlapplicationengine/data/i18n/qml_de_CH.ts
new file mode 100644
index 0000000000..2105cfb2cf
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/data/i18n/qml_de_CH.ts
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="de_CH" sourcelanguage="en">
+<context>
+ <name>loadTranslation</name>
+ <message>
+ <source>translate it</source>
+ <translation>Grüezi</translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
index 2bee283826..f636e527c3 100644
--- a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
+++ b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
@@ -53,6 +53,7 @@ private slots:
void removeObjectsWhenDestroyed();
void loadTranslation_data();
void loadTranslation();
+ void translationChange();
void setInitialProperties();
void failureToLoadTriggersWarningSignal();
@@ -278,6 +279,28 @@ void tst_qqmlapplicationengine::loadTranslation()
QCOMPARE(rootObject->property("translation").toString(), translation);
}
+void tst_qqmlapplicationengine::translationChange()
+{
+ if (QLocale().language() == QLocale::SwissGerman) {
+ QSKIP("Skipping this when running under the Swiss locale as we would always load translation.");
+ }
+
+ QQmlApplicationEngine engine(testFileUrl("loadTranslation.qml"));
+
+ QCOMPARE(engine.uiLanguage(), QLocale().bcp47Name());
+
+ QObject *rootObject = engine.rootObjects().first();
+ QVERIFY(rootObject);
+
+ QCOMPARE(rootObject->property("translation").toString(), "translated");
+
+ engine.setUiLanguage("de_CH");
+ QCOMPARE(rootObject->property("translation").toString(), QString::fromUtf8("Gr\u00FCezi"));
+
+ engine.setUiLanguage(QString());
+ QCOMPARE(rootObject->property("translation").toString(), "translate it");
+}
+
void tst_qqmlapplicationengine::setInitialProperties()
{
QQmlApplicationEngine test {};
diff --git a/tests/auto/qml/qqmlcomponent/data/AliasToSubcomponentRequiredBase.qml b/tests/auto/qml/qqmlcomponent/data/AliasToSubcomponentRequiredBase.qml
new file mode 100644
index 0000000000..f693cb4c2e
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/AliasToSubcomponentRequiredBase.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.13
+
+Item {
+ property alias i_alias: sub.i
+
+ Item {
+ id: sub
+ required property int i
+ }
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/BaseWithRequired.qml b/tests/auto/qml/qqmlcomponent/data/BaseWithRequired.qml
new file mode 100644
index 0000000000..0ce61c8d9d
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/BaseWithRequired.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.14
+
+Item {
+ id: base
+ required property int i
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/RequiredDefault.qml b/tests/auto/qml/qqmlcomponent/data/RequiredDefault.qml
new file mode 100644
index 0000000000..7e8f225a52
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/RequiredDefault.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Item {
+ required default property Text requiredDefault
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/aliasToSubcomponentNotSet.qml b/tests/auto/qml/qqmlcomponent/data/aliasToSubcomponentNotSet.qml
new file mode 100644
index 0000000000..527eb417e5
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/aliasToSubcomponentNotSet.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.13
+
+AliasToSubcomponentRequiredBase {
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/createdFromQml.qml b/tests/auto/qml/qqmlcomponent/data/createdFromQml.qml
new file mode 100644
index 0000000000..60a2077606
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/createdFromQml.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.14
+
+Item {
+ id: root
+ property Item it
+ Component.onCompleted: function() {
+ let component = Qt.createComponent("requiredNotSet.qml", Component.PreferSynchronous, root)
+ console.assert(component.status == Component.Ready)
+ it = component.createObject(component, {i: 42})
+ }
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/createdFromQmlFail.qml b/tests/auto/qml/qqmlcomponent/data/createdFromQmlFail.qml
new file mode 100644
index 0000000000..e09ddcccc1
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/createdFromQmlFail.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.14
+
+Item {
+ id: root
+ property Item it
+ Component.onCompleted: function() {
+ let component = Qt.createComponent("requiredNotSet.qml", Component.PreferSynchronous, root)
+ console.assert(component.status == Component.Ready)
+ root.it = component.createObject(component)
+ }
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.1.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.1.qml
new file mode 100644
index 0000000000..68dff22f33
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.1.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+RequiredDefault {
+ Text {text: "Hello, world!"}
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.2.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.2.qml
new file mode 100644
index 0000000000..a6c4e8ea3f
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.2.qml
@@ -0,0 +1,3 @@
+import QtQuick 2.15
+
+RequiredDefault { }
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.3.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.3.qml
new file mode 100644
index 0000000000..19b3271858
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.3.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.15
+import qt.test 1.0
+
+RequiredDefaultCpp {
+ Text {text: "Hello, world!"}
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.4.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.4.qml
new file mode 100644
index 0000000000..acd56db328
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.4.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.15
+import qt.test 1.0
+
+RequiredDefaultCpp { }
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredNotSet.qml b/tests/auto/qml/qqmlcomponent/data/requiredNotSet.qml
new file mode 100644
index 0000000000..c0b5d695f1
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredNotSet.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.14
+
+Item {
+ required property int i
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetInSameFile.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetInSameFile.qml
new file mode 100644
index 0000000000..76dfcd87e5
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredSetInSameFile.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.14
+
+Item {
+ required property int i
+ i: 42
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetLater.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetLater.qml
new file mode 100644
index 0000000000..3b7811e453
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredSetLater.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.14
+
+BaseWithRequired {
+ i: 13
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasAfterSameFile.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasAfterSameFile.qml
new file mode 100644
index 0000000000..163616bc8a
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasAfterSameFile.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.14
+
+Item {
+ id: withAlias
+ j: 42
+ required property int i
+ property alias j: withAlias.i
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasBeforeSameFile.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasBeforeSameFile.qml
new file mode 100644
index 0000000000..e59bccf379
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasBeforeSameFile.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.14
+
+Item {
+ id: withAlias
+ required property int i
+ j: 42
+ property alias j: withAlias.i
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasParentFile.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasParentFile.qml
new file mode 100644
index 0000000000..0bc2f8a7df
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasParentFile.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.14
+
+BaseWithRequired {
+ id: withAlias
+ property alias j: withAlias.i
+ j: 42
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetViaChainedAlias.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetViaChainedAlias.qml
new file mode 100644
index 0000000000..45cf02d3d8
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredSetViaChainedAlias.qml
@@ -0,0 +1,9 @@
+import QtQml 2.12
+
+QtObject {
+ id: stuff
+ required property int x;
+ property alias y: stuff.x
+ property alias z: stuff.y
+ z: 5
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/setViaAliasToSubcomponent.qml b/tests/auto/qml/qqmlcomponent/data/setViaAliasToSubcomponent.qml
new file mode 100644
index 0000000000..2dc182ea82
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/setViaAliasToSubcomponent.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.13
+
+AliasToSubcomponentRequiredBase {
+ i_alias: 42
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/shadowing.qml b/tests/auto/qml/qqmlcomponent/data/shadowing.qml
new file mode 100644
index 0000000000..4d119d8884
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/shadowing.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.14
+
+BaseWithRequired {
+ property int i: 13
+}
diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
index 1d2fa42b75..43cbd93396 100644
--- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
+++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
@@ -121,6 +121,9 @@ private slots:
void relativeUrl_data();
void relativeUrl();
void setDataNoEngineNoSegfault();
+ void testRequiredProperties_data();
+ void testRequiredProperties();
+ void testRequiredPropertiesFromQml();
void testSetInitialProperties();
private:
@@ -668,35 +671,96 @@ void tst_qqmlcomponent::setDataNoEngineNoSegfault()
QVERIFY(!c);
}
-void tst_qqmlcomponent::testSetInitialProperties()
+class RequiredDefaultCpp : public QObject
+{
+ Q_OBJECT
+public:
+ Q_PROPERTY(QQuickItem *defaultProperty MEMBER m_defaultProperty NOTIFY defaultPropertyChanged REQUIRED)
+ Q_SIGNAL void defaultPropertyChanged();
+ Q_CLASSINFO("DefaultProperty", "defaultProperty")
+private:
+ QQuickItem *m_defaultProperty = nullptr;
+};
+
+void tst_qqmlcomponent::testRequiredProperties_data()
+{
+ qmlRegisterType<RequiredDefaultCpp>("qt.test", 1, 0, "RequiredDefaultCpp");
+ QTest::addColumn<QUrl>("testFile");
+ QTest::addColumn<bool>("shouldSucceed");
+ QTest::addColumn<QString>("errorMsg");
+
+ QTest::addRow("requiredSetViaChainedAlias") << testFileUrl("requiredSetViaChainedAlias.qml") << true << "";
+ QTest::addRow("requiredNotSet") << testFileUrl("requiredNotSet.qml") << false << "Required property i was not initialized";
+ QTest::addRow("requiredSetInSameFile") << testFileUrl("requiredSetInSameFile.qml") << true << "";
+ QTest::addRow("requiredSetViaAlias1") << testFileUrl("requiredSetViaAliasBeforeSameFile.qml") << true << "";
+ QTest::addRow("requiredSetViaAlias2") << testFileUrl("requiredSetViaAliasAfterSameFile.qml") << true << "";
+ QTest::addRow("requiredSetViaAlias3") << testFileUrl("requiredSetViaAliasParentFile.qml") << true << "";
+ QTest::addRow("shadowing") << testFileUrl("shadowing.qml") << false << "Required property i was not initialized";
+ QTest::addRow("setLater") << testFileUrl("requiredSetLater.qml") << true << "";
+ QTest::addRow("setViaAliasToSubcomponent") << testFileUrl("setViaAliasToSubcomponent.qml") << true << "";
+ QTest::addRow("aliasToSubcomponentNotSet") << testFileUrl("aliasToSubcomponentNotSet.qml") << false << "It can be set via the alias property i_alias";
+ QTest::addRow("required default set") << testFileUrl("requiredDefault.1.qml") << true << "";
+ QTest::addRow("required default not set") << testFileUrl("requiredDefault.2.qml") << false << "Required property requiredDefault was not initialized";
+ QTest::addRow("required default set (C++)") << testFileUrl("requiredDefault.3.qml") << true << "";
+ QTest::addRow("required default not set (C++)") << testFileUrl("requiredDefault.4.qml") << false << "Required property defaultProperty was not initialized";
+}
+
+
+void tst_qqmlcomponent::testRequiredProperties()
+{
+ QQmlEngine eng;
+ using QScopedObjPointer = QScopedPointer<QObject>;
+ QFETCH(QUrl, testFile);
+ QFETCH(bool, shouldSucceed);
+ QQmlComponent comp(&eng);
+ comp.loadUrl(testFile);
+ QScopedObjPointer obj {comp.create()};
+ if (shouldSucceed)
+ QVERIFY(obj);
+ else {
+ QVERIFY(!obj);
+ QFETCH(QString, errorMsg);
+ QVERIFY(comp.errorString().contains(errorMsg));
+ }
+}
+
+void tst_qqmlcomponent::testRequiredPropertiesFromQml()
{
QQmlEngine eng;
{
- // JSON based initialization
QQmlComponent comp(&eng);
- comp.loadUrl(testFileUrl("allJSONTypes.qml"));
- QScopedPointer<QObject> obj { comp.beginCreate(eng.rootContext()) };
+ comp.loadUrl(testFileUrl("createdFromQml.qml"));
+ QScopedPointer<QObject> obj { comp.create() };
QVERIFY(obj);
- comp.setInitialProperties(obj.get(), QVariantMap {
- {QLatin1String("i"), 42},
- {QLatin1String("b"), true},
- {QLatin1String("d"), 3.1416},
- {QLatin1String("s"), QLatin1String("hello world")},
- {QLatin1String("nothing"), QVariant::fromValue(nullptr)}
- });
- comp.completeCreate();
- if (!comp.errors().empty())
- qDebug() << comp.errorString() << comp.errors();
- QVERIFY(comp.errors().empty());
- QCOMPARE(obj->property("i"), 42);
- QCOMPARE(obj->property("b"), true);
- QCOMPARE(obj->property("d"), 3.1416);
- QCOMPARE(obj->property("s"), QLatin1String("hello world"));
- QCOMPARE(obj->property("nothing"), QVariant::fromValue(nullptr));
+ auto root = qvariant_cast<QQuickItem*>(obj->property("it"));
+ QVERIFY(root);
+ QCOMPARE(root->property("i").toInt(), 42);
}
{
- // QVariant
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression(".*requiredNotSet.qml:4:5: Required property i was not initialized"));
QQmlComponent comp(&eng);
+ comp.loadUrl(testFileUrl("createdFromQmlFail.qml"));
+ QScopedPointer<QObject> obj { comp.create() };
+ QVERIFY(obj);
+ QCOMPARE(qvariant_cast<QQuickItem *>(obj->property("it")), nullptr);
+ }
+}
+
+struct ComponentWithPublicSetInitial : QQmlComponent
+{
+ using QQmlComponent::QQmlComponent;
+ void setInitialProperties(QObject *o, QVariantMap map)
+ {
+ QQmlComponent::setInitialProperties(o, map);
+ }
+};
+
+void tst_qqmlcomponent::testSetInitialProperties()
+{
+ QQmlEngine eng;
+ {
+ // QVariant
+ ComponentWithPublicSetInitial comp(&eng);
comp.loadUrl(testFileUrl("variantBasedInitialization.qml"));
QScopedPointer<QObject> obj { comp.beginCreate(eng.rootContext()) };
QVERIFY(obj);
@@ -728,8 +792,6 @@ void tst_qqmlcomponent::testSetInitialProperties()
});
#undef ASJSON
comp.completeCreate();
- if (!comp.errors().empty())
- qDebug() << comp.errorString() << comp.errors();
QVERIFY(comp.errors().empty());
QCOMPARE(obj->property("i"), 42);
QCOMPARE(obj->property("b"), true);
@@ -751,13 +813,20 @@ void tst_qqmlcomponent::testSetInitialProperties()
}
{
+ // createWithInitialProperties convenience function
+ QQmlComponent comp(&eng);
+ comp.loadUrl(testFileUrl("requiredNotSet.qml"));
+ QScopedPointer<QObject> obj {comp.createWithInitialProperties( QVariantMap { {QLatin1String("i"), QJsonValue{42}} })};
+ QVERIFY(obj);
+ QCOMPARE(obj->property("i"), 42);
+ }
+ {
// createWithInitialProperties: setting a nonexistent property
QQmlComponent comp(&eng);
comp.loadUrl(testFileUrl("allJSONTypes.qml"));
QScopedPointer<QObject> obj {
comp.createWithInitialProperties(QVariantMap { {"notThePropertiesYoureLookingFor", 42} })
};
- qDebug() << comp.errorString();
QVERIFY(obj);
QVERIFY(comp.errorString().contains("Could not set property notThePropertiesYoureLookingFor"));
}
diff --git a/tests/auto/qml/qqmlconsole/data/logging.qml b/tests/auto/qml/qqmlconsole/data/logging.qml
index 1f929d311b..f5eaeb442a 100644
--- a/tests/auto/qml/qqmlconsole/data/logging.qml
+++ b/tests/auto/qml/qqmlconsole/data/logging.qml
@@ -31,6 +31,8 @@ import QtQuick 2.0
QtObject {
id:root
+ required property var customObject
+ required property var stringListProperty
function consoleCount() {
console.count("console.count", "Ignore additional argument");
@@ -67,7 +69,7 @@ QtObject {
console.log(1, "pong!", new Object);
console.log(1, ["ping","pong"], new Object, 2);
- console.log(contextStringListProperty);
+ console.log(stringListProperty);
console.log(customObject);
console.log([[1,2,3,[2,2,2,2],4],[5,6,7,8]]);
diff --git a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
index b157314071..48613d04f1 100644
--- a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
+++ b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
@@ -95,16 +95,16 @@ void tst_qqmlconsole::logging()
QTest::ignoreMessage(QtDebugMsg, "QVariant(CustomObject, MY OBJECT)");
QTest::ignoreMessage(QtDebugMsg, "[[1,2,3,[2,2,2,2],4],[5,6,7,8]]");
- QScopedPointer<QQmlContext> loggingContext(new QQmlContext(engine.rootContext()));
QStringList stringList; stringList << QStringLiteral("Hello") << QStringLiteral("World");
- loggingContext->setContextProperty("contextStringListProperty", stringList);
CustomObject customObject;
QVERIFY(QMetaType::registerDebugStreamOperator<CustomObject>());
- loggingContext->setContextProperty("customObject", QVariant::fromValue(customObject));
QQmlComponent component(&engine, testUrl);
- QScopedPointer<QObject> object(component.create(loggingContext.data()));
+ QScopedPointer<QObject> object(component.createWithInitialProperties({
+ {"customObject", QVariant::fromValue(customObject)},
+ {"stringListProperty", stringList}
+ }));
QVERIFY(object != nullptr);
}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml b/tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml
new file mode 100644
index 0000000000..01ebfd8e1e
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQml.Models 2.15
+import QtQuick 2.15
+
+import Test 1.0
+
+DelegateModel {
+ model: AbstractItemModel {}
+ delegate: Item {}
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/integerModel.qml b/tests/auto/qml/qqmldelegatemodel/data/integerModel.qml
new file mode 100644
index 0000000000..f6cd886e09
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/integerModel.qml
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQml.Models 2.15
+import QtQuick 2.15
+
+DelegateModel {
+ model: 100
+ delegate: Item {}
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/listModel.qml b/tests/auto/qml/qqmldelegatemodel/data/listModel.qml
new file mode 100644
index 0000000000..1ee8bcac72
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/listModel.qml
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQml.Models 2.15
+import QtQuick 2.15
+
+DelegateModel {
+ model: ListModel {
+ ListElement {
+ name: "Item 0"
+ }
+ ListElement {
+ name: "Item 1"
+ }
+ ListElement {
+ name: "Item 2"
+ }
+ }
+ delegate: Item {}
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro b/tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro
new file mode 100644
index 0000000000..7fdd3ab5f1
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro
@@ -0,0 +1,13 @@
+CONFIG += testcase
+TARGET = tst_qqmldelegatemodel
+macos:CONFIG -= app_bundle
+
+QT += qml testlib core-private qml-private qmlmodels-private
+
+SOURCES += tst_qqmldelegatemodel.cpp
+
+include (../../shared/util.pri)
+
+TESTDATA = data/*
+
+OTHER_FILES += data/*
diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
new file mode 100644
index 0000000000..87f42c0c8a
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/qtest.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQmlModels/private/qqmldelegatemodel_p.h>
+
+#include "../../shared/util.h"
+
+class tst_QQmlDelegateModel : public QQmlDataTest
+{
+ Q_OBJECT
+
+public:
+ tst_QQmlDelegateModel();
+
+private slots:
+ void valueWithoutCallingObjectFirst_data();
+ void valueWithoutCallingObjectFirst();
+};
+
+class AbstractItemModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ AbstractItemModel()
+ {
+ for (int i = 0; i < 3; ++i)
+ mValues.append(QString::fromLatin1("Item %1").arg(i));
+ }
+
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
+ {
+ if (parent.isValid())
+ return QModelIndex();
+
+ return createIndex(row, column);
+ }
+
+ QModelIndex parent(const QModelIndex &) const override
+ {
+ return QModelIndex();
+ }
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override
+ {
+ if (parent.isValid())
+ return 0;
+
+ return mValues.count();
+ }
+
+ int columnCount(const QModelIndex &parent) const override
+ {
+ if (parent.isValid())
+ return 0;
+
+ return 1;
+ }
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
+ {
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ return mValues.at(index.row());
+ }
+
+private:
+ QVector<QString> mValues;
+};
+
+tst_QQmlDelegateModel::tst_QQmlDelegateModel()
+{
+ qmlRegisterType<AbstractItemModel>("Test", 1, 0, "AbstractItemModel");
+}
+
+void tst_QQmlDelegateModel::valueWithoutCallingObjectFirst_data()
+{
+ QTest::addColumn<QUrl>("qmlFileUrl");
+ QTest::addColumn<int>("index");
+ QTest::addColumn<QString>("role");
+ QTest::addColumn<QVariant>("expectedValue");
+
+ QTest::addRow("integer") << testFileUrl("integerModel.qml")
+ << 50 << QString::fromLatin1("modelData") << QVariant(50);
+ QTest::addRow("ListModel") << testFileUrl("listModel.qml")
+ << 1 << QString::fromLatin1("name") << QVariant(QLatin1String("Item 1"));
+ QTest::addRow("QAbstractItemModel") << testFileUrl("abstractItemModel.qml")
+ << 1 << QString::fromLatin1("display") << QVariant(QLatin1String("Item 1"));
+}
+
+// Tests that it's possible to call variantValue() without creating
+// costly delegate items first via object().
+void tst_QQmlDelegateModel::valueWithoutCallingObjectFirst()
+{
+ QFETCH(const QUrl, qmlFileUrl);
+ QFETCH(const int, index);
+ QFETCH(const QString, role);
+ QFETCH(const QVariant, expectedValue);
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(qmlFileUrl);
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY2(root, qPrintable(component.errorString()));
+ QQmlDelegateModel *model = qobject_cast<QQmlDelegateModel*>(root.data());
+ QVERIFY(model);
+ QCOMPARE(model->variantValue(index, role), expectedValue);
+}
+
+QTEST_MAIN(tst_QQmlDelegateModel)
+
+#include "tst_qqmldelegatemodel.moc"
diff --git a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp
index bc4ba9437c..7e96205743 100644
--- a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp
+++ b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp
@@ -63,10 +63,10 @@ namespace {
for (const QQmlJS::DiagnosticMessage &e : errors) {
QString errorString = QLatin1String("qmldir");
- if (e.line > 0) {
- errorString += QLatin1Char(':') + QString::number(e.line);
- if (e.column > 0)
- errorString += QLatin1Char(':') + QString::number(e.column);
+ if (e.loc.startLine > 0) {
+ errorString += QLatin1Char(':') + QString::number(e.loc.startLine);
+ if (e.loc.startColumn > 0)
+ errorString += QLatin1Char(':') + QString::number(e.loc.startColumn);
}
errorString += QLatin1String(": ") + e.message;
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
index 3233e7f105..03e3262e7b 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.h
+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
@@ -36,7 +36,6 @@
#include <QtCore/qregularexpression.h>
#include <QtQml/qqmllist.h>
#include <QtCore/qrect.h>
-#include <QtGui/qmatrix.h>
#include <QtGui/qcolor.h>
#include <QtGui/qvector3d.h>
#include <QtGui/QFont>
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 26232ac1a3..4b0cbfa1aa 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -74,6 +74,7 @@ public:
private slots:
void initTestCase();
+ void arrayIncludesValueType();
void assignBasicTypes();
void assignDate_data();
void assignDate();
@@ -414,6 +415,36 @@ void tst_qqmlecmascript::initTestCase()
registerTypes();
}
+void tst_qqmlecmascript::arrayIncludesValueType()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ // It is vital that QtQuick is imported below else we get a warning about
+ // QQml_colorProvider and tst_qqmlecmascript::signalParameterTypes fails due
+ // to some static variable being initialized with the wrong value
+ component.setData(R"(
+ import QtQuick 2.15
+ import QtQml 2.15
+ QtObject {
+ id: root
+ property color r: Qt.rgba(1, 0, 0)
+ property color g: Qt.rgba(0, 1, 0)
+ property color b: Qt.rgba(0, 0, 1)
+ property var colors: [r, g, b]
+ property bool success: false
+
+ Component.onCompleted: {
+ root.success = root.colors.includes(root.g)
+ }
+ }
+ )", QUrl("testData"));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(o);
+ auto success = o->property("success");
+ QVERIFY(success.isValid());
+ QVERIFY(success.toBool());
+}
+
void tst_qqmlecmascript::assignBasicTypes()
{
QQmlEngine engine;
@@ -6439,6 +6470,8 @@ void tst_qqmlecmascript::topLevelGeneratorFunction()
QQmlComponent component(&engine, testFileUrl("generatorFunction.qml"));
QScopedPointer<QObject> o {component.create()};
+ if (!o)
+ qDebug() << component.errorString();
QVERIFY(o != nullptr);
// check that generator works correctly in QML
@@ -7271,7 +7304,7 @@ void tst_qqmlecmascript::forInLoop()
QMetaObject::invokeMethod(object, "listProperty");
- QStringList r = object->property("listResult").toString().split("|", QString::SkipEmptyParts);
+ QStringList r = object->property("listResult").toString().split("|", Qt::SkipEmptyParts);
QCOMPARE(r.size(), 3);
QCOMPARE(r[0],QLatin1String("0=obj1"));
QCOMPARE(r[1],QLatin1String("1=obj2"));
diff --git a/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.1.qml
index 812242f146..a37461a173 100644
--- a/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.2.qml
index a171ee6b28..1dc06ee6ae 100644
--- a/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.1.qml
index de40284452..ea945eebb0 100644
--- a/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.2.qml
index 4939087b31..9a4fc53833 100644
--- a/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testEmptyComponent.1.qml
index 5cee0341fe..155dbdcb91 100644
--- a/tests/auto/qml/qqmlengine/data/testEmptyComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testEmptyComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testEmptyComponent.2.qml
index 2a13822fab..940d54be90 100644
--- a/tests/auto/qml/qqmlengine/data/testEmptyComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testEmptyComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.1.qml
index 2f238175fa..46d20e38bb 100644
--- a/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.2.qml
index d36e95fec3..ffdb30f072 100644
--- a/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.1.qml
index 53dd5a17e9..ca669a9708 100644
--- a/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.2.qml
index e5cd7d60de..a93c3b302c 100644
--- a/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.1.qml
index d98aef2932..5930e12df6 100644
--- a/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.2.qml
index 7f438aa995..8f929c20b2 100644
--- a/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.1.qml
index 83d6226e83..20bde6d0af 100644
--- a/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.2.qml
index 98dfb7241b..10ae369459 100644
--- a/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testIncubatedComponent.qml b/tests/auto/qml/qqmlengine/data/testIncubatedComponent.qml
index 50af9c4f16..422637fe31 100644
--- a/tests/auto/qml/qqmlengine/data/testIncubatedComponent.qml
+++ b/tests/auto/qml/qqmlengine/data/testIncubatedComponent.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testLoaderComponent.qml b/tests/auto/qml/qqmlengine/data/testLoaderComponent.qml
index a04ca41c26..67d7ddd1c9 100644
--- a/tests/auto/qml/qqmlengine/data/testLoaderComponent.qml
+++ b/tests/auto/qml/qqmlengine/data/testLoaderComponent.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testReloadComponent.qml b/tests/auto/qml/qqmlengine/data/testReloadComponent.qml
index 74442108cd..79d4f29db0 100644
--- a/tests/auto/qml/qqmlengine/data/testReloadComponent.qml
+++ b/tests/auto/qml/qqmlengine/data/testReloadComponent.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testScriptComponent.qml b/tests/auto/qml/qqmlengine/data/testScriptComponent.qml
index b33eb48461..4952a08a6c 100644
--- a/tests/auto/qml/qqmlengine/data/testScriptComponent.qml
+++ b/tests/auto/qml/qqmlengine/data/testScriptComponent.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testTopLevelComponent.qml b/tests/auto/qml/qqmlengine/data/testTopLevelComponent.qml
index 6cf8ec4203..a6a1f4d4d3 100644
--- a/tests/auto/qml/qqmlengine/data/testTopLevelComponent.qml
+++ b/tests/auto/qml/qqmlengine/data/testTopLevelComponent.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testTransientComponent.1.qml b/tests/auto/qml/qqmlengine/data/testTransientComponent.1.qml
index d3e6ffd7cf..c661cb6fe4 100644
--- a/tests/auto/qml/qqmlengine/data/testTransientComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testTransientComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testTransientComponent.2.qml b/tests/auto/qml/qqmlengine/data/testTransientComponent.2.qml
index acb0113e61..8b6c7eda4d 100644
--- a/tests/auto/qml/qqmlengine/data/testTransientComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testTransientComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.1.qml
index a5beede469..8c0596eae4 100644
--- a/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.2.qml
index 4c8e52f251..39b604d42f 100644
--- a/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.1.qml
index 983d6e824c..807203b6c7 100644
--- a/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.2.qml
index fc8e5a0cd4..100b287cfd 100644
--- a/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMEComponent.1.qml
index fcfd05c51f..dddf51b926 100644
--- a/tests/auto/qml/qqmlengine/data/testVMEComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMEComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMEComponent.2.qml
index f434406eec..fa508f16ac 100644
--- a/tests/auto/qml/qqmlengine/data/testVMEComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMEComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.1.qml
index 1dcaec90e6..b36d6ebf14 100644
--- a/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.2.qml
index fd7d7e454c..fce617046b 100644
--- a/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.1.qml
index d2dab32fc9..39629d47df 100644
--- a/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.2.qml
index 813e43896c..a4c947cc17 100644
--- a/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.1.qml
index c6f0b7928b..a87372cd27 100644
--- a/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.2.qml
index 255138520c..c4b16d8ec9 100644
--- a/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.1.qml
index 0ad59b32d3..a18a88884c 100644
--- a/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.2.qml
index 60f72a92fe..eb042e82f8 100644
--- a/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.1.qml
index 6c7f959f49..1f97e587e0 100644
--- a/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.2.qml
index 86060c3998..794686494b 100644
--- a/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.1.qml
index c50fd70dec..f442500c7f 100644
--- a/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.1.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.1.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.2.qml
index 120d249bc0..d57cd8a739 100644
--- a/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.2.qml
+++ b/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.2.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
Item {
property bool success: false
+ required property QtObject componentCache
function reportError(s) { console.warn(s) }
diff --git a/tests/auto/qml/qqmlengine/data/uiLanguage.qml b/tests/auto/qml/qqmlengine/data/uiLanguage.qml
new file mode 100644
index 0000000000..bc20351245
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/uiLanguage.qml
@@ -0,0 +1,9 @@
+import QtQml 2.15
+QtObject {
+ property string chosenLanguage: Qt.uiLanguage
+ property string textToTranslate: {
+ numberOfTranslationBindingEvaluations++;
+ return qsTr("Translate me maybe");
+ }
+ property int numberOfTranslationBindingEvaluations: 0
+}
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index 613616ab71..cfbbd2a94c 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -84,6 +84,7 @@ private slots:
void aggressiveGc();
void cachedGetterLookup_qtbug_75335();
void createComponentOnSingletonDestruction();
+ void uiLanguage();
public slots:
QObject *createAQObjectForOwnershipTest ()
@@ -425,12 +426,13 @@ void tst_qqmlengine::trimComponentCache()
QQmlEngine engine;
ComponentCacheFunctions componentCache(engine);
- engine.rootContext()->setContextProperty("componentCache", &componentCache);
engine.setIncubationController(&componentCache);
QQmlComponent component(&engine, testFileUrl(file));
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> object(component.create());
+ QScopedPointer<QObject> object(component.createWithInitialProperties({
+ {"componentCache", QVariant::fromValue(&componentCache)}
+ }));
QVERIFY(object != nullptr);
QCOMPARE(object->property("success").toBool(), true);
}
@@ -512,6 +514,7 @@ void tst_qqmlengine::failedCompilation()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl(file));
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, "QQmlComponent: Component is not ready");
QVERIFY(!component.isReady());
QScopedPointer<QObject> object(component.create());
QVERIFY(object.isNull());
@@ -602,11 +605,10 @@ void tst_qqmlengine::objectOwnership()
{
QQmlEngine engine;
QQmlComponent c(&engine);
- engine.rootContext()->setContextProperty("test", this);
QQmlEngine::setObjectOwnership(ptr, QQmlEngine::JavaScriptOwnership);
- c.setData("import QtQuick 2.0; Item { property int data: test.createAQObjectForOwnershipTest() ? 0 : 1 }", QUrl());
+ c.setData("import QtQuick 2.0; Item { required property QtObject test; property int data: test.createAQObjectForOwnershipTest() ? 0 : 1 }", QUrl());
QVERIFY(c.isReady());
- QObject *o = c.create();
+ QObject *o = c.createWithInitialProperties( {{"test", QVariant::fromValue(this)}} );
QVERIFY(o != nullptr);
}
QTRY_VERIFY(spy.count());
@@ -617,13 +619,13 @@ void tst_qqmlengine::objectOwnership()
{
QQmlEngine engine;
QQmlComponent c(&engine);
- engine.rootContext()->setContextProperty("test", ptr);
QQmlEngine::setObjectOwnership(ptr, QQmlEngine::JavaScriptOwnership);
- c.setData("import QtQuick 2.0; QtObject { property var object: { var i = test; test ? 0 : 1 } }", QUrl());
+ c.setData("import QtQuick 2.0; QtObject { required property QtObject test; property var object: { var i = test; test ? 0 : 1 } }", QUrl());
QVERIFY(c.isReady());
- QObject *o = c.create();
+ QObject *o = c.createWithInitialProperties({{"test", QVariant::fromValue(ptr)}});
QVERIFY(o != nullptr);
- engine.rootContext()->setContextProperty("test", nullptr);
+ QQmlProperty testProp(o, "test");
+ testProp.write(QVariant::fromValue<QObject*>(nullptr));
}
QTRY_VERIFY(spy.count());
}
@@ -773,6 +775,7 @@ public:
};
Q_DECLARE_METATYPE(QList<QQmlAbstractUrlInterceptor::DataType>);
+
void tst_qqmlengine::urlInterceptor_data()
{
QTest::addColumn<QUrl>("testFile");
@@ -941,14 +944,15 @@ void tst_qqmlengine::cppSignalAndEval()
{
ObjectCaller objectCaller;
QQmlEngine engine;
- engine.rootContext()->setContextProperty(QLatin1String("CallerCpp"), &objectCaller);
+ qmlRegisterSingletonInstance("Test", 1, 0, "CallerCpp", &objectCaller);
QQmlComponent c(&engine);
c.setData("import QtQuick 2.9\n"
+ "import Test 1.0\n"
"Item {\n"
" property var r: 0\n"
" Connections {\n"
" target: CallerCpp;\n"
- " onDoubleReply: {\n"
+ " function onDoubleReply() {\n"
" eval('var z = 1');\n"
" r = a;\n"
" }\n"
@@ -993,6 +997,11 @@ public:
SomeQObjectClass() : QObject(nullptr){}
};
+class Dayfly : public QObject
+{
+ Q_OBJECT
+};
+
void tst_qqmlengine::singletonInstance()
{
QQmlEngine engine;
@@ -1111,7 +1120,7 @@ void tst_qqmlengine::singletonInstance()
{
// deleted object
- auto dayfly = new QObject{};
+ auto dayfly = new Dayfly{};
auto id = qmlRegisterSingletonInstance("Vanity", 1, 0, "Dayfly", dayfly);
delete dayfly;
QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: The registered singleton has already been deleted. Ensure that it outlives the engine.");
@@ -1172,6 +1181,38 @@ void tst_qqmlengine::createComponentOnSingletonDestruction()
QVERIFY(obj);
}
+void tst_qqmlengine::uiLanguage()
+{
+ QQmlEngine engine;
+
+ QObject::connect(&engine, &QJSEngine::uiLanguageChanged, [&engine]() {
+ engine.retranslate();
+ });
+
+ QSignalSpy uiLanguageChangeSpy(&engine, SIGNAL(uiLanguageChanged()));
+
+ QQmlComponent component(&engine, testFileUrl("uiLanguage.qml"));
+
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, (component.url().toString() + ":2:1: QML QtObject: Binding loop detected for property \"textToTranslate\"").toLatin1());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QVERIFY(engine.uiLanguage().isEmpty());
+ QCOMPARE(object->property("numberOfTranslationBindingEvaluations").toInt(), 1);
+
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, (component.url().toString() + ":2:1: QML QtObject: Binding loop detected for property \"textToTranslate\"").toLatin1());
+ engine.setUiLanguage("TestLanguage");
+ QCOMPARE(object->property("numberOfTranslationBindingEvaluations").toInt(), 2);
+ QCOMPARE(object->property("chosenLanguage").toString(), "TestLanguage");
+
+
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, (component.url().toString() + ":2:1: QML QtObject: Binding loop detected for property \"textToTranslate\"").toLatin1());
+ engine.evaluate("Qt.uiLanguage = \"anotherLanguage\"");
+ QCOMPARE(engine.uiLanguage(), QString("anotherLanguage"));
+ QCOMPARE(object->property("numberOfTranslationBindingEvaluations").toInt(), 3);
+ QCOMPARE(object->property("chosenLanguage").toString(), "anotherLanguage");
+}
+
QTEST_MAIN(tst_qqmlengine)
#include "tst_qqmlengine.moc"
diff --git a/tests/auto/qml/qqmlenginecleanup/data/MyItem.qml b/tests/auto/qml/qqmlenginecleanup/data/MyItem.qml
new file mode 100644
index 0000000000..4bb8dfb486
--- /dev/null
+++ b/tests/auto/qml/qqmlenginecleanup/data/MyItem.qml
@@ -0,0 +1,2 @@
+import QtQuick 2.12
+Item {}
diff --git a/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp b/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp
index 690db30838..846ac842db 100644
--- a/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp
+++ b/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp
@@ -45,6 +45,7 @@ private slots:
void test_qmlClearTypeRegistrations();
void test_valueTypeProviderModule(); // QTBUG-43004
void test_customModuleCleanup();
+ void test_qmlListCleared();
};
// A wrapper around QQmlComponent to ensure the temporary reference counts
@@ -186,6 +187,18 @@ void tst_qqmlenginecleanup::test_customModuleCleanup()
}
}
+void tst_qqmlenginecleanup::test_qmlListCleared()
+{
+ {
+ QQmlEngine engine;
+ auto url = testFileUrl("MyItem.qml");
+ QQmlComponent comp(&engine, url);
+ QScopedPointer<QObject> item {comp.create()};
+ QCOMPARE(QQmlMetaType::qmlRegisteredListTypeCount(), 1);
+ }
+ QCOMPARE(QQmlMetaType::qmlRegisteredListTypeCount(), 0);
+}
+
QTEST_MAIN(tst_qqmlenginecleanup)
#include "tst_qqmlenginecleanup.moc"
diff --git a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
index ca1e52ad2c..9c865b3f73 100644
--- a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
+++ b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
@@ -32,6 +32,7 @@
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
#include <private/qqmlimport_p.h>
+#include <private/qqmlengine_p.h>
#include "../../shared/util.h"
class tst_QQmlImport : public QQmlDataTest
@@ -46,6 +47,7 @@ private slots:
void completeQmldirPaths();
void interceptQmldir();
void singletonVersionResolution();
+ void removeDynamicPlugin();
void cleanup();
};
@@ -260,6 +262,25 @@ void tst_QQmlImport::singletonVersionResolution()
}
}
+void tst_QQmlImport::removeDynamicPlugin()
+{
+ qmlClearTypeRegistrations();
+ QQmlEngine engine;
+ {
+ // Load something that adds a dynamic plugin
+ QQmlComponent component(&engine);
+ component.setData(QByteArray("import QtTest 1.0; TestResult{}"), QUrl());
+ QVERIFY(component.isReady());
+ }
+ QQmlImportDatabase *imports = &QQmlEnginePrivate::get(&engine)->importDatabase;
+ const QStringList &plugins = imports->dynamicPlugins();
+ QVERIFY(!plugins.isEmpty());
+ for (const QString &plugin : plugins)
+ QVERIFY(imports->removeDynamicPlugin(plugin));
+ QVERIFY(imports->dynamicPlugins().isEmpty());
+ qmlClearTypeRegistrations();
+}
+
QTEST_MAIN(tst_QQmlImport)
diff --git a/tests/auto/qml/qqmlincubator/data/requiredProperty.qml b/tests/auto/qml/qqmlincubator/data/requiredProperty.qml
new file mode 100644
index 0000000000..9e355dce72
--- /dev/null
+++ b/tests/auto/qml/qqmlincubator/data/requiredProperty.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.12
+
+Item {
+ required property int requiredProperty
+}
diff --git a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
index 8e25079703..549aae8c2b 100644
--- a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
+++ b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
@@ -70,6 +70,7 @@ private slots:
void selfDelete();
void contextDelete();
void garbageCollection();
+ void requiredProperties();
private:
QQmlIncubationController controller;
@@ -148,7 +149,7 @@ void tst_qqmlincubator::objectDeleted()
QVERIFY(!SelfRegisteringType::me());
while (SelfRegisteringOuterType::me() == nullptr && incubator.isLoading()) {
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -156,14 +157,14 @@ void tst_qqmlincubator::objectDeleted()
QVERIFY(incubator.isLoading());
while (SelfRegisteringType::me() == nullptr && incubator.isLoading()) {
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
delete SelfRegisteringType::me();
{
- bool b = true;
+ std::atomic<bool> b{true};
controller.incubateWhile(&b);
}
@@ -204,7 +205,7 @@ void tst_qqmlincubator::clear()
component.create(incubator);
while (SelfRegisteringType::me() == nullptr && incubator.isLoading()) {
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -223,7 +224,7 @@ void tst_qqmlincubator::clear()
component.create(incubator);
{
- bool b = true;
+ std::atomic<bool> b{true};
controller.incubateWhile(&b);
}
@@ -317,7 +318,7 @@ void tst_qqmlincubator::forceCompletion()
QVERIFY(incubator.isLoading());
while (SelfRegisteringType::me() == nullptr && incubator.isLoading()) {
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -376,7 +377,7 @@ void tst_qqmlincubator::setInitialState()
MyIncubator incubator(QQmlIncubator::Asynchronous);
component.create(incubator);
QVERIFY(incubator.isLoading());
- bool b = true;
+ std::atomic<bool> b{true};
controller.incubateWhile(&b);
QVERIFY(incubator.isReady());
QVERIFY(incubator.object());
@@ -413,7 +414,7 @@ void tst_qqmlincubator::clearDuringCompletion()
QVERIFY(!CompletionRegisteringType::me());
while (CompletionRegisteringType::me() == nullptr && incubator.isLoading()) {
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -452,7 +453,7 @@ void tst_qqmlincubator::objectDeletionAfterInit()
component.create(incubator);
while (!incubator.obj && incubator.isLoading()) {
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -551,7 +552,7 @@ void tst_qqmlincubator::statusChanged()
QCOMPARE(incubator.statuses.at(0), int(QQmlIncubator::Loading));
{
- bool b = true;
+ std::atomic<bool> b{true};
controller.incubateWhile(&b);
}
@@ -573,7 +574,7 @@ void tst_qqmlincubator::statusChanged()
QCOMPARE(incubator.statuses.at(0), int(QQmlIncubator::Loading));
{
- bool b = true;
+ std::atomic<bool> b{true};
controller.incubateWhile(&b);
}
@@ -621,7 +622,7 @@ void tst_qqmlincubator::asynchronousIfNested()
QVERIFY(incubator.isLoading());
QVERIFY(!SelfRegisteringType::me());
while (SelfRegisteringType::me() == nullptr && incubator.isLoading()) {
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -634,7 +635,7 @@ void tst_qqmlincubator::asynchronousIfNested()
while (nested.isLoading()) {
QVERIFY(incubator.isLoading());
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -642,7 +643,7 @@ void tst_qqmlincubator::asynchronousIfNested()
QVERIFY(incubator.isLoading());
{
- bool b = true;
+ std::atomic<bool> b{true};
controller.incubateWhile(&b);
}
@@ -741,7 +742,7 @@ void tst_qqmlincubator::chainedAsynchronousIfNested()
QVERIFY(!SelfRegisteringType::me());
while (SelfRegisteringType::me() == nullptr && incubator.isLoading()) {
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -778,7 +779,7 @@ void tst_qqmlincubator::chainedAsynchronousIfNested()
QVERIFY(incubator1.isLoading());
QVERIFY(incubator2.isNull());
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -791,14 +792,14 @@ void tst_qqmlincubator::chainedAsynchronousIfNested()
QVERIFY(incubator1.isReady());
QVERIFY(incubator2.isLoading());
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
QVERIFY(incubator1.isReady());
QVERIFY(incubator2.isReady());
if (incubator.isLoading()) {
- bool b = true;
+ std::atomic<bool> b{true};
controller.incubateWhile(&b);
}
@@ -855,7 +856,7 @@ void tst_qqmlincubator::chainedAsynchronousIfNestedOnCompleted()
QVERIFY(!SelfRegisteringType::me());
while (SelfRegisteringType::me() == nullptr && incubator.isLoading()) {
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -875,7 +876,7 @@ void tst_qqmlincubator::chainedAsynchronousIfNestedOnCompleted()
QVERIFY(incubator2.isNull());
QVERIFY(incubator3.isNull());
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -890,7 +891,7 @@ void tst_qqmlincubator::chainedAsynchronousIfNestedOnCompleted()
QVERIFY(incubator2.isNull());
QVERIFY(incubator3.isNull());
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -905,7 +906,7 @@ void tst_qqmlincubator::chainedAsynchronousIfNestedOnCompleted()
QVERIFY(incubator2.isLoading());
QVERIFY(incubator3.isNull());
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -920,12 +921,12 @@ void tst_qqmlincubator::chainedAsynchronousIfNestedOnCompleted()
QVERIFY(incubator2.isReady());
QVERIFY(incubator3.isLoading());
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
{
- bool b = true;
+ std::atomic<bool> b{true};
controller.incubateWhile(&b);
}
@@ -983,7 +984,7 @@ void tst_qqmlincubator::chainedAsynchronousClear()
QVERIFY(!SelfRegisteringType::me());
while (SelfRegisteringType::me() == nullptr && incubator.isLoading()) {
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -1003,7 +1004,7 @@ void tst_qqmlincubator::chainedAsynchronousClear()
QVERIFY(incubator2.isNull());
QVERIFY(incubator3.isNull());
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -1018,7 +1019,7 @@ void tst_qqmlincubator::chainedAsynchronousClear()
QVERIFY(incubator2.isNull());
QVERIFY(incubator3.isNull());
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -1033,7 +1034,7 @@ void tst_qqmlincubator::chainedAsynchronousClear()
QVERIFY(incubator2.isLoading());
QVERIFY(incubator3.isNull());
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -1077,7 +1078,7 @@ void tst_qqmlincubator::selfDelete()
#define DELETE_TEST(status, mode) { \
bool done = false; \
component.create(*(new MyIncubator(&done, status, mode))); \
- bool True = true; \
+ std::atomic<bool> True{true}; \
controller.incubateWhile(&True); \
QVERIFY(done == true); \
}
@@ -1106,7 +1107,7 @@ void tst_qqmlincubator::selfDelete()
QVERIFY(!SelfRegisteringType::me());
while (SelfRegisteringType::me() == nullptr && incubator->isLoading()) {
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
@@ -1120,7 +1121,7 @@ void tst_qqmlincubator::selfDelete()
delete SelfRegisteringType::me();
{
- bool b = true;
+ std::atomic<bool> b{true};
controller.incubateWhile(&b);
}
@@ -1141,7 +1142,7 @@ void tst_qqmlincubator::contextDelete()
delete context;
{
- bool b = false;
+ std::atomic<bool> b{false};
controller.incubateWhile(&b);
}
}
@@ -1154,7 +1155,7 @@ void tst_qqmlincubator::garbageCollection()
engine.collectGarbage();
- bool b = true;
+ std::atomic<bool> b{true};
controller.incubateWhile(&b);
// verify incubation completed (the incubator was not prematurely collected)
@@ -1174,6 +1175,44 @@ void tst_qqmlincubator::garbageCollection()
QVERIFY(weakIncubatorRef.isNullOrUndefined());
}
+void tst_qqmlincubator::requiredProperties()
+{
+ {
+ QQmlComponent component(&engine, testFileUrl("requiredProperty.qml"));
+ QVERIFY(component.isReady());
+ // forceCompletion immediately after creating an asynchronous object completes it
+ QQmlIncubator incubator;
+ incubator.setInitialProperties({{"requiredProperty", 42}});
+ QVERIFY(incubator.isNull());
+ component.create(incubator);
+ QVERIFY(incubator.isLoading());
+
+ incubator.forceCompletion();
+
+ QVERIFY(incubator.isReady());
+ QVERIFY(incubator.object() != nullptr);
+ QCOMPARE(incubator.object()->property("requiredProperty").toInt(), 42);
+
+ delete incubator.object();
+ }
+ {
+ QQmlComponent component(&engine, testFileUrl("requiredProperty.qml"));
+ QVERIFY(component.isReady());
+ // forceCompletion immediately after creating an asynchronous object completes it
+ QQmlIncubator incubator;
+ QVERIFY(incubator.isNull());
+ component.create(incubator);
+ QVERIFY(incubator.isLoading());
+
+ incubator.forceCompletion();
+
+ QVERIFY(incubator.isError());
+ auto error = incubator.errors().first();
+ QVERIFY(error.description().contains(QLatin1String("Required property requiredProperty was not initialized")));
+ QVERIFY(incubator.object() == nullptr);
+ }
+}
+
QTEST_MAIN(tst_qqmlincubator)
#include "tst_qqmlincubator.moc"
diff --git a/tests/auto/qml/qqmlinstantiator/data/createAndRemove.qml b/tests/auto/qml/qqmlinstantiator/data/createAndRemove.qml
index 5dd322b5f5..40e996ee4a 100644
--- a/tests/auto/qml/qqmlinstantiator/data/createAndRemove.qml
+++ b/tests/auto/qml/qqmlinstantiator/data/createAndRemove.qml
@@ -1,18 +1,19 @@
import QtQml 2.1
import QtQuick 2.1
+import Test 1.0
Rectangle {
Instantiator {
objectName: "instantiator1"
- model: model1
+ model: Model1
delegate: QtObject {
property string datum: model.text
}
}
Component.onCompleted: {
- model1.add("Delta");
- model1.add("Gamma");
- model1.add("Beta");
- model1.add("Alpha");
+ Model1.add("Delta");
+ Model1.add("Gamma");
+ Model1.add("Beta");
+ Model1.add("Alpha");
}
}
diff --git a/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp b/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp
index 9c5e09c77c..84e08c471a 100644
--- a/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp
+++ b/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp
@@ -190,9 +190,9 @@ void tst_qqmlinstantiator::intModelChange()
void tst_qqmlinstantiator::createAndRemove()
{
QQmlEngine engine;
+ QScopedPointer<StringModel> model {new StringModel("model1")};
+ qmlRegisterSingletonInstance("Test", 1, 0, "Model1", model.get());
QQmlComponent component(&engine, testFileUrl("createAndRemove.qml"));
- StringModel *model = new StringModel("model1");
- engine.rootContext()->setContextProperty("model1", model);
QObject *rootObject = component.create();
QVERIFY(rootObject != nullptr);
diff --git a/tests/auto/qml/qqmllanguage/data/Action.qml b/tests/auto/qml/qqmllanguage/data/Action.qml
new file mode 100644
index 0000000000..4db2bacf6e
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/Action.qml
@@ -0,0 +1,21 @@
+import QtQuick 2.12
+
+QtObject {
+ id:root
+ property Item parent
+ property Item displayComponent: null
+
+ property list<QtObject> children
+
+ readonly property var visibleChildren: {
+ var visible = [];
+ var child;
+ for (var i in children) {
+ child = children[i];
+ if (!child.hasOwnProperty("visible") || child.visible) {
+ visible.push(child)
+ }
+ }
+ return visible;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/InlineComponentBase.qml b/tests/auto/qml/qqmllanguage/data/InlineComponentBase.qml
new file mode 100644
index 0000000000..0b297a7779
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/InlineComponentBase.qml
@@ -0,0 +1,9 @@
+import QtQml 2.15
+
+QtObject {
+ property alias i: icInstance.i
+ component IC : QtObject {
+ property int i: 42
+ }
+ property QtObject ic: IC {id: icInstance}
+}
diff --git a/tests/auto/qml/qqmllanguage/data/InlineComponentChild.qml b/tests/auto/qml/qqmllanguage/data/InlineComponentChild.qml
new file mode 100644
index 0000000000..49a90ab7da
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/InlineComponentChild.qml
@@ -0,0 +1,7 @@
+import QtQml 2.15
+
+InlineComponentBase {
+ component IC : QtObject {
+ property int i: 13
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/InlineComponentProvider.qml b/tests/auto/qml/qqmllanguage/data/InlineComponentProvider.qml
new file mode 100644
index 0000000000..6058e32b2f
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/InlineComponentProvider.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.15
+
+Item {
+ component StyledRectangle: Rectangle {
+ width: 24
+ height: 24
+ color: "red"
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/InlineComponentProvider2.qml b/tests/auto/qml/qqmllanguage/data/InlineComponentProvider2.qml
new file mode 100644
index 0000000000..b5a0efaccf
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/InlineComponentProvider2.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.15
+
+Item {
+ property color myColor: "red"
+ component StyledRectangle: Rectangle {
+ width: 24
+ height: 24
+ color: myColor
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/InlineComponentProvider3.qml b/tests/auto/qml/qqmllanguage/data/InlineComponentProvider3.qml
new file mode 100644
index 0000000000..9a4f1fd272
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/InlineComponentProvider3.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.15
+
+Item {
+ Item {
+ component StyledRectangle: Rectangle {
+ width: 24
+ height: 24
+ color: "red"
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/InlineComponentProviderChild.qml b/tests/auto/qml/qqmllanguage/data/InlineComponentProviderChild.qml
new file mode 100644
index 0000000000..ddb55e55e6
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/InlineComponentProviderChild.qml
@@ -0,0 +1 @@
+InlineComponentProvider {}
diff --git a/tests/auto/qml/qqmllanguage/data/InlineComponentReexporter.qml b/tests/auto/qml/qqmllanguage/data/InlineComponentReexporter.qml
new file mode 100644
index 0000000000..24bf6f771e
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/InlineComponentReexporter.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.14
+
+QtObject {
+ component StyledRectangle: InlineComponentProvider.StyledRectangle {
+ color: "green"
+ }
+
+}
diff --git a/tests/auto/qml/qqmllanguage/data/NonRequiredBase.qml b/tests/auto/qml/qqmllanguage/data/NonRequiredBase.qml
new file mode 100644
index 0000000000..60d45c2b1e
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/NonRequiredBase.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Item {
+ property int i
+}
diff --git a/tests/auto/qml/qqmllanguage/data/RequiredBase.qml b/tests/auto/qml/qqmllanguage/data/RequiredBase.qml
new file mode 100644
index 0000000000..4effdbf1c7
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/RequiredBase.qml
@@ -0,0 +1,3 @@
+NonRequiredBase {
+ required i
+}
diff --git a/tests/auto/qml/qqmllanguage/data/SelfInstantiation.errors.txt b/tests/auto/qml/qqmllanguage/data/SelfInstantiation.errors.txt
new file mode 100644
index 0000000000..dfd077941e
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/SelfInstantiation.errors.txt
@@ -0,0 +1 @@
+3:29:SelfInstantiation is instantiated recursively
diff --git a/tests/auto/qml/qqmllanguage/data/SelfInstantiation.qml b/tests/auto/qml/qqmllanguage/data/SelfInstantiation.qml
new file mode 100644
index 0000000000..b2e4e453a0
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/SelfInstantiation.qml
@@ -0,0 +1,5 @@
+import QtQml 2.0
+QtObject {
+ property QtObject self: SelfInstantiation {
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/SelfReference.qml b/tests/auto/qml/qqmllanguage/data/SelfReference.qml
new file mode 100644
index 0000000000..129a171d77
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/SelfReference.qml
@@ -0,0 +1,8 @@
+import QtQml 2.0
+QtObject {
+ property SelfReference self
+ signal blah(selfParam: SelfReference)
+ function returnSelf() : SelfReference {
+ return this;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/SimpleItem.qml b/tests/auto/qml/qqmllanguage/data/SimpleItem.qml
new file mode 100644
index 0000000000..c7bce2bc78
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/SimpleItem.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Item {
+ property int i: 42
+}
diff --git a/tests/auto/qml/qqmllanguage/data/alias.14.errors.txt b/tests/auto/qml/qqmllanguage/data/alias.14.errors.txt
deleted file mode 100644
index 90a3ea4317..0000000000
--- a/tests/auto/qml/qqmllanguage/data/alias.14.errors.txt
+++ /dev/null
@@ -1 +0,0 @@
-10:34:References to other aliases within the same object are not supported at the moment
diff --git a/tests/auto/qml/qqmllanguage/data/alias.18.errors.txt b/tests/auto/qml/qqmllanguage/data/alias.18.errors.txt
new file mode 100644
index 0000000000..dda3e7a174
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/alias.18.errors.txt
@@ -0,0 +1 @@
+7:24:Duplicate alias name
diff --git a/tests/auto/qml/qqmllanguage/data/alias.18.qml b/tests/auto/qml/qqmllanguage/data/alias.18.qml
new file mode 100644
index 0000000000..a9be937975
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/alias.18.qml
@@ -0,0 +1,9 @@
+import QtQml 2.14
+
+QtObject {
+ id: root
+ property QtObject o1: QtObject {
+ property alias a: root
+ property alias a: root
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml b/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml
index ee400eb41f..d8e278a7a1 100644
--- a/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml
+++ b/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml
@@ -3,5 +3,7 @@ import qt.test 1.0
TestItem {
property var vector
+ property var myset
positions: vector
+ barrays: myset
}
diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredProperty.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredProperty.qml
new file mode 100644
index 0000000000..76673f6409
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cppRequiredProperty.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.15
+import example.org 1.0
+
+MyClass {test: 42}
diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParent.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParent.qml
new file mode 100644
index 0000000000..d4c059581c
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParent.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.15
+import example.org 1.0
+
+Child2 {test: test2; test2: 18}
diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParentNotSet.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParentNotSet.qml
new file mode 100644
index 0000000000..082e22dc3f
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParentNotSet.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.15
+import example.org 1.0
+
+Child2 { test: 13 }
diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParent.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParent.qml
new file mode 100644
index 0000000000..6602684542
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParent.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.15
+import example.org 1.0
+
+Child {test: 42}
diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParentNotSet.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParentNotSet.qml
new file mode 100644
index 0000000000..5971b0c263
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParentNotSet.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.15
+import example.org 1.0
+
+Child {}
diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyNotSet.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyNotSet.qml
new file mode 100644
index 0000000000..dab48a3d71
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyNotSet.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.15
+import example.org 1.0
+
+MyClass {}
diff --git a/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.2.qml b/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.2.qml
new file mode 100644
index 0000000000..3b37c29b18
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.2.qml
@@ -0,0 +1,5 @@
+import StaticTest 1.0
+
+MyStaticSecondNamespacedType {
+ list: [ MyStaticNamespacedType {} ]
+}
diff --git a/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.qml b/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.qml
new file mode 100644
index 0000000000..2778baadb9
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.qml
@@ -0,0 +1,6 @@
+import StaticTest 1.0
+
+MyStaticNamespacedType {
+ myEnum: MyStaticNamespace.Key5
+ property int intProperty: MyStaticNamespace.MyOtherNSEnum.OtherKey2
+}
diff --git a/tests/auto/qml/qqmllanguage/data/foreignExtended.qml b/tests/auto/qml/qqmllanguage/data/foreignExtended.qml
new file mode 100644
index 0000000000..182d60fd02
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/foreignExtended.qml
@@ -0,0 +1,20 @@
+import QtQml 2.12
+import Test 1.0
+
+QtObject {
+ property Foreign foreign: Foreign {
+ objectName: "foreign"
+ }
+ property Extended extended: Extended {}
+ property ForeignExtended foreignExtended: ForeignExtended {
+ objectName: "foreignExtended"
+ }
+
+ property int extendedBase: extended.base
+
+ property int extendedExtension: extended.extension
+ property int foreignExtendedExtension: foreignExtended.extension
+
+ property string foreignObjectName: foreign.objectName
+ property string foreignExtendedObjectName: foreignExtended.objectName
+}
diff --git a/tests/auto/qml/qqmllanguage/data/icCycleViaProperty.qml b/tests/auto/qml/qqmllanguage/data/icCycleViaProperty.qml
new file mode 100644
index 0000000000..c5aa4cfdf5
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/icCycleViaProperty.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.15
+
+Item {
+ component A : Item {
+ property var test: B {}
+ }
+ component B: A {}
+ A {}
+}
diff --git a/tests/auto/qml/qqmllanguage/data/icSimpleCycle.qml b/tests/auto/qml/qqmllanguage/data/icSimpleCycle.qml
new file mode 100644
index 0000000000..69e74f7c96
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/icSimpleCycle.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.15
+
+Item {
+ component A : B {}
+ component B: A {}
+}
diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentDuplicateName.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentDuplicateName.qml
new file mode 100644
index 0000000000..12cc79cf14
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/inlineComponentDuplicateName.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.12
+Item
+{
+ component IC: Item {}
+ component IC: Item {}
+}
diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentFoundBeforeOtherImports.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentFoundBeforeOtherImports.qml
new file mode 100644
index 0000000000..85903727fb
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/inlineComponentFoundBeforeOtherImports.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.12
+
+Item
+{
+ component Rectangle: Item {
+ Component.onCompleted: console.info("Created")
+ }
+ Rectangle {}
+}
diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentOrder.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentOrder.qml
new file mode 100644
index 0000000000..a96f68e56a
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/inlineComponentOrder.qml
@@ -0,0 +1,20 @@
+import QtQuick 2.15
+
+Item {
+ width: 600
+ height: 480
+ IC2 {
+ objectName: "icInstance"
+ anchors.centerIn: parent
+ }
+
+ component IC2: IC1 {}
+ component IC0: Rectangle {
+ height: 200
+ width: 200
+ color: "blue"
+ }
+ component IC1: IC0 {}
+
+
+}
diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentUser1.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentUser1.qml
new file mode 100644
index 0000000000..8968a20112
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/inlineComponentUser1.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.14
+
+Item {
+ width: 600
+ height: 480
+ property InlineComponentProvider.StyledRectangle myProp: InlineComponentProvider.StyledRectangle {}
+ InlineComponentProvider.StyledRectangle {
+ objectName: "icInstance"
+ anchors.centerIn: parent
+ color: "blue"
+ }
+
+}
diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentUser2.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentUser2.qml
new file mode 100644
index 0000000000..dc6e3850db
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/inlineComponentUser2.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.14
+
+Item {
+ width: 600
+ height: 480
+ property InlineComponentProvider.StyledRectangle myProp: InlineComponentReexporter.StyledRectangle {
+ objectName: "icInstance"
+ }
+
+}
diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentUser3.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentUser3.qml
new file mode 100644
index 0000000000..c57c4cad01
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/inlineComponentUser3.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.14
+
+Item {
+ width: 600
+ height: 480
+ component StyledRectangle: Rectangle {
+ width: 24
+ height: 24
+ color: "blue"
+ }
+ StyledRectangle {
+ objectName: "icInstance"
+ anchors.centerIn: parent
+ }
+
+}
diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentUser4.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentUser4.qml
new file mode 100644
index 0000000000..9f3903c8df
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/inlineComponentUser4.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.14
+
+Item {
+ width: 600
+ height: 480
+ property color myColor: "blue"
+ InlineComponentProvider2.StyledRectangle {
+ objectName: "icInstance"
+ anchors.centerIn: parent
+ }
+
+}
diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentUser5.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentUser5.qml
new file mode 100644
index 0000000000..150d0c2ded
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/inlineComponentUser5.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.15
+
+Item {
+ width: 600
+ height: 480
+ property var test: InlineComponentProvider3.StyledRectangle {
+ objectName: "icInstance"
+ anchors.centerIn: parent
+ }
+
+}
diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentWithAlias.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentWithAlias.qml
new file mode 100644
index 0000000000..ab125e9323
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/inlineComponentWithAlias.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.15
+
+Item {
+ id: root
+ component IC: SimpleItem {
+ width: i
+ Rectangle {
+ id: rect
+ color: "lime"
+ }
+ property alias color: rect.color
+ }
+ width: 200
+ IC {
+ objectName: "icInstance"
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentWithId.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentWithId.qml
new file mode 100644
index 0000000000..c4093bad2f
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/inlineComponentWithId.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.15
+
+Item {
+ id: root
+ component IC: SimpleItem {
+ id: root
+ width: root.i
+ property color color: "red"
+ }
+ width: 200
+ IC {
+ objectName: "icInstance"
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/invalidRoot.4.errors.txt b/tests/auto/qml/qqmllanguage/data/invalidRoot.4.errors.txt
index 3b90f573a2..41cb0eaac1 100644
--- a/tests/auto/qml/qqmllanguage/data/invalidRoot.4.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/invalidRoot.4.errors.txt
@@ -1 +1 @@
-3:1:Bar.Item - Bar is not a namespace
+3:1:Bar.Item - Bar is neither a type nor a namespace
diff --git a/tests/auto/qml/qqmllanguage/data/invalidTypeName.4.errors.txt b/tests/auto/qml/qqmllanguage/data/invalidTypeName.4.errors.txt
index 3b90f573a2..41cb0eaac1 100644
--- a/tests/auto/qml/qqmllanguage/data/invalidTypeName.4.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/invalidTypeName.4.errors.txt
@@ -1 +1 @@
-3:1:Bar.Item - Bar is not a namespace
+3:1:Bar.Item - Bar is neither a type nor a namespace
diff --git a/tests/auto/qml/qqmllanguage/data/listContainingDeleted.qml b/tests/auto/qml/qqmllanguage/data/listContainingDeleted.qml
new file mode 100644
index 0000000000..efd273ddc6
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/listContainingDeleted.qml
@@ -0,0 +1,36 @@
+import QtQuick 2.12
+
+Item {
+ width: 1024
+ height: 800
+
+ property Component a: Component {
+ id: a
+ Item {
+ property list<QtObject> myList: [
+ QtObject {
+ property bool enabled: true
+ }
+ ]
+ }
+ }
+ Component {
+ id: b
+ Item {
+ property list<QtObject> myList
+
+ function test() {
+ for (var i = 0; i < myList.length; ++i)
+ console.log(i, "==", myList[i].enabled)
+ }
+ }
+ }
+ property Item instance
+ function doAssign(o) {
+ instance = b.createObject(null, {myList: o.myList})
+ }
+ function use() {
+ instance.test()
+ }
+
+}
diff --git a/tests/auto/qml/qqmllanguage/data/listPropertiesChild.qml b/tests/auto/qml/qqmllanguage/data/listPropertiesChild.qml
new file mode 100644
index 0000000000..b1635a9409
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/listPropertiesChild.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.12
+
+Action
+{
+ id: action
+ property color color
+}
diff --git a/tests/auto/qml/qqmllanguage/data/nestedIC.qml b/tests/auto/qml/qqmllanguage/data/nestedIC.qml
new file mode 100644
index 0000000000..04cef64d54
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nestedIC.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ component Outer : Item {
+ component Inner : Item {}
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/nonExistingICUser1.qml b/tests/auto/qml/qqmllanguage/data/nonExistingICUser1.qml
new file mode 100644
index 0000000000..a07a6a9838
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nonExistingICUser1.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Item {
+ property InlineComponentProvider.NonExisting myProp
+}
diff --git a/tests/auto/qml/qqmllanguage/data/nonExistingICUser2.qml b/tests/auto/qml/qqmllanguage/data/nonExistingICUser2.qml
new file mode 100644
index 0000000000..5c24962def
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nonExistingICUser2.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Item {
+ InlineComponentProvider.NotExisting {}
+}
diff --git a/tests/auto/qml/qqmllanguage/data/nonExistingICUser3.qml b/tests/auto/qml/qqmllanguage/data/nonExistingICUser3.qml
new file mode 100644
index 0000000000..34595707fc
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nonExistingICUser3.qml
@@ -0,0 +1,3 @@
+import QtQuick 2.15
+
+InlineComponentProvider.NotExisting {}
diff --git a/tests/auto/qml/qqmllanguage/data/nonExistingICUser4.qml b/tests/auto/qml/qqmllanguage/data/nonExistingICUser4.qml
new file mode 100644
index 0000000000..2be01ccd96
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nonExistingICUser4.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.0
+import "singleton" as MySingleton
+
+Item {
+ property MySingleton.SingletonTypeWithIC.NonExisting singletonIC
+}
diff --git a/tests/auto/qml/qqmllanguage/data/nonExistingICUser5.qml b/tests/auto/qml/qqmllanguage/data/nonExistingICUser5.qml
new file mode 100644
index 0000000000..a2ca5db6de
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nonExistingICUser5.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Item {
+ property InlineComponentProviderChild.StyledRectangle myProp
+}
diff --git a/tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_And.errors.txt b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_And.errors.txt
new file mode 100644
index 0000000000..d4f3eb3ecf
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_And.errors.txt
@@ -0,0 +1 @@
+6:29:Left-hand side may not contain || or &&
diff --git a/tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_And.qml b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_And.qml
new file mode 100644
index 0000000000..ce6aa9a532
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_And.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+Component {
+ Component.onCompleted: {
+ // Should cause an error since having either || or && on any side of the coalescing operator is banned by the specification
+ var bad_lhs_and = 3 && 4 ?? 0;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_Or.errors.txt b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_Or.errors.txt
new file mode 100644
index 0000000000..f2f1719acd
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_Or.errors.txt
@@ -0,0 +1 @@
+6:28:Left-hand side may not contain || or &&
diff --git a/tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_Or.qml b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_Or.qml
new file mode 100644
index 0000000000..8864524d0d
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_Or.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+Component {
+ Component.onCompleted: {
+ // Should cause an error since having either || or && on any side of the coalescing operator is banned by the specification
+ var bad_lhs_or = 3 || 4 ?? 0;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_And.errors.txt b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_And.errors.txt
new file mode 100644
index 0000000000..0ff61be687
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_And.errors.txt
@@ -0,0 +1 @@
+6:34:Right-hand side may not contain || or &&
diff --git a/tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_And.qml b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_And.qml
new file mode 100644
index 0000000000..97898f055a
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_And.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+Component {
+ Component.onCompleted: {
+ // Should cause an error since having either || or && on any side of the coalescing operator is banned by the specification
+ var bad_rhs_and = 0 ?? 3 && 4;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_Or.errors.txt b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_Or.errors.txt
new file mode 100644
index 0000000000..4b2784ac0a
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_Or.errors.txt
@@ -0,0 +1 @@
+6:33:Right-hand side may not contain || or &&
diff --git a/tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_Or.qml b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_Or.qml
new file mode 100644
index 0000000000..f172755e91
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_Or.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+Component {
+ Component.onCompleted: {
+ // Should cause an error since having either || or && on any side of the coalescing operator is banned by the specification
+ var bad_rhs_or = 0 ?? 3 || 4;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.1.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.1.qml
new file mode 100644
index 0000000000..dac43c6d88
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.1.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.13
+Item {
+ property var required: 32 // required is still allowed as an identifier for properties
+ function f(required) { // for javascript
+ required = required + required;
+ console.log(required);
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.2.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.2.qml
new file mode 100644
index 0000000000..4c12c7b602
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.2.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.13
+Item {
+ required property int test: 42 // cannot specify value for required property
+}
diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml
new file mode 100644
index 0000000000..2585cf361e
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.15
+
+Item {
+ property int i;
+ required i;
+}
diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.4.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.4.qml
new file mode 100644
index 0000000000..1126f845c9
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.4.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Item {
+ required objectName
+}
diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.5.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.5.qml
new file mode 100644
index 0000000000..c2d155b123
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.5.qml
@@ -0,0 +1 @@
+RequiredBase {}
diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.6.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.6.qml
new file mode 100644
index 0000000000..e8802aef20
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.6.qml
@@ -0,0 +1,3 @@
+RequiredBase {
+ i: 42
+}
diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.7.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.7.qml
new file mode 100644
index 0000000000..40987f5c56
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.7.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Item {
+ required blub
+}
diff --git a/tests/auto/qml/qqmllanguage/data/selfreferencingsingletonmodule/TestSingleton.qml b/tests/auto/qml/qqmllanguage/data/selfreferencingsingletonmodule/TestSingleton.qml
new file mode 100644
index 0000000000..f70a3b1fea
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/selfreferencingsingletonmodule/TestSingleton.qml
@@ -0,0 +1,7 @@
+import QtQml 2.0
+import selfreferencingsingletonmodule 1.0
+pragma Singleton
+QtObject {
+ property SelfReferencingSingleton self
+ property int dummy: 42
+}
diff --git a/tests/auto/qml/qqmllanguage/data/selfreferencingsingletonmodule/qmldir b/tests/auto/qml/qqmllanguage/data/selfreferencingsingletonmodule/qmldir
new file mode 100644
index 0000000000..617861b00b
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/selfreferencingsingletonmodule/qmldir
@@ -0,0 +1 @@
+singleton SelfReferencingSingleton 1.0 TestSingleton.qml
diff --git a/tests/auto/qml/qqmllanguage/data/singleton/SingletonTypeWithIC.qml b/tests/auto/qml/qqmllanguage/data/singleton/SingletonTypeWithIC.qml
new file mode 100644
index 0000000000..bd724c4aeb
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/singleton/SingletonTypeWithIC.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+pragma Singleton
+
+Item {
+ id: singletonId
+ component IC1: Item {
+ property int iProp: 42
+ property string sProp: "Hello, world"
+ property Rectangle myRect: Rectangle {color: "green"}
+ }
+ component IC2: Item {
+ property int iProp: 13
+ property string sProp: "Goodbye, world"
+ property Rectangle myRect: Rectangle {color: "red"}
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/singleton/qmldir b/tests/auto/qml/qqmllanguage/data/singleton/qmldir
index 533fb6999a..727b09b4e8 100644
--- a/tests/auto/qml/qqmllanguage/data/singleton/qmldir
+++ b/tests/auto/qml/qqmllanguage/data/singleton/qmldir
@@ -1,3 +1,4 @@
singleton SingletonType SingletonType.qml
+singleton SingletonTypeWithIC SingletonTypeWithIC.qml
diff --git a/tests/auto/qml/qqmllanguage/data/singletonICTest.qml b/tests/auto/qml/qqmllanguage/data/singletonICTest.qml
new file mode 100644
index 0000000000..d0d3b079be
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/singletonICTest.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.0
+import "singleton" as MySingleton
+
+Item {
+ property MySingleton.SingletonTypeWithIC.IC1 singleton1: MySingleton.SingletonTypeWithIC.IC1 {};
+}
diff --git a/tests/auto/qml/qqmllanguage/data/unsupportedProperty.errors.txt b/tests/auto/qml/qqmllanguage/data/unsupportedProperty.errors.txt
index 3cd626de86..b45c320c20 100644
--- a/tests/auto/qml/qqmllanguage/data/unsupportedProperty.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/unsupportedProperty.errors.txt
@@ -1 +1 @@
-3:13:Invalid property assignment: unsupported type "QMatrix"
+3:16:Invalid property assignment: unsupported type "QTransform"
diff --git a/tests/auto/qml/qqmllanguage/data/unsupportedProperty.qml b/tests/auto/qml/qqmllanguage/data/unsupportedProperty.qml
index 9f19680368..ec8171dd2c 100644
--- a/tests/auto/qml/qqmllanguage/data/unsupportedProperty.qml
+++ b/tests/auto/qml/qqmllanguage/data/unsupportedProperty.qml
@@ -1,4 +1,4 @@
import Test 1.0
MyQmlObject {
- matrix: "1,0,0,0,1,0,0,0,1"
+ transform: "1,0,0,0,1,0,0,0,1"
}
diff --git a/tests/auto/qml/qqmllanguage/qqmllanguage.pro b/tests/auto/qml/qqmllanguage/qqmllanguage.pro
index 724a27320c..6c54525544 100644
--- a/tests/auto/qml/qqmllanguage/qqmllanguage.pro
+++ b/tests/auto/qml/qqmllanguage/qqmllanguage.pro
@@ -1,4 +1,7 @@
-CONFIG += testcase
+CONFIG += testcase qmltypes
+QML_IMPORT_NAME = StaticTest
+QML_IMPORT_VERSION = 1.0
+
TARGET = tst_qqmllanguage
macx:CONFIG -= app_bundle
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index 6956533196..31a4135d89 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -57,7 +57,7 @@ void registerTypes()
qmlRegisterType<MyNamespace::MySecondNamespacedType>("Test",1,0,"MySecondNamespacedType");
qmlRegisterUncreatableMetaObject(MyNamespace::staticMetaObject, "Test", 1, 0, "MyNamespace", "Access to enums & flags only");
qmlRegisterType<MyParserStatus>("Test",1,0,"MyParserStatus");
- qmlRegisterType<MyGroupedObject>();
+ qmlRegisterAnonymousType<MyGroupedObject>("Test", 1);
qmlRegisterType<MyRevisionedClass>("Test",1,0,"MyRevisionedClass");
qmlRegisterType<MyRevisionedClass,1>("Test",1,1,"MyRevisionedClass");
qmlRegisterType<MyRevisionedIllegalOverload>("Test",1,0,"MyRevisionedIllegalOverload");
@@ -118,6 +118,10 @@ void registerTypes()
qmlRegisterType<LazyDeferredSubObject>("Test", 1, 0, "LazyDeferredSubObject");
qmlRegisterType<DeferredProperties>("Test", 1, 0, "DeferredProperties");
+
+ qmlRegisterTypesAndRevisions<Extended, Foreign, ForeignExtended>("Test", 1);
+ qmlRegisterTypesAndRevisions<BareSingleton>("Test", 1);
+ qmlRegisterTypesAndRevisions<UncreatableSingleton>("Test", 1);
}
QVariant myCustomVariantTypeConverter(const QString &data)
@@ -210,3 +214,9 @@ bool MyQmlObject::event(QEvent *event)
m_childAddedEventCount++;
return QObject::event(event);
}
+
+UncreatableSingleton *UncreatableSingleton::instance()
+{
+ static UncreatableSingleton instance;
+ return &instance;
+}
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index 1aab24841a..8852bf7af9 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -31,7 +31,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qrect.h>
#include <QtCore/qdatetime.h>
-#include <QtGui/qmatrix.h>
+#include <QtGui/qtransform.h>
#include <QtGui/qcolor.h>
#include <QtGui/qvector2d.h>
#include <QtGui/qvector3d.h>
@@ -104,7 +104,7 @@ class MyQmlObject : public QObject, public MyInterface
Q_PROPERTY(QString readOnlyString READ readOnlyString)
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled)
Q_PROPERTY(QRect rect READ rect WRITE setRect)
- Q_PROPERTY(QMatrix matrix READ matrix WRITE setMatrix) //assumed to be unsupported by QML
+ Q_PROPERTY(QTransform transform READ transform WRITE setTransform) //assumed to be unsupported by QML
Q_PROPERTY(MyInterface *interfaceProperty READ interface WRITE setInterface)
Q_PROPERTY(int onLiteralSignal READ onLiteralSignal WRITE setOnLiteralSignal)
Q_PROPERTY(MyCustomVariantType customType READ customType WRITE setCustomType)
@@ -129,8 +129,8 @@ public:
QRect rect() const { return QRect(); }
void setRect(const QRect&) {}
- QMatrix matrix() const { return QMatrix(); }
- void setMatrix(const QMatrix&) {}
+ QTransform transform() const { return QTransform(); }
+ void setTransform(const QTransform &) {}
MyInterface *interface() const { return m_interface; }
void setInterface(MyInterface *iface) { m_interface = iface; }
@@ -750,6 +750,47 @@ private:
bool m_ownRWObj;
};
+namespace MyStaticNamespace {
+ Q_NAMESPACE
+ QML_ELEMENT
+
+ enum MyNSEnum {
+ Key1 = 1,
+ Key2,
+ Key5 = 5
+ };
+ Q_ENUM_NS(MyNSEnum);
+
+ enum class MyOtherNSEnum {
+ OtherKey1 = 1,
+ OtherKey2
+ };
+ Q_ENUM_NS(MyOtherNSEnum);
+
+
+ class MyNamespacedType : public QObject
+ {
+ Q_OBJECT
+ Q_PROPERTY(MyStaticNamespace::MyNSEnum myEnum MEMBER m_myEnum)
+ QML_NAMED_ELEMENT(MyStaticNamespacedType)
+ MyStaticNamespace::MyNSEnum m_myEnum = MyNSEnum::Key1;
+ };
+
+ class MySecondNamespacedType : public QObject
+ {
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<MyStaticNamespace::MyNamespacedType> list READ list)
+ QML_NAMED_ELEMENT(MyStaticSecondNamespacedType)
+ public:
+ QQmlListProperty<MyNamespacedType> list()
+ {
+ return QQmlListProperty<MyNamespacedType>(this, &m_list);
+ }
+
+ private:
+ QList<MyNamespacedType *> m_list;
+ };
+}
namespace MyNamespace {
Q_NAMESPACE
@@ -1420,6 +1461,71 @@ public:
enum class OtherScopedEnum : int { ScopedVal1, ScopedVal2, ScopedVal3 };
};
+class Extension : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int extension READ extension CONSTANT)
+public:
+ Extension(QObject *parent = nullptr) : QObject(parent) {}
+ int extension() const { return 42; }
+};
+
+class Extended : public QObject
+{
+ Q_OBJECT
+ QML_EXTENDED(Extension)
+ QML_NAMED_ELEMENT(Extended)
+ Q_PROPERTY(int base READ base CONSTANT)
+
+public:
+ int base() const { return 43; }
+};
+
+class Local : public QObject
+{
+ Q_OBJECT
+};
+
+class Foreign
+{
+ Q_GADGET
+ QML_FOREIGN(Local)
+ QML_NAMED_ELEMENT(Foreign)
+};
+
+class ForeignExtended
+{
+ Q_GADGET
+ QML_FOREIGN(Local)
+ QML_NAMED_ELEMENT(ForeignExtended)
+ QML_EXTENDED(Extension)
+};
+
+class BareSingleton : public QObject
+{
+ Q_OBJECT
+ QML_SINGLETON
+ QML_ELEMENT
+
+public:
+ BareSingleton(QObject *parent = nullptr) : QObject(parent)
+ {
+ setObjectName("statically registered");
+ }
+};
+
+class UncreatableSingleton : public QObject
+{
+ Q_OBJECT
+ QML_SINGLETON
+ QML_ELEMENT
+
+public:
+ static UncreatableSingleton *instance();
+
+private:
+ UncreatableSingleton() { setObjectName("uncreatable"); }
+};
void registerTypes();
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 4a8ce77f92..5665775258 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -123,6 +123,7 @@ private slots:
void dynamicProperties();
void dynamicPropertiesNested();
void listProperties();
+ void listPropertiesInheritanceNoCrash();
void badListItemType();
void dynamicObjectProperties();
void dynamicSignalsAndSlots();
@@ -132,6 +133,9 @@ private slots:
void autoComponentCreation();
void autoComponentCreationInGroupProperty();
void propertyValueSource();
+ void requiredProperty();
+ void requiredPropertyFromCpp_data();
+ void requiredPropertyFromCpp();
void attachedProperties();
void dynamicObjects();
void customVariantTypes();
@@ -303,7 +307,28 @@ private slots:
void typeWrapperToVariant();
+ void extendedForeignTypes();
+
+ void inlineComponent();
+ void inlineComponent_data();
+ void inlineComponentReferenceCycle_data();
+ void inlineComponentReferenceCycle();
+ void nestedInlineComponentNotAllowed();
+ void inlineComponentStaticTypeResolution();
+ void inlineComponentInSingleton();
+ void nonExistingInlineComponent_data();
+ void nonExistingInlineComponent();
+ void inlineComponentFoundBeforeOtherImports();
+ void inlineComponentDuplicateNameError();
+
+ void selfReference();
+ void selfReferencingSingleton();
+
+ void listContainingDeletedObject();
+ void overrideSingleton();
+
void arrayToContainer();
+ void qualifiedScopeInCustomParser();
private:
QQmlEngine engine;
@@ -473,6 +498,11 @@ void tst_qqmllanguage::errors_data()
QTest::newRow("finalOverride") << "finalOverride.qml" << "finalOverride.errors.txt" << false;
QTest::newRow("customParserIdNotAllowed") << "customParserIdNotAllowed.qml" << "customParserIdNotAllowed.errors.txt" << false;
+ QTest::newRow("nullishCoalescing_LHS_Or") << "nullishCoalescing_LHS_Or.qml" << "nullishCoalescing_LHS_Or.errors.txt" << false;
+ QTest::newRow("nullishCoalescing_LHS_And") << "nullishCoalescing_LHS_And.qml" << "nullishCoalescing_LHS_And.errors.txt" << false;
+ QTest::newRow("nullishCoalescing_RHS_Or") << "nullishCoalescing_RHS_Or.qml" << "nullishCoalescing_RHS_Or.errors.txt" << false;
+ QTest::newRow("nullishCoalescing_RHS_And") << "nullishCoalescing_RHS_And.qml" << "nullishCoalescing_RHS_And.errors.txt" << false;
+
QTest::newRow("invalidGroupedProperty.1") << "invalidGroupedProperty.1.qml" << "invalidGroupedProperty.1.errors.txt" << false;
QTest::newRow("invalidGroupedProperty.2") << "invalidGroupedProperty.2.qml" << "invalidGroupedProperty.2.errors.txt" << false;
QTest::newRow("invalidGroupedProperty.3") << "invalidGroupedProperty.3.qml" << "invalidGroupedProperty.3.errors.txt" << false;
@@ -630,6 +660,8 @@ void tst_qqmllanguage::errors_data()
QTest::newRow("typeAnnotations.2") << "typeAnnotations.2.qml" << "typeAnnotations.2.errors.txt" << false;
QTest::newRow("propertyUnknownType") << "propertyUnknownType.qml" << "propertyUnknownType.errors.txt" << false;
+
+ QTest::newRow("selfInstantiation") << "SelfInstantiation.qml" << "SelfInstantiation.errors.txt" << false;
}
void tst_qqmllanguage::errors()
@@ -1462,6 +1494,16 @@ void tst_qqmllanguage::listProperties()
QCOMPARE(object->property("test").toInt(), 2);
}
+// Tests that initializing list properties of a base class does not crash
+// (QTBUG-82171)
+void tst_qqmllanguage::listPropertiesInheritanceNoCrash()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("listPropertiesChild.qml"));
+ QScopedPointer<QObject> object(component.create()); // should not crash
+ QVERIFY(object != nullptr);
+}
+
void tst_qqmllanguage::badListItemType()
{
QQmlComponent component(&engine, testFileUrl("badListItemType.qml"));
@@ -1636,6 +1678,120 @@ void tst_qqmllanguage::propertyValueSource()
}
}
+void tst_qqmllanguage::requiredProperty()
+{
+ QQmlEngine engine;
+ {
+ QQmlComponent component(&engine, testFileUrl("requiredProperties.1.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object);
+ }
+ {
+ QQmlComponent component(&engine, testFileUrl("requiredProperties.2.qml"));
+ QVERIFY(!component.errors().empty());
+ }
+ {
+ QQmlComponent component(&engine, testFileUrl("requiredProperties.4.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!component.errors().empty());
+ QVERIFY(component.errorString().contains("Required property objectName was not initialized"));
+ }
+ {
+ QQmlComponent component(&engine, testFileUrl("requiredProperties.3.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!component.errors().empty());
+ QVERIFY(component.errorString().contains("Required property i was not initialized"));
+ }
+ {
+ QQmlComponent component(&engine, testFileUrl("requiredProperties.5.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!component.errors().empty());
+ QVERIFY(component.errorString().contains("Required property i was not initialized"));
+ }
+ {
+ QQmlComponent component(&engine, testFileUrl("requiredProperties.6.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object);
+ }
+ {
+ QQmlComponent component(&engine, testFileUrl("requiredProperties.7.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!component.errors().empty());
+ QVERIFY(component.errorString().contains("Property blub was marked as required but does not exist"));
+ }
+}
+
+class MyClassWithRequiredProperty : public QObject
+{
+public:
+ Q_OBJECT
+ Q_PROPERTY(int test MEMBER m_test REQUIRED NOTIFY testChanged)
+ Q_SIGNAL void testChanged();
+private:
+ int m_test;
+};
+
+class ChildClassWithoutOwnRequired : public MyClassWithRequiredProperty
+{
+public:
+ Q_OBJECT
+ Q_PROPERTY(int test2 MEMBER m_test2 NOTIFY test2Changed)
+ Q_SIGNAL void test2Changed();
+private:
+ int m_test2;
+};
+
+class ChildClassWithOwnRequired : public MyClassWithRequiredProperty
+{
+public:
+ Q_OBJECT
+ Q_PROPERTY(int test2 MEMBER m_test2 REQUIRED NOTIFY test2Changed)
+ Q_SIGNAL void test2Changed();
+private:
+ int m_test2;
+};
+
+void tst_qqmllanguage::requiredPropertyFromCpp_data()
+{
+ qmlRegisterType<MyClassWithRequiredProperty>("example.org", 1, 0, "MyClass");
+ qmlRegisterType<ChildClassWithoutOwnRequired>("example.org", 1, 0, "Child");
+ qmlRegisterType<ChildClassWithOwnRequired>("example.org", 1, 0, "Child2");
+
+
+ QTest::addColumn<QUrl>("setFile");
+ QTest::addColumn<QUrl>("notSetFile");
+ QTest::addColumn<QString>("errorMessage");
+ QTest::addColumn<int>("expectedValue");
+
+ QTest::addRow("direct") << testFileUrl("cppRequiredProperty.qml") << testFileUrl("cppRequiredPropertyNotSet.qml") << QString(":4 Required property test was not initialized\n") << 42;
+ QTest::addRow("in parent") << testFileUrl("cppRequiredPropertyInParent.qml") << testFileUrl("cppRequiredPropertyInParentNotSet.qml") << QString(":4 Required property test was not initialized\n") << 42;
+ QTest::addRow("in child and parent") << testFileUrl("cppRequiredPropertyInChildAndParent.qml") << testFileUrl("cppRequiredPropertyInChildAndParentNotSet.qml") << QString(":4 Required property test2 was not initialized\n") << 18;
+}
+
+void tst_qqmllanguage::requiredPropertyFromCpp()
+{
+ QQmlEngine engine;
+ QFETCH(QUrl, setFile);
+ QFETCH(QUrl, notSetFile);
+ QFETCH(QString, errorMessage);
+ QFETCH(int, expectedValue);
+ {
+ QQmlComponent comp(&engine, notSetFile);
+ QScopedPointer<QObject> o { comp.create() };
+ QVERIFY(o.isNull());
+ QVERIFY(comp.isError());
+ QCOMPARE(comp.errorString(), notSetFile.toString() + errorMessage);
+ }
+ {
+ QQmlComponent comp(&engine, setFile);
+ QScopedPointer<QObject> o { comp.create() };
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("test").toInt(), expectedValue);
+ }
+}
+
void tst_qqmllanguage::attachedProperties()
{
QQmlComponent component(&engine, testFileUrl("attachedProperties.qml"));
@@ -1704,21 +1860,30 @@ void tst_qqmllanguage::valueTypes()
void tst_qqmllanguage::cppnamespace()
{
- {
- QQmlComponent component(&engine, testFileUrl("cppnamespace.qml"));
+ QScopedPointer<QObject> object;
+
+ auto create = [&](const char *file) {
+ QQmlComponent component(&engine, testFileUrl(file));
VERIFY_ERRORS(0);
- QScopedPointer<QObject> object(component.create());
+ object.reset(component.create());
QVERIFY(object != nullptr);
+ };
- QCOMPARE(object->property("intProperty").toInt(), (int)MyNamespace::MyOtherNSEnum::OtherKey2);
- }
+ auto createAndCheck = [&](const char *file) {
+ create(file);
+ return !QTest::currentTestFailed();
+ };
- {
- QQmlComponent component(&engine, testFileUrl("cppnamespace.2.qml"));
- VERIFY_ERRORS(0);
- QScopedPointer<QObject> object(component.create());
- QVERIFY(object != nullptr);
- }
+ QVERIFY(createAndCheck("cppnamespace.qml"));
+ QCOMPARE(object->property("intProperty").toInt(),
+ (int)MyNamespace::MyOtherNSEnum::OtherKey2);
+
+ QVERIFY(createAndCheck("cppstaticnamespace.qml"));
+ QCOMPARE(object->property("intProperty").toInt(),
+ (int)MyStaticNamespace::MyOtherNSEnum::OtherKey2);
+
+ QVERIFY(createAndCheck("cppnamespace.2.qml"));
+ QVERIFY(createAndCheck("cppstaticnamespace.2.qml"));
}
void tst_qqmllanguage::aliasProperties()
@@ -1936,7 +2101,6 @@ void tst_qqmllanguage::aliasProperties()
// "Nested" aliases within an object that require iterative resolution
{
- // This is known to fail at the moment.
QQmlComponent component(&engine, testFileUrl("alias.14.qml"));
VERIFY_ERRORS(0);
@@ -2035,6 +2199,11 @@ void tst_qqmllanguage::aliasProperties()
auto text = myText->property("text").toString();
QCOMPARE(text, "alias:\n20");
}
+
+ {
+ QQmlComponent component(&engine, testFileUrl("alias.18.qml"));
+ VERIFY_ERRORS("alias.18.errors.txt");
+ }
}
// QTBUG-13374 Test that alias properties and signals can coexist
@@ -2294,20 +2463,31 @@ void tst_qqmllanguage::scriptStringJs()
QVERIFY(!object->scriptProperty().booleanLiteral(&ok) && !ok);
}
+struct FreeUnitData
+{
+ static void cleanup(const QV4::CompiledData::Unit *readOnlyQmlUnit)
+ {
+ if (readOnlyQmlUnit && !(readOnlyQmlUnit->flags & QV4::CompiledData::Unit::StaticData))
+ free(const_cast<QV4::CompiledData::Unit *>(readOnlyQmlUnit));
+ }
+};
+
void tst_qqmllanguage::scriptStringWithoutSourceCode()
{
QUrl url = testFileUrl("scriptString7.qml");
+ QScopedPointer<const QV4::CompiledData::Unit, FreeUnitData> readOnlyQmlUnit;
{
QQmlEnginePrivate *eng = QQmlEnginePrivate::get(&engine);
QQmlRefPointer<QQmlTypeData> td = eng->typeLoader.getType(url);
Q_ASSERT(td);
- const QV4::CompiledData::Unit *readOnlyQmlUnit = td->compilationUnit()->unitData();
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit = td->compilationUnit();
+ readOnlyQmlUnit.reset(compilationUnit->unitData());
Q_ASSERT(readOnlyQmlUnit);
QV4::CompiledData::Unit *qmlUnit = reinterpret_cast<QV4::CompiledData::Unit *>(malloc(readOnlyQmlUnit->unitSize));
- memcpy(qmlUnit, readOnlyQmlUnit, readOnlyQmlUnit->unitSize);
+ memcpy(qmlUnit, readOnlyQmlUnit.data(), readOnlyQmlUnit->unitSize);
+
qmlUnit->flags &= ~QV4::CompiledData::Unit::StaticData;
- QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit = td->compilationUnit();
compilationUnit->setUnitData(qmlUnit);
const QV4::CompiledData::Object *rootObject = compilationUnit->objectAt(/*root object*/0);
@@ -2743,12 +2923,12 @@ void tst_qqmllanguage::importsLocal_data()
QTest::newRow("local import QTBUG-7721 A")
<< "subdir.Test {}" // no longer allowed (QTBUG-7721)
<< ""
- << "subdir.Test - subdir is not a namespace";
+ << "subdir.Test - subdir is neither a type nor a namespace";
QTest::newRow("local import QTBUG-7721 B")
<< "import \"subdir\" as X\n"
"X.subsubdir.SubTest {}" // no longer allowed (QTBUG-7721)
<< ""
- << "X.subsubdir.SubTest - nested namespaces not allowed";
+ << "X.subsubdir.SubTest - subsubdir is not a type";
QTest::newRow("local import as")
<< "import \"subdir\" as T\n"
"T.Test {}"
@@ -4709,11 +4889,13 @@ static void beginDeferredOnce(QQmlEnginePrivate *enginePriv,
typedef QMultiHash<int, const QV4::CompiledData::Binding *> QV4PropertyBindingHash;
auto it = std::reverse_iterator<QV4PropertyBindingHash::iterator>(range.second);
auto last = std::reverse_iterator<QV4PropertyBindingHash::iterator>(range.first);
+ state->creator->beginPopulateDeferred(deferData->context);
while (it != last) {
- if (!state->creator->populateDeferredBinding(property, deferData, *it))
- state->errors << state->creator->errors;
+ state->creator->populateDeferredBinding(property, deferData->deferredIdx, *it);
++it;
}
+ state->creator->finalizePopulateDeferred();
+ state->errors << state->creator->errors;
deferredState->constructionStates += state;
@@ -4938,24 +5120,24 @@ void tst_qqmllanguage::instanceof_data()
// assert that basic types don't convert to QObject
QTest::newRow("1 instanceof QtObject")
<< testFileUrl("instanceof_qtqml.qml")
- << QVariant("TypeError: Type error");
+ << QVariant(false);
QTest::newRow("true instanceof QtObject")
<< testFileUrl("instanceof_qtqml.qml")
- << QVariant("TypeError: Type error");
+ << QVariant(false);
QTest::newRow("\"foobar\" instanceof QtObject")
<< testFileUrl("instanceof_qtqml.qml")
- << QVariant("TypeError: Type error");
+ << QVariant(false);
// assert that Managed don't either
QTest::newRow("new String(\"foobar\") instanceof QtObject")
<< testFileUrl("instanceof_qtqml.qml")
- << QVariant("TypeError: Type error");
+ << QVariant(false);
QTest::newRow("new Object() instanceof QtObject")
<< testFileUrl("instanceof_qtqml.qml")
- << QVariant("TypeError: Type error");
+ << QVariant(false);
QTest::newRow("new Date() instanceof QtObject")
<< testFileUrl("instanceof_qtqml.qml")
- << QVariant("TypeError: Type error");
+ << QVariant(false);
// test that simple QtQml comparisons work
QTest::newRow("qtobjectInstance instanceof QtObject")
@@ -5240,29 +5422,341 @@ void tst_qqmllanguage::typeWrapperToVariant()
QVERIFY(target);
}
+void tst_qqmllanguage::extendedForeignTypes()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("foreignExtended.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("extendedBase").toInt(), 43);
+ QCOMPARE(o->property("extendedExtension").toInt(), 42);
+ QCOMPARE(o->property("foreignExtendedExtension").toInt(), 42);
+ QCOMPARE(o->property("foreignObjectName").toString(), QLatin1String("foreign"));
+ QCOMPARE(o->property("foreignExtendedObjectName").toString(), QLatin1String("foreignExtended"));
+}
+
+void tst_qqmllanguage::selfReference()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("SelfReference.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+
+ QQmlComponentPrivate *componentPrivate = QQmlComponentPrivate::get(&component);
+ auto compilationUnit = componentPrivate->compilationUnit;
+ QVERIFY(compilationUnit);
+
+ const QMetaObject *metaObject = o->metaObject();
+ QMetaProperty selfProperty = metaObject->property(metaObject->indexOfProperty("self"));
+ QCOMPARE(selfProperty.userType(), compilationUnit->metaTypeId);
+
+ QByteArray typeName = selfProperty.typeName();
+ QVERIFY(typeName.endsWith('*'));
+ typeName = typeName.chopped(1);
+ QCOMPARE(typeName, metaObject->className());
+
+ QMetaMethod selfFunction = metaObject->method(metaObject->indexOfMethod("returnSelf()"));
+ QVERIFY(selfFunction.isValid());
+ QCOMPARE(selfFunction.returnType(), compilationUnit->metaTypeId);
+
+ QMetaMethod selfSignal;
+
+ for (int i = metaObject->methodOffset(); i < metaObject->methodCount(); ++i) {
+ QMetaMethod method = metaObject->method(i);
+ if (method.isValid() && method.name().startsWith("blah")) {
+ selfSignal = method;
+ break;
+ }
+ }
+
+ QVERIFY(selfSignal.isValid());
+ QCOMPARE(selfSignal.parameterCount(), 1);
+ QCOMPARE(selfSignal.parameterType(0), compilationUnit->metaTypeId);
+}
+
+void tst_qqmllanguage::selfReferencingSingleton()
+{
+ QQmlEngine engine;
+ engine.addImportPath(dataDirectory());
+
+ QPointer<QObject> singletonPointer;
+ {
+ QQmlComponent component(&engine);
+ component.setData(QByteArray(R"(import QtQml 2.0
+ import selfreferencingsingletonmodule 1.0
+ QtObject {
+ property SelfReferencingSingleton singletonPointer: SelfReferencingSingleton
+ })"), QUrl());
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+ singletonPointer = o->property("singletonPointer").value<QObject*>();
+ }
+
+ QVERIFY(!singletonPointer.isNull());
+ QCOMPARE(singletonPointer->property("dummy").toInt(), 42);
+}
+
+void tst_qqmllanguage::listContainingDeletedObject()
+{
+ QQmlEngine engine;
+ auto url = testFileUrl("listContainingDeleted.qml");
+ const QString message = url.toString() + ":24: TypeError: Cannot read property 'enabled' of null";
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, message.toUtf8().data());
+ QQmlComponent comp(&engine, url);
+ QScopedPointer<QObject> root(comp.create());
+ QVERIFY(root);
+
+ auto cmp = root->property("a").value<QQmlComponent*>();
+ auto o = cmp->create();
+
+ QMetaObject::invokeMethod(root.get(), "doAssign", Q_ARG(QVariant, QVariant::fromValue(o)));
+ delete o;
+ QMetaObject::invokeMethod(root.get(), "use");
+
+}
+
+void tst_qqmllanguage::overrideSingleton()
+{
+ auto check = [](const QString &name, const QByteArray &singletonElement) {
+ const QByteArray testQml = "import Test 1.0\n"
+ "import QtQml 2.0\n"
+ "QtObject { objectName: " + singletonElement + ".objectName }";
+ QQmlEngine engine;
+ QQmlComponent component(&engine, nullptr);
+ component.setData(testQml, QUrl("singleton.qml"));
+ QVERIFY(component.isReady());
+ QScopedPointer<QObject> obj(component.create());
+ QCOMPARE(obj->objectName(), name);
+ };
+
+ check("statically registered", "BareSingleton");
+
+ BareSingleton singleton;
+ singleton.setObjectName("dynamically registered");
+ qmlRegisterSingletonInstance("Test", 1, 0, "BareSingleton", &singleton);
+
+ check("dynamically registered", "BareSingleton");
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "singleton.qml:3: TypeError: Cannot read property 'objectName' of undefined");
+ check("", "UncreatableSingleton");
+
+ qmlRegisterSingletonInstance("Test", 1, 0, "UncreatableSingleton",
+ UncreatableSingleton::instance());
+ check("uncreatable", "UncreatableSingleton");
+}
+
+void tst_qqmllanguage::inlineComponent()
+{
+ QFETCH(QUrl, componentUrl);
+ QFETCH(QColor, color);
+ QFETCH(int, width);
+ QQmlEngine engine;
+ QQmlComponent component(&engine, componentUrl);
+ QScopedPointer<QObject> o(component.create());
+ if (component.isError()) {
+ qDebug() << component.errorString();
+ }
+ QVERIFY(!o.isNull());
+ auto icInstance = o->findChild<QObject *>("icInstance");
+ QVERIFY(icInstance);
+ QCOMPARE(icInstance->property("color").value<QColor>(),color);
+ QCOMPARE(icInstance->property("width").value<qreal>(), width);
+}
+
+void tst_qqmllanguage::inlineComponent_data()
+{
+ QTest::addColumn<QUrl>("componentUrl");
+ QTest::addColumn<QColor>("color");
+ QTest::addColumn<int>("width");
+
+ QTest::newRow("Usage from other component") << testFileUrl("inlineComponentUser1.qml") << QColorConstants::Blue << 24;
+ QTest::newRow("Reexport") << testFileUrl("inlineComponentUser2.qml") << QColorConstants::Svg::green << 24;
+ QTest::newRow("Usage in same component") << testFileUrl("inlineComponentUser3.qml") << QColorConstants::Blue << 24;
+
+ QTest::newRow("Resolution happens at instantiation") << testFileUrl("inlineComponentUser4.qml") << QColorConstants::Blue << 24;
+ QTest::newRow("Non-toplevel IC is found") << testFileUrl("inlineComponentUser5.qml") << QColorConstants::Svg::red << 24;
+
+ QTest::newRow("Resolved in correct order") << testFileUrl("inlineComponentOrder.qml") << QColorConstants::Blue << 200;
+
+ QTest::newRow("ID resolves correctly") << testFileUrl("inlineComponentWithId.qml") << QColorConstants::Svg::red << 42;
+ QTest::newRow("Alias resolves correctly") << testFileUrl("inlineComponentWithAlias.qml") << QColorConstants::Svg::lime << 42;
+}
+
+void tst_qqmllanguage::inlineComponentReferenceCycle_data()
+{
+ QTest::addColumn<QUrl>("componentUrl");
+
+ QTest::newRow("Simple cycle") << testFileUrl("icSimpleCycle.qml");
+ QTest::newRow("Via property") << testFileUrl("icCycleViaProperty.qml");
+}
+
+void tst_qqmllanguage::inlineComponentReferenceCycle()
+{
+ QFETCH(QUrl, componentUrl);
+ QQmlEngine engine;
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, "QQmlComponent: Component is not ready");
+ QQmlComponent component(&engine, componentUrl);
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(o.isNull());
+ QVERIFY(component.isError());
+ QCOMPARE(component.errorString(), componentUrl.toString() + QLatin1String(":-1 Inline components form a cycle!\n"));
+}
+
+void tst_qqmllanguage::nestedInlineComponentNotAllowed()
+{
+ QQmlEngine engine;
+ auto url = testFileUrl("nestedIC.qml");
+ QQmlComponent component(&engine, url);
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, "QQmlComponent: Component is not ready");
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(component.isError());
+ QCOMPARE(component.errorString(), QLatin1String("%1:%2").arg(url.toString(), QLatin1String("5 Nested inline components are not supported\n")));
+}
+
+void tst_qqmllanguage::inlineComponentStaticTypeResolution()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("InlineComponentChild.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("i").toInt(), 42);
+}
+
+void tst_qqmllanguage::inlineComponentInSingleton()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("singletonICTest.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+ auto untyped = o->property("singleton1");
+ QVERIFY(untyped.isValid());
+ auto singleton1 = untyped.value<QObject*>();
+ QVERIFY(singleton1);
+ QCOMPARE(singleton1->property("iProp").value<int>(), 42);
+ QCOMPARE(singleton1->property("sProp").value<QString>(), QString::fromLatin1("Hello, world"));
+ QVERIFY(!o.isNull());
+}
+
+void tst_qqmllanguage::nonExistingInlineComponent_data()
+{
+ QTest::addColumn<QUrl>("componentUrl");
+ QTest::addColumn<QString>("errorMessage");
+ QTest::addColumn<int>("line");
+ QTest::addColumn<int>("column");
+
+ QTest::newRow("Property type") << testFileUrl("nonExistingICUser1.qml") << QString("Type InlineComponentProvider has no inline component type called NonExisting") << 4 << 5;
+ QTest::newRow("Instantiation") << testFileUrl("nonExistingICUser2.qml") << QString("Type InlineComponentProvider has no inline component type called NotExisting") << 4 << 5;
+ QTest::newRow("Inheritance") << testFileUrl("nonExistingICUser3.qml") << QString("Type InlineComponentProvider has no inline component type called NotExisting") << 3 << 1;
+ QTest::newRow("From singleton") << testFileUrl("nonExistingICUser4.qml") << QString("Type MySingleton.SingletonTypeWithIC has no inline component type called NonExisting") << 5 << 5;
+
+ QTest::newRow("Cannot access parent inline components from child") << testFileUrl("nonExistingICUser5.qml") << QString("Type InlineComponentProviderChild has no inline component type called StyledRectangle") << 4 << 5;
+}
+
+void tst_qqmllanguage::nonExistingInlineComponent()
+{
+ QFETCH(QUrl, componentUrl);
+ QFETCH(QString, errorMessage);
+ QFETCH(int, line);
+ QFETCH(int, column);
+ QQmlEngine engine;
+ QQmlComponent component(&engine, componentUrl);
+ auto errors = component.errors();
+ QCOMPARE(errors.size(), 1);
+ const auto &error = errors.first();
+ QCOMPARE(error.description(), errorMessage);
+ QCOMPARE(error.line(), line);
+ QCOMPARE(error.column(), column);
+}
+
+void tst_qqmllanguage::inlineComponentFoundBeforeOtherImports()
+{
+ QQmlEngine engine;
+ QUrl url = testFileUrl("inlineComponentFoundBeforeOtherImports.qml");
+ QQmlComponent component(&engine, url);
+
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "Created");
+ QScopedPointer<QObject> root {component.create()};
+}
+
+void tst_qqmllanguage::inlineComponentDuplicateNameError()
+{
+ QQmlEngine engine;
+ QUrl url = testFileUrl("inlineComponentDuplicateName.qml");
+ QQmlComponent component(&engine, url);
+
+ QString message = QLatin1String("%1:5 Inline component names must be unique per file\n").arg(url.toString());
+ QScopedPointer<QObject> root {component.create()};
+ QVERIFY(root.isNull());
+ QVERIFY(component.isError());
+ QCOMPARE(component.errorString(), message);
+}
+
class TestItem : public QObject
{
Q_OBJECT
Q_PROPERTY( QVector<QPointF> positions MEMBER m_points )
+ Q_PROPERTY( QSet<QByteArray> barrays MEMBER m_barrays )
public:
TestItem() = default;
QVector< QPointF > m_points;
+ QSet<QByteArray> m_barrays;
};
Q_DECLARE_METATYPE(QVector<QPointF>);
+Q_DECLARE_METATYPE(QSet<QByteArray>);
void tst_qqmllanguage::arrayToContainer()
{
QQmlEngine engine;
qmlRegisterType<TestItem>("qt.test", 1, 0, "TestItem");
QVector<QPointF> points { QPointF (2.0, 3.0) };
+ QSet<QByteArray> barrays { QByteArray("hello"), QByteArray("world") };
engine.rootContext()->setContextProperty("test", QVariant::fromValue(points));
QQmlComponent component(&engine, testFileUrl("arrayToContainer.qml"));
VERIFY_ERRORS(0);
- QScopedPointer<TestItem> root(qobject_cast<TestItem *>(component.createWithInitialProperties( {{"vector", QVariant::fromValue(points)}} )));
+ QScopedPointer<TestItem> root(qobject_cast<TestItem *>(component.createWithInitialProperties( {{"vector", QVariant::fromValue(points)}, {"myset", QVariant::fromValue(barrays)} } )));
QVERIFY(root);
QCOMPARE(root->m_points.at(0), QPointF (2.0, 3.0) );
+ QVERIFY(root->m_barrays.contains("hello"));
+ QVERIFY(root->m_barrays.contains("world"));
+}
+
+class EnumTester : public QObject
+{
+ Q_OBJECT
+public:
+ enum Types
+ {
+ FIRST = 0,
+ SECOND,
+ THIRD
+ };
+ Q_ENUM(Types)
+};
+
+void tst_qqmllanguage::qualifiedScopeInCustomParser()
+{
+ qmlRegisterUncreatableType<EnumTester>("scoped.custom.test", 1, 0, "EnumTester",
+ "Object only creatable in C++");
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData("import QtQml.Models 2.12\n"
+ "import scoped.custom.test 1.0 as BACKEND\n"
+ "ListModel {\n"
+ " ListElement { text: \"a\"; type: BACKEND.EnumTester.FIRST }\n"
+ "}\n", QUrl());
+ QVERIFY(component.isReady());
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
}
QTEST_MAIN(tst_qqmllanguage)
diff --git a/tests/auto/qml/qqmllistmodel/qqmllistmodel.pro b/tests/auto/qml/qqmllistmodel/qqmllistmodel.pro
index 4d44d6b22b..c0808f8599 100644
--- a/tests/auto/qml/qqmllistmodel/qqmllistmodel.pro
+++ b/tests/auto/qml/qqmllistmodel/qqmllistmodel.pro
@@ -8,4 +8,4 @@ include (../../shared/util.pri)
TESTDATA = data/*
-QT += core-private gui-private qml-private quick-private testlib qmlmodels-private
+QT += core-private gui-private qml-private quick-private testlib qmlmodels-private
diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
index 75a932b6f4..d54e3467b7 100644
--- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
+++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
@@ -700,7 +700,7 @@ void tst_qqmllistmodel::error_data()
QTest::newRow("unknown qualified ListElement not allowed")
<< "import QtQuick 2.0\nListModel { Foo.ListElement { a: 123 } }"
- << "Foo.ListElement - Foo is not a namespace";
+ << "Foo.ListElement - Foo is neither a type nor a namespace";
}
void tst_qqmllistmodel::error()
diff --git a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
index 199f7bc7e4..e25d555d61 100644
--- a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
+++ b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
@@ -45,6 +45,9 @@ class tst_qqmllistreference : public QQmlDataTest
public:
tst_qqmllistreference() {}
+private:
+ void modeData();
+
private slots:
void initTestCase();
void qmllistreference();
@@ -56,12 +59,19 @@ private slots:
void canAt();
void canClear();
void canCount();
+ void canReplace();
+ void canRemoveLast();
void isReadable();
void isManipulable();
void append();
void at();
+ void clear_data() { modeData(); }
void clear();
void count();
+ void replace_data() { modeData(); }
+ void replace();
+ void removeLast_data() { modeData(); }
+ void removeLast();
void copy();
void qmlmetaproperty();
void engineTypes();
@@ -76,7 +86,67 @@ class TestType : public QObject
Q_PROPERTY(int intProperty READ intProperty)
public:
- TestType() : property(this, data) {}
+ enum Mode {
+ SyntheticClear,
+ SyntheticReplace,
+ SyntheticClearAndReplace,
+ SyntheticRemoveLast,
+ SyntheticRemoveLastAndReplace,
+ AutomaticReference,
+ AutomaticPointer
+ };
+
+ static void append(QQmlListProperty<TestType> *p, TestType *v) {
+ reinterpret_cast<QList<TestType *> *>(p->data)->append(v);
+ }
+ static int count(QQmlListProperty<TestType> *p) {
+ return reinterpret_cast<QList<TestType *> *>(p->data)->count();
+ }
+ static TestType *at(QQmlListProperty<TestType> *p, int idx) {
+ return reinterpret_cast<QList<TestType *> *>(p->data)->at(idx);
+ }
+ static void clear(QQmlListProperty<TestType> *p) {
+ return reinterpret_cast<QList<TestType *> *>(p->data)->clear();
+ }
+ static void replace(QQmlListProperty<TestType> *p, int idx, TestType *v) {
+ return reinterpret_cast<QList<TestType *> *>(p->data)->replace(idx, v);
+ }
+ static void removeLast(QQmlListProperty<TestType> *p) {
+ return reinterpret_cast<QList<TestType *> *>(p->data)->removeLast();
+ }
+
+ TestType(Mode mode = AutomaticReference)
+ {
+ switch (mode) {
+ case SyntheticClear:
+ property = QQmlListProperty<TestType>(this, &data, append, count, at, nullptr,
+ replace, removeLast);
+ break;
+ case SyntheticReplace:
+ property = QQmlListProperty<TestType>(this, &data, append, count, at, clear,
+ nullptr, removeLast);
+ break;
+ case SyntheticClearAndReplace:
+ property = QQmlListProperty<TestType>(this, &data, append, count, at, nullptr,
+ nullptr, removeLast);
+ break;
+ case SyntheticRemoveLast:
+ property = QQmlListProperty<TestType>(this, &data, append, count, at, clear,
+ replace, nullptr);
+ break;
+ case SyntheticRemoveLastAndReplace:
+ property = QQmlListProperty<TestType>(this, &data, append, count, at, clear,
+ nullptr, nullptr);
+ break;
+ case AutomaticReference:
+ property = QQmlListProperty<TestType>(this, data);
+ break;
+ case AutomaticPointer:
+ property = QQmlListProperty<TestType>(this, &data);
+ break;
+ }
+ }
+
QQmlListProperty<TestType> dataProperty() { return property; }
int intProperty() const { return 10; }
@@ -84,10 +154,24 @@ public:
QQmlListProperty<TestType> property;
};
+Q_DECLARE_METATYPE(TestType::Mode)
+
+void tst_qqmllistreference::modeData()
+{
+ QTest::addColumn<TestType::Mode>("mode");
+ QTest::addRow("AutomaticReference") << TestType::AutomaticReference;
+ QTest::addRow("AutomaticPointer") << TestType::AutomaticPointer;
+ QTest::addRow("SyntheticClear") << TestType::SyntheticClear;
+ QTest::addRow("SyntheticReplace") << TestType::SyntheticReplace;
+ QTest::addRow("SyntheticClearAndReplace") << TestType::SyntheticClearAndReplace;
+ QTest::addRow("SyntheticRemoveLast") << TestType::SyntheticRemoveLast;
+ QTest::addRow("SyntheticRemoveLastAndReplace") << TestType::SyntheticRemoveLastAndReplace;
+}
+
void tst_qqmllistreference::initTestCase()
{
QQmlDataTest::initTestCase();
- qmlRegisterType<TestType>();
+ qmlRegisterAnonymousType<TestType>("Test", 1);
}
void tst_qqmllistreference::qmllistreference()
@@ -340,6 +424,64 @@ void tst_qqmllistreference::canCount()
}
}
+void tst_qqmllistreference::canReplace()
+{
+ QScopedPointer<TestType> tt(new TestType);
+
+ {
+ QQmlListReference ref;
+ QVERIFY(!ref.canReplace());
+ }
+
+ {
+ QQmlListReference ref(tt.data(), "blah");
+ QVERIFY(!ref.canReplace());
+ }
+
+ {
+ QQmlListReference ref(tt.data(), "data");
+ QVERIFY(ref.canReplace());
+ tt.reset();
+ QVERIFY(!ref.canReplace());
+ }
+
+ {
+ TestType tt;
+ tt.property.replace = nullptr;
+ QQmlListReference ref(&tt, "data");
+ QVERIFY(!ref.canReplace());
+ }
+}
+
+void tst_qqmllistreference::canRemoveLast()
+{
+ QScopedPointer<TestType> tt(new TestType);
+
+ {
+ QQmlListReference ref;
+ QVERIFY(!ref.canRemoveLast());
+ }
+
+ {
+ QQmlListReference ref(tt.data(), "blah");
+ QVERIFY(!ref.canRemoveLast());
+ }
+
+ {
+ QQmlListReference ref(tt.data(), "data");
+ QVERIFY(ref.canRemoveLast());
+ tt.reset();
+ QVERIFY(!ref.canRemoveLast());
+ }
+
+ {
+ TestType tt;
+ tt.property.removeLast = nullptr;
+ QQmlListReference ref(&tt, "data");
+ QVERIFY(!ref.canRemoveLast());
+ }
+}
+
void tst_qqmllistreference::isReadable()
{
TestType *tt = new TestType;
@@ -474,7 +616,8 @@ void tst_qqmllistreference::at()
void tst_qqmllistreference::clear()
{
- TestType *tt = new TestType;
+ QFETCH(TestType::Mode, mode);
+ TestType *tt = new TestType(mode);
tt->data.append(tt);
tt->data.append(0);
tt->data.append(tt);
@@ -540,6 +683,70 @@ void tst_qqmllistreference::count()
}
}
+void tst_qqmllistreference::replace()
+{
+ QFETCH(TestType::Mode, mode);
+ QScopedPointer<TestType> tt(new TestType(mode));
+ tt->data.append(tt.get());
+ tt->data.append(nullptr);
+ tt->data.append(tt.get());
+
+ {
+ QQmlListReference ref(tt.get(), "data");
+ QVERIFY(ref.replace(1, tt.get()));
+ QCOMPARE(ref.at(1), tt.get());
+ QVERIFY(ref.replace(2, nullptr));
+ QCOMPARE(ref.at(2), nullptr);
+ QCOMPARE(ref.count(), 3);
+ tt.reset();
+ QVERIFY(!ref.replace(0, tt.get()));
+ }
+
+ {
+ TestType tt;
+ tt.data.append(&tt);
+ tt.property.replace = nullptr;
+ QQmlListReference ref(&tt, "data");
+ QVERIFY(!ref.replace(0, nullptr));
+ }
+}
+
+void tst_qqmllistreference::removeLast()
+{
+ QFETCH(TestType::Mode, mode);
+ QScopedPointer<TestType> tt(new TestType(mode));
+ tt->data.append(tt.get());
+ tt->data.append(nullptr);
+ tt->data.append(tt.get());
+
+ {
+ QQmlListReference ref;
+ QVERIFY(!ref.removeLast());
+ }
+
+ {
+ QQmlListReference ref(tt.get(), "blah");
+ QVERIFY(!ref.removeLast());
+ }
+
+ {
+ QQmlListReference ref(tt.get(), "data");
+ QCOMPARE(tt->data.count(), 3);
+ QVERIFY(ref.removeLast());
+ QCOMPARE(tt->data.count(), 2);
+ tt.reset();
+ QVERIFY(!ref.removeLast());
+ }
+
+ {
+ TestType tt;
+ tt.property.removeLast = nullptr;
+ QQmlListReference ref(&tt, "data");
+ ref.append(&tt);
+ QVERIFY(!ref.removeLast());
+ }
+}
+
void tst_qqmllistreference::copy()
{
TestType tt;
diff --git a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
index a90749208c..e3094db708 100644
--- a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
+++ b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
@@ -102,6 +102,7 @@ private slots:
void numberFromLocaleString_data();
void numberFromLocaleString();
void numberConstToLocaleString();
+ void numberOptions();
void stringLocaleCompare_data();
void stringLocaleCompare();
@@ -448,7 +449,7 @@ void tst_qqmllocale::firstDayOfWeek()
Q_ARG(QVariant, QVariant(locale)));
QVariant val = obj->property("firstDayOfWeek");
- QCOMPARE(val.type(), QVariant::Int);
+ QCOMPARE(val.userType(), QMetaType::Int);
int day = int(QLocale(locale).firstDayOfWeek());
if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday)
@@ -1157,6 +1158,35 @@ void tst_qqmllocale::numberConstToLocaleString()
QCOMPARE(obj->property("const2").toString(), l.toString(1234., 'f', 2));
}
+void tst_qqmllocale::numberOptions()
+{
+ QQmlEngine engine;
+ QQmlComponent comp(&engine);
+ comp.setData(R"(
+ import QtQml 2.15
+ QtObject {
+ id: root
+ property string formatted
+ property bool caughtException: false
+ Component.onCompleted: () => {
+ const myLocale = Qt.locale("de_DE")
+ myLocale.numberOptions = Locale.OmitGroupSeparator | Locale.RejectTrailingZeroesAfterDot
+ root.formatted = Number(10000).toLocaleString(myLocale, 'f', 4)
+ try {
+ Number.fromLocaleString(myLocale, "1,10");
+ } catch (e) {console.warn(e); root.caughtException = true}
+ }
+ }
+ )", QUrl("testdata"));
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, "Error: Locale: Number.fromLocaleString(): Invalid format");
+ QScopedPointer<QObject> root {comp.create()};
+ qDebug() << comp.errorString();
+ QVERIFY(root);
+ QCOMPARE(root->property("formatted").toString(), QLatin1String("10000,0000"));
+ QCOMPARE(root->property("caughtException").toBool(), true);
+
+}
+
void tst_qqmllocale::stringLocaleCompare_data()
{
QTest::addColumn<QString>("string1");
diff --git a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
index ea157a7d15..b21d2a908d 100644
--- a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
+++ b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
@@ -112,9 +112,9 @@ void tst_QQmlMetaObject::property_data()
QTest::newRow("date") << "property.date.qml"
<< QByteArray("QDateTime") << int(QMetaType::QDateTime)
<< false // default
- << QVariant(QDateTime(QDate(2012, 2, 7)))
+ << QVariant(QDate(2012, 2, 7).startOfDay())
<< true // writable
- << QVariant(QDateTime(QDate(2010, 7, 2)));
+ << QVariant(QDate(2010, 7, 2).startOfDay());
QTest::newRow("variant") << "property.variant.qml"
<< QByteArray("QVariant") << int(QMetaType::QVariant)
<< true // default
diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
index 76185a97e0..296d1b14e0 100644
--- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
+++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
@@ -157,7 +157,7 @@ void tst_qqmlmetatype::initTestCase()
void tst_qqmlmetatype::qmlParserStatusCast()
{
- QVERIFY(!QQmlMetaType::qmlType(QVariant::Int).isValid());
+ QVERIFY(!QQmlMetaType::qmlType(QMetaType::Int).isValid());
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).isValid());
QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).parserStatusCast(), -1);
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()).isValid());
@@ -177,7 +177,7 @@ void tst_qqmlmetatype::qmlParserStatusCast()
void tst_qqmlmetatype::qmlPropertyValueSourceCast()
{
- QVERIFY(!QQmlMetaType::qmlType(QVariant::Int).isValid());
+ QVERIFY(!QQmlMetaType::qmlType(QMetaType::Int).isValid());
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).isValid());
QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).propertyValueSourceCast(), -1);
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()).isValid());
@@ -197,7 +197,7 @@ void tst_qqmlmetatype::qmlPropertyValueSourceCast()
void tst_qqmlmetatype::qmlPropertyValueInterceptorCast()
{
- QVERIFY(!QQmlMetaType::qmlType(QVariant::Int).isValid());
+ QVERIFY(!QQmlMetaType::qmlType(QMetaType::Int).isValid());
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).isValid());
QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).propertyValueInterceptorCast(), -1);
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()).isValid());
@@ -256,8 +256,8 @@ void tst_qqmlmetatype::prettyTypeName()
void tst_qqmlmetatype::isList()
{
- QCOMPARE(QQmlMetaType::isList(QVariant::Invalid), false);
- QCOMPARE(QQmlMetaType::isList(QVariant::Int), false);
+ QCOMPARE(QQmlMetaType::isList(QMetaType::UnknownType), false);
+ QCOMPARE(QQmlMetaType::isList(QMetaType::Int), false);
QQmlListProperty<TestType> list;
@@ -307,7 +307,7 @@ void tst_qqmlmetatype::compositeType()
//Loading the test file also loads all composite types it imports
QQmlComponent c(&engine, testFileUrl("testImplicitComposite.qml"));
- QObject* obj = c.create();
+ QScopedPointer<QObject> obj(c.create());
QVERIFY(obj);
QQmlType type = QQmlMetaType::qmlType(QString("ImplicitType"), QString(""), 1, 0);
@@ -324,13 +324,13 @@ void tst_qqmlmetatype::externalEnums()
qmlRegisterSingletonType<ExternalEnums>("x.y.z", 1, 0, "ExternalEnums", ExternalEnums::create);
QQmlComponent c(&engine, testFileUrl("testExternalEnums.qml"));
- QObject *obj = c.create();
+ QScopedPointer<QObject> obj(c.create());
QVERIFY(obj);
QVariant a = obj->property("a");
- QCOMPARE(a.type(), QVariant::Int);
+ QCOMPARE(a.userType(), QVariant::Int);
QCOMPARE(a.toInt(), int(QStandardPaths::DocumentsLocation));
QVariant b = obj->property("b");
- QCOMPARE(b.type(), QVariant::Int);
+ QCOMPARE(b.userType(), QVariant::Int);
QCOMPARE(b.toInt(), int(QStandardPaths::DocumentsLocation));
}
@@ -394,10 +394,10 @@ void tst_qqmlmetatype::unregisterCustomType()
QObject *controller = obj->findChild<QObject *>("controller");
QVERIFY(qobject_cast<Controller1 *>(controller));
QVariant stringVal = controller->property("string");
- QCOMPARE(stringVal.type(), QVariant::String);
+ QCOMPARE(stringVal.userType(), QVariant::String);
QCOMPARE(stringVal.toString(), QStringLiteral("Controller #1"));
QVariant enumVal = controller->property("enumVal");
- QCOMPARE(enumVal.type(), QVariant::Int);
+ QCOMPARE(enumVal.userType(), QVariant::Int);
QCOMPARE(enumVal.toInt(), 1);
}
QQmlMetaType::unregisterType(controllerId);
@@ -417,10 +417,10 @@ void tst_qqmlmetatype::unregisterCustomType()
QObject *controller = obj->findChild<QObject *>("controller");
QVERIFY(qobject_cast<Controller2 *>(controller));
QVariant stringVal = controller->property("string");
- QCOMPARE(stringVal.type(), QVariant::String);
+ QCOMPARE(stringVal.userType(), QVariant::String);
QCOMPARE(stringVal.toString(), QStringLiteral("Controller #2"));
QVariant enumVal = controller->property("enumVal");
- QCOMPARE(enumVal.type(), QVariant::Int);
+ QCOMPARE(enumVal.userType(), QVariant::Int);
QCOMPARE(enumVal.toInt(), 111);
}
QQmlMetaType::unregisterType(controllerId);
@@ -440,10 +440,10 @@ void tst_qqmlmetatype::unregisterCustomType()
QObject *controller = obj->findChild<QObject *>("controller");
QVERIFY(qobject_cast<Controller1 *>(controller));
QVariant stringVal = controller->property("string");
- QCOMPARE(stringVal.type(), QVariant::String);
+ QCOMPARE(stringVal.userType(), QVariant::String);
QCOMPARE(stringVal.toString(), QStringLiteral("Controller #1"));
QVariant enumVal = controller->property("enumVal");
- QCOMPARE(enumVal.type(), QVariant::Int);
+ QCOMPARE(enumVal.userType(), QVariant::Int);
QCOMPARE(enumVal.toInt(), 1);
}
}
@@ -489,7 +489,7 @@ void tst_qqmlmetatype::unregisterCustomSingletonType()
QScopedPointer<QObject> obj(c.create());
QVERIFY(obj.data());
QVariant stringVal = obj->property("text");
- QCOMPARE(stringVal.type(), QVariant::String);
+ QCOMPARE(stringVal.userType(), QVariant::String);
QCOMPARE(stringVal.toString(), QStringLiteral("StaticProvider #1"));
}
QQmlMetaType::unregisterType(staticProviderId);
@@ -505,7 +505,7 @@ void tst_qqmlmetatype::unregisterCustomSingletonType()
QScopedPointer<QObject> obj(c.create());
QVERIFY(obj.data());
QVariant stringVal = obj->property("text");
- QCOMPARE(stringVal.type(), QVariant::String);
+ QCOMPARE(stringVal.userType(), QVariant::String);
QCOMPARE(stringVal.toString(), QStringLiteral("StaticProvider #2"));
}
QQmlMetaType::unregisterType(staticProviderId);
@@ -521,7 +521,7 @@ void tst_qqmlmetatype::unregisterCustomSingletonType()
QScopedPointer<QObject> obj(c.create());
QVERIFY(obj.data());
QVariant stringVal = obj->property("text");
- QCOMPARE(stringVal.type(), QVariant::String);
+ QCOMPARE(stringVal.userType(), QVariant::String);
QCOMPARE(stringVal.toString(), QStringLiteral("StaticProvider #1"));
}
}
@@ -552,7 +552,8 @@ void tst_qqmlmetatype::unregisterAttachedProperties()
QCOMPARE(attachedType.attachedPropertiesType(QQmlEnginePrivate::get(&e)),
attachedType.metaObject());
- QVERIFY(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ QVERIFY(obj);
}
qmlClearTypeRegistrations();
@@ -571,7 +572,8 @@ void tst_qqmlmetatype::unregisterAttachedProperties()
QCOMPARE(attachedType.attachedPropertiesType(QQmlEnginePrivate::get(&e)),
attachedType.metaObject());
- QVERIFY(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ QVERIFY(obj);
}
}
diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton.qml b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton.qml
index 9789be8191..258667be18 100644
--- a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton.qml
+++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton.qml
@@ -1,5 +1,6 @@
pragma Singleton
import QtQuick 2.0
+import Test 1.0
QtObject {
property Loader _loader: Loader {
@@ -7,10 +8,10 @@ QtObject {
}
Component.onCompleted: {
- if (tracker.objectName === "first")
- tracker.objectName = "second"
+ if (Tracker.objectName === "first")
+ Tracker.objectName = "second"
else
- tracker.objectName = "first"
+ Tracker.objectName = "first"
//console.log("created singleton", this)
}
}
diff --git a/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp
index ae8c231aab..bb5bb00adb 100644
--- a/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp
@@ -47,9 +47,9 @@ public:
void registerTypes(const char *uri)
{
- // Because the module is protected, this plugin should never be loaded
+ // The module is protected. The plugin can still be loaded, but it cannot register
+ // any types.
Q_UNUSED(uri);
- Q_ASSERT(0);
}
};
diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
index f89cc9f24a..75885bc84a 100644
--- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
@@ -609,7 +609,7 @@ void tst_qqmlmoduleplugin::importStrictModule_data()
<< "import org.qtproject.NonstrictModule 1.0\n"
"MyPluginType {}"
<< "Module 'org.qtproject.NonstrictModule' does not contain a module identifier directive - it cannot be protected from external registrations."
- << ":1:1: plugin cannot be loaded for module \"org.qtproject.NonstrictModule\": Cannot install element 'MyPluginType' into protected namespace 'org.qtproject.StrictModule'";
+ << ":1:1: plugin cannot be loaded for module \"org.qtproject.NonstrictModule\": Cannot install element 'MyPluginType' into protected module 'org.qtproject.StrictModule' version '1'";
QTest::newRow("non-strict preemption")
<< "import org.qtproject.PreemptiveModule 1.0\n"
@@ -777,7 +777,7 @@ void tst_qqmlmoduleplugin::multiSingleton()
{
QQmlEngine engine;
QObject obj;
- engine.rootContext()->setContextProperty("tracker", &obj);
+ qmlRegisterSingletonInstance("Test", 1, 0, "Tracker", &obj);
engine.addImportPath(m_importsDirectory);
QQmlComponent component(&engine, testFileUrl("multiSingleton.qml"));
QObject *object = component.create();
diff --git a/tests/auto/qml/qqmlnotifier/data/connectnotify.qml b/tests/auto/qml/qqmlnotifier/data/connectnotify.qml
index 35226ee5ab..34e70e6afe 100644
--- a/tests/auto/qml/qqmlnotifier/data/connectnotify.qml
+++ b/tests/auto/qml/qqmlnotifier/data/connectnotify.qml
@@ -3,6 +3,7 @@ import Test 1.0
Item {
id: root
+ required property ExportedClass exportedObject
ExportedClass {
id: exportedClass
objectName: "exportedClass"
@@ -22,7 +23,7 @@ Item {
}
property int foo: exportedClass.qmlObjectProp
- property int baz: _exportedObject.cppObjectProp
+ property int baz: exportedObject.cppObjectProp
// v4 bindings that could share a subscription. They don't, though, and the code
// relies on that
diff --git a/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp b/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
index de762d66c5..836b94ad45 100644
--- a/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
+++ b/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
@@ -185,8 +185,7 @@ void tst_qqmlnotifier::createObjects()
QQmlComponent component(&engine, testFileUrl("connectnotify.qml"));
exportedObject = new ExportedClass();
exportedObject->setObjectName("exportedObject");
- engine.rootContext()->setContextProperty("_exportedObject", exportedObject);
- root = component.create();
+ root = component.createWithInitialProperties({{"exportedObject", QVariant::fromValue(exportedObject)}});
QVERIFY(root != nullptr);
exportedClass = qobject_cast<ExportedClass *>(
@@ -324,12 +323,12 @@ void tst_qqmlnotifier::lotsOfBindings()
TestObject o;
QQmlEngine *e = new QQmlEngine;
- e->rootContext()->setContextProperty(QStringLiteral("test"), &o);
+ qmlRegisterSingletonInstance("Test", 1, 0, "Test", &o);
QList<QQmlComponent *> components;
for (int i = 0; i < 20000; ++i) {
QQmlComponent *component = new QQmlComponent(e);
- component->setData("import QtQuick 2.0; Item { width: test.a; }", QUrl());
+ component->setData("import QtQuick 2.0; import Test 1.0; Item {width: Test.a; }", QUrl());
component->create(e->rootContext());
components.append(component);
}
diff --git a/tests/auto/qml/qqmlparser/data/annotations/View1.qml b/tests/auto/qml/qqmlparser/data/annotations/View1.qml
new file mode 100644
index 0000000000..2d3d7d2cfd
--- /dev/null
+++ b/tests/auto/qml/qqmlparser/data/annotations/View1.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Charts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//![2]
+import QtQuick 2.0
+//![2]
+import QtCharts 2.0
+
+@Pippo{ atg1:3 }
+@Annotation2{}
+Item {
+ @Annotate{}
+ anchors.fill: parent
+ @AnnotateMore{
+ property int x: 5
+ }
+ @AnnotateALot{}
+ property variant othersSlice: 0
+
+ //![1]
+ ChartView {
+ id: chart
+ title: "Top-5 car brand shares in Finland"
+ anchors.fill: parent
+ legend.alignment: Qt.AlignBottom
+ antialiasing: true
+
+@ExtraAnnotation{
+ signal pippo
+}
+ PieSeries {
+ id: pieSeries
+ PieSlice { label: "Volkswagen"; value: 13.5 }
+ PieSlice { label: "Toyota"; value: 10.9 }
+ PieSlice { label: "Ford"; value: 8.6 }
+ PieSlice { label: "Skoda"; value: 8.2 }
+ PieSlice { label: "Volvo"; value: 6.8 }
+ }
+ }
+
+@SuperComplete{
+binding: late
+}
+ Component.onCompleted: {
+ // You can also manipulate slices dynamically, like append a slice or set a slice exploded
+ othersSlice = pieSeries.append("Others", 52.0);
+ pieSeries.find("Volkswagen").exploded = true;
+ }
+ //![1]
+}
diff --git a/tests/auto/qml/qqmlparser/data/noannotations/View1.qml b/tests/auto/qml/qqmlparser/data/noannotations/View1.qml
new file mode 100644
index 0000000000..945bce3a44
--- /dev/null
+++ b/tests/auto/qml/qqmlparser/data/noannotations/View1.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Charts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//![2]
+import QtQuick 2.0
+//![2]
+import QtCharts 2.0
+
+
+
+Item {
+
+ anchors.fill: parent
+
+
+
+
+ property variant othersSlice: 0
+
+ //![1]
+ ChartView {
+ id: chart
+ title: "Top-5 car brand shares in Finland"
+ anchors.fill: parent
+ legend.alignment: Qt.AlignBottom
+ antialiasing: true
+
+
+
+
+ PieSeries {
+ id: pieSeries
+ PieSlice { label: "Volkswagen"; value: 13.5 }
+ PieSlice { label: "Toyota"; value: 10.9 }
+ PieSlice { label: "Ford"; value: 8.6 }
+ PieSlice { label: "Skoda"; value: 8.2 }
+ PieSlice { label: "Volvo"; value: 6.8 }
+ }
+ }
+
+
+
+
+ Component.onCompleted: {
+ // You can also manipulate slices dynamically, like append a slice or set a slice exploded
+ othersSlice = pieSeries.append("Others", 52.0);
+ pieSeries.find("Volkswagen").exploded = true;
+ }
+ //![1]
+}
diff --git a/tests/auto/qml/qqmlparser/qqmlparser.pro b/tests/auto/qml/qqmlparser/qqmlparser.pro
index d8e4b0dd06..7f117b3157 100644
--- a/tests/auto/qml/qqmlparser/qqmlparser.pro
+++ b/tests/auto/qml/qqmlparser/qqmlparser.pro
@@ -11,3 +11,4 @@ cross_compile: DEFINES += QTEST_CROSS_COMPILED
TESTDATA = data/*
include (../../shared/util.pri)
+include (../../shared/astdump.pri)
diff --git a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
index 9d8818d01e..c7d09f9d6e 100644
--- a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
+++ b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
@@ -33,6 +33,7 @@
#include <private/qqmljsast_p.h>
#include "../../shared/util.h"
+#include "../../shared/qqmljsastdumper.h"
#include <qtest.h>
#include <QDir>
@@ -62,6 +63,11 @@ private slots:
void typeAnnotations();
void disallowedTypeAnnotations_data();
void disallowedTypeAnnotations();
+ void semicolonPartOfExpressionStatement();
+ void typeAssertion_data();
+ void typeAssertion();
+ void annotations_data();
+ void annotations();
private:
QStringList excludedDirs;
@@ -141,6 +147,30 @@ struct TypeAnnotationObserver: public AST::Visitor
}
};
+struct ExpressionStatementObserver: public AST::Visitor
+{
+ int expressionsSeen = 0;
+ bool endsWithSemicolon = true;
+
+ void operator()(AST::Node *node)
+ {
+ AST::Node::accept(node, this);
+ }
+
+ virtual bool visit(AST::ExpressionStatement *statement)
+ {
+ ++expressionsSeen;
+ endsWithSemicolon = endsWithSemicolon
+ && (statement->lastSourceLocation().end() == statement->semicolonToken.end());
+ return true;
+ }
+
+ void throwRecursionDepthError() final
+ {
+ QFAIL("Maximum statement or expression depth exceeded");
+ }
+};
+
}
tst_qqmlparser::tst_qqmlparser()
@@ -438,6 +468,123 @@ void tst_qqmlparser::disallowedTypeAnnotations()
QVERIFY2(parser.errorMessage().startsWith("Type annotations are not permitted "), qPrintable(parser.errorMessage()));
}
+void tst_qqmlparser::semicolonPartOfExpressionStatement()
+{
+ QQmlJS::Engine engine;
+ QQmlJS::Lexer lexer(&engine);
+ lexer.setCode(QLatin1String("A { property int x: 1+1; property int y: 2+2 \n"
+ "tt: {'a': 5, 'b': 6}; ff: {'c': 'rrr'}}"), 1);
+ QQmlJS::Parser parser(&engine);
+ QVERIFY(parser.parse());
+
+ check::ExpressionStatementObserver observer;
+ observer(parser.rootNode());
+
+ QCOMPARE(observer.expressionsSeen, 4);
+ QVERIFY(observer.endsWithSemicolon);
+}
+
+void tst_qqmlparser::typeAssertion_data()
+{
+ QTest::addColumn<QString>("expression");
+ QTest::addRow("as A")
+ << QString::fromLatin1("A { onStuff: (b as A).happen() }");
+ QTest::addRow("as double paren")
+ << QString::fromLatin1("A { onStuff: console.log((12 as double)); }");
+ QTest::addRow("as double noparen")
+ << QString::fromLatin1("A { onStuff: console.log(12 as double); }");
+ QTest::addRow("property as double")
+ << QString::fromLatin1("A { prop: (12 as double); }");
+ QTest::addRow("property noparen as double")
+ << QString::fromLatin1("A { prop: 12 as double; }");
+
+ // rabbits cannot be discerned from types on a syntactical level.
+ // We could detect this on a semantical level, once we implement type assertions there.
+
+ QTest::addRow("as rabbit")
+ << QString::fromLatin1("A { onStuff: (b as rabbit).happen() }");
+ QTest::addRow("as rabbit paren")
+ << QString::fromLatin1("A { onStuff: console.log((12 as rabbit)); }");
+ QTest::addRow("as rabbit noparen")
+ << QString::fromLatin1("A { onStuff: console.log(12 as rabbit); }");
+ QTest::addRow("property as rabbit")
+ << QString::fromLatin1("A { prop: (12 as rabbit); }");
+ QTest::addRow("property noparen as rabbit")
+ << QString::fromLatin1("A { prop: 12 as rabbit; }");
+}
+
+void tst_qqmlparser::typeAssertion()
+{
+ QFETCH(QString, expression);
+
+ QQmlJS::Engine engine;
+ QQmlJS::Lexer lexer(&engine);
+ lexer.setCode(expression, 1);
+ QQmlJS::Parser parser(&engine);
+ QVERIFY(parser.parse());
+}
+
+void tst_qqmlparser::annotations_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QString>("refFile");
+
+ QString tests = dataDirectory() + "/annotations/";
+ QString compare = dataDirectory() + "/noannotations/";
+
+ QStringList files;
+ files << findFiles(QDir(tests));
+
+ QStringList refFiles;
+ refFiles << findFiles(QDir(compare));
+
+ for (const QString &file: qAsConst(files)) {
+ auto fileNameStart = file.lastIndexOf(QDir::separator());
+ QStringRef fileName(&file, fileNameStart, file.length()-fileNameStart);
+ auto ref=std::find_if(refFiles.constBegin(),refFiles.constEnd(), [fileName](const QString &s){ return s.endsWith(fileName); });
+ if (ref != refFiles.constEnd())
+ QTest::newRow(qPrintable(file)) << file << *ref;
+ else
+ QTest::newRow(qPrintable(file)) << file << QString();
+ }
+}
+
+void tst_qqmlparser::annotations()
+{
+ using namespace QQmlJS;
+
+ QFETCH(QString, file);
+ QFETCH(QString, refFile);
+
+ QString code;
+ QString refCode;
+
+ QFile f(file);
+ if (f.open(QFile::ReadOnly))
+ code = QString::fromUtf8(f.readAll());
+ QFile refF(refFile);
+ if (!refFile.isEmpty() && refF.open(QFile::ReadOnly))
+ refCode = QString::fromUtf8(refF.readAll());
+
+ const bool qmlMode = true;
+
+ Engine engine;
+ Lexer lexer(&engine);
+ lexer.setCode(code, 1, qmlMode);
+ Parser parser(&engine);
+ QVERIFY(parser.parse());
+
+ if (!refCode.isEmpty()) {
+ Engine engine2;
+ Lexer lexer2(&engine2);
+ lexer2.setCode(refCode, 1, qmlMode);
+ Parser parser2(&engine2);
+ QVERIFY(parser2.parse());
+
+ QCOMPARE(AstDumper::diff(parser.ast(), parser2.rootNode(), 3, DumperOptions::NoAnnotations | DumperOptions::NoLocations), QString());
+ }
+}
+
QTEST_MAIN(tst_qqmlparser)
#include "tst_qqmlparser.moc"
diff --git a/tests/auto/qml/qqmlproperty/data/aliasToBinding.qml b/tests/auto/qml/qqmlproperty/data/aliasToBinding.qml
new file mode 100644
index 0000000000..54f9e3f944
--- /dev/null
+++ b/tests/auto/qml/qqmlproperty/data/aliasToBinding.qml
@@ -0,0 +1,23 @@
+import QtQuick 2.7
+
+Item {
+ id: _window
+ property bool userFontStrikeout: true
+
+ Component.onCompleted: {
+ _box.font.strikeout = Qt.binding(function() { return _window.userFontStrikeout; });
+ }
+
+ Rectangle {
+ id: _box
+ width: 100
+ height: 100
+ property alias font: _text.font
+
+ Text {
+ id: _text
+ anchors.fill: parent
+ text: "Text"
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlproperty/data/assignEmptyVariantMap.qml b/tests/auto/qml/qqmlproperty/data/assignEmptyVariantMap.qml
index a9e51c1255..440f07ac87 100644
--- a/tests/auto/qml/qqmlproperty/data/assignEmptyVariantMap.qml
+++ b/tests/auto/qml/qqmlproperty/data/assignEmptyVariantMap.qml
@@ -1,5 +1,6 @@
import QtQuick 2.0
Item {
+ required property QtObject o
Component.onCompleted: { o.variantMap = {}; }
}
diff --git a/tests/auto/qml/qqmlproperty/data/interfaceBinding2.qml b/tests/auto/qml/qqmlproperty/data/interfaceBinding2.qml
new file mode 100644
index 0000000000..e7c5dc7344
--- /dev/null
+++ b/tests/auto/qml/qqmlproperty/data/interfaceBinding2.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.12
+import io.qt.bugreports 2.0
+Item {
+ InterfaceConsumer2 {
+ objectName: "a1"
+ i: A2 {
+ property int i: 42
+ }
+ }
+
+ InterfaceConsumer2 {
+ objectName: "a2"
+ property A2 a: A2 {
+ property int i: 43
+ }
+ i: a
+ }
+
+ InterfaceConsumer2 {
+ objectName: "a3"
+ property A2 a: A2 {
+ id : aa
+ property int i: 44
+ }
+ i: aa
+ }
+}
diff --git a/tests/auto/qml/qqmlproperty/interfaces.h b/tests/auto/qml/qqmlproperty/interfaces.h
new file mode 100644
index 0000000000..2c06c5f594
--- /dev/null
+++ b/tests/auto/qml/qqmlproperty/interfaces.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INTERFACES_H
+#define INTERFACES_H
+
+#include <QtQml/qqml.h>
+
+struct Interface {
+};
+
+QT_BEGIN_NAMESPACE
+#define MyInterface_iid "io.qt.bugreports.Interface"
+Q_DECLARE_INTERFACE(Interface, MyInterface_iid);
+QT_END_NAMESPACE
+
+class A : public QObject, Interface {
+ Q_OBJECT
+ Q_INTERFACES(Interface)
+};
+
+class B : public QObject, Interface {
+ Q_OBJECT
+ Q_INTERFACES(Interface)
+};
+
+class C : public QObject {
+ Q_OBJECT
+};
+
+struct Interface2
+{
+ Q_GADGET
+ QML_INTERFACE
+};
+
+QT_BEGIN_NAMESPACE
+#define MyInterface2_iid "io.qt.bugreports.Interface2"
+Q_DECLARE_INTERFACE(Interface2, MyInterface2_iid);
+QT_END_NAMESPACE
+
+class A2 : public QObject, Interface2 {
+ Q_OBJECT
+ QML_ELEMENT
+ Q_INTERFACES(Interface2)
+};
+
+class B2 : public QObject, Interface2 {
+ Q_OBJECT
+ QML_ELEMENT
+ Q_INTERFACES(Interface2)
+};
+
+class C2 : public QObject {
+ Q_OBJECT
+ QML_ELEMENT
+};
+
+class InterfaceConsumer : public QObject {
+ Q_OBJECT
+ Q_PROPERTY(Interface *i READ interface WRITE setInterface NOTIFY interfaceChanged)
+ Q_PROPERTY(int testValue READ testValue NOTIFY testValueChanged)
+
+public:
+
+ Interface* interface() const
+ {
+ return m_interface;
+ }
+ void setInterface(Interface* interface)
+ {
+ QObject* object = reinterpret_cast<QObject*>(interface);
+ m_testValue = object->property("i").toInt();
+ emit testValueChanged();
+ if (m_interface == interface)
+ return;
+
+ m_interface = interface;
+ emit interfaceChanged();
+ }
+
+ int testValue() {
+ return m_testValue;
+ }
+
+signals:
+ void interfaceChanged();
+ void testValueChanged();
+
+private:
+ Interface* m_interface = nullptr;
+ int m_testValue = 0;
+};
+
+
+class InterfaceConsumer2 : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(Interface2 *i READ interface WRITE setInterface NOTIFY interfaceChanged)
+ Q_PROPERTY(int testValue READ testValue NOTIFY testValueChanged)
+
+ QML_ELEMENT
+
+public:
+
+ Interface2* interface() const
+ {
+ return m_interface;
+ }
+ void setInterface(Interface2* interface2)
+ {
+ QObject* object = reinterpret_cast<QObject*>(interface2);
+ m_testValue = object->property("i").toInt();
+ emit testValueChanged();
+ if (m_interface == interface2)
+ return;
+
+ m_interface = interface2;
+ emit interfaceChanged();
+ }
+
+ int testValue() {
+ return m_testValue;
+ }
+
+signals:
+ void interfaceChanged();
+ void testValueChanged();
+
+private:
+ Interface2 *m_interface = nullptr;
+ int m_testValue = 0;
+};
+
+#endif // INTERFACES_H
diff --git a/tests/auto/qml/qqmlproperty/qqmlproperty.pro b/tests/auto/qml/qqmlproperty/qqmlproperty.pro
index b1bcf1f17d..4d42975369 100644
--- a/tests/auto/qml/qqmlproperty/qqmlproperty.pro
+++ b/tests/auto/qml/qqmlproperty/qqmlproperty.pro
@@ -1,7 +1,10 @@
-CONFIG += testcase
+CONFIG += testcase qmltypes
TARGET = tst_qqmlproperty
macx:CONFIG -= app_bundle
+QML_IMPORT_NAME = io.qt.bugreports
+QML_IMPORT_VERSION = 2.0
+
SOURCES += tst_qqmlproperty.cpp
include (../../shared/util.pri)
@@ -9,3 +12,6 @@ include (../../shared/util.pri)
TESTDATA = data/*
QT += core-private gui-private qml-private testlib
+
+HEADERS += \
+ interfaces.h
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index 864a47e998..8a96fc52c5 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -25,6 +25,8 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+
+#include "interfaces.h"
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -157,6 +159,8 @@ private slots:
void copy();
+ void bindingToAlias();
+
void nestedQQmlPropertyMap();
void underscorePropertyChangeHandler();
@@ -1224,10 +1228,10 @@ void tst_qqmlproperty::read()
}
{
QQmlComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
- QQmlProperty p(object, "test", &engine);
+ QQmlProperty p(object.data(), "test", &engine);
QCOMPARE(p.propertyTypeCategory(), QQmlProperty::Object);
QVERIFY(p.propertyType() != QMetaType::QObjectStar);
@@ -1239,10 +1243,10 @@ void tst_qqmlproperty::read()
}
{ // static
QQmlComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
- QVariant v = QQmlProperty::read(object, "test", &engine);
+ QVariant v = QQmlProperty::read(object.data(), "test", &engine);
QCOMPARE(v.userType(), int(QMetaType::QObjectStar));
QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
@@ -1252,41 +1256,38 @@ void tst_qqmlproperty::read()
{
QQmlComponent component(&engine);
component.setData("import Test 1.0\nMyContainer { }", QUrl());
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
- QQmlProperty p(object, "MyContainer.foo", qmlContext(object));
+ QQmlProperty p(object.data(), "MyContainer.foo", qmlContext(object.data()));
QCOMPARE(p.read(), QVariant(13));
- delete object;
}
{
QQmlComponent component(&engine);
component.setData("import Test 1.0\nMyContainer { MyContainer.foo: 10 }", QUrl());
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
- QQmlProperty p(object, "MyContainer.foo", qmlContext(object));
+ QQmlProperty p(object.data(), "MyContainer.foo", qmlContext(object.data()));
QCOMPARE(p.read(), QVariant(10));
- delete object;
}
{
QQmlComponent component(&engine);
component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
- QQmlProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
+ QQmlProperty p(object.data(), "Foo.MyContainer.foo", qmlContext(object.data()));
QCOMPARE(p.read(), QVariant(10));
- delete object;
}
{ // static
QQmlComponent component(&engine);
component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
- QCOMPARE(QQmlProperty::read(object, "Foo.MyContainer.foo", qmlContext(object)), QVariant(10));
- delete object;
+ QCOMPARE(QQmlProperty::read(object.data(), "Foo.MyContainer.foo",
+ qmlContext(object.data())), QVariant(10));
}
}
@@ -1447,11 +1448,12 @@ void tst_qqmlproperty::write()
{ // QChar -> QString
QQmlComponent component(&engine);
component.setData("import Test 1.0\nPropertyObject { stringProperty: constQChar }", QUrl());
- PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
- QVERIFY(obj != nullptr);
- if (obj) {
- QQmlProperty stringProperty(obj, "stringProperty");
- QCOMPARE(stringProperty.read(), QVariant(QString(obj->constQChar())));
+ QScopedPointer<QObject> object(component.create());
+ PropertyObject *propertyObject = qobject_cast<PropertyObject*>(object.data());
+ QVERIFY(propertyObject != nullptr);
+ if (propertyObject) {
+ QQmlProperty stringProperty(propertyObject, "stringProperty");
+ QCOMPARE(stringProperty.read(), QVariant(QString(propertyObject->constQChar())));
}
}
@@ -1628,29 +1630,32 @@ void tst_qqmlproperty::writeObjectToList()
{
QQmlComponent containerComponent(&engine);
containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
- MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
+ QScopedPointer<QObject> object(containerComponent.create());
+ MyContainer *container = qobject_cast<MyContainer*>(object.data());
QVERIFY(container != nullptr);
QQmlListReference list(container, "children");
QCOMPARE(list.count(), 1);
- MyQmlObject *object = new MyQmlObject;
+ QScopedPointer<MyQmlObject> childObject(new MyQmlObject);
QQmlProperty prop(container, "children");
- prop.write(QVariant::fromValue(object));
+ prop.write(QVariant::fromValue(childObject.data()));
QCOMPARE(list.count(), 1);
- QCOMPARE(list.at(0), qobject_cast<QObject*>(object));
+ QCOMPARE(list.at(0), qobject_cast<QObject*>(childObject.data()));
}
void tst_qqmlproperty::writeListToList()
{
QQmlComponent containerComponent(&engine);
containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
- MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
+ QScopedPointer<QObject> object(containerComponent.create());
+ MyContainer *container = qobject_cast<MyContainer*>(object.data());
QVERIFY(container != nullptr);
QQmlListReference list(container, "children");
QCOMPARE(list.count(), 1);
QList<QObject*> objList;
- objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
+ objList << new MyQmlObject(this) << new MyQmlObject(this)
+ << new MyQmlObject(this) << new MyQmlObject(this);
QQmlProperty prop(container, "children");
prop.write(QVariant::fromValue(objList));
QCOMPARE(list.count(), 4);
@@ -1828,10 +1833,11 @@ void tst_qqmlproperty::crashOnValueProperty()
QQmlComponent component(engine);
component.setData("import Test 1.0\nPropertyObject { wrectProperty.x: 10 }", QUrl());
- PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
- QVERIFY(obj != nullptr);
+ QScopedPointer<QObject> object(component.create());
+ PropertyObject *propertyObject = qobject_cast<PropertyObject*>(object.data());
+ QVERIFY(propertyObject != nullptr);
- QQmlProperty p(obj, "wrectProperty.x", qmlContext(obj));
+ QQmlProperty p(propertyObject, "wrectProperty.x", qmlContext(propertyObject));
QCOMPARE(p.name(), QString("wrectProperty.x"));
QCOMPARE(p.read(), QVariant(10));
@@ -1999,11 +2005,9 @@ void tst_qqmlproperty::assignEmptyVariantMap()
QCOMPARE(o.variantMap().count(), 1);
QCOMPARE(o.variantMap().isEmpty(), false);
- QQmlContext context(&engine);
- context.setContextProperty("o", &o);
QQmlComponent component(&engine, testFileUrl("assignEmptyVariantMap.qml"));
- QObject *obj = component.create(&context);
+ QObject *obj = component.createWithInitialProperties({{"o", QVariant::fromValue(&o)}});
QVERIFY(obj);
QCOMPARE(o.variantMap().count(), 0);
@@ -2090,74 +2094,20 @@ void tst_qqmlproperty::nullPropertyBinding()
QMetaObject::invokeMethod(root.get(), "tog");
}
-struct Interface {
-};
-
-QT_BEGIN_NAMESPACE
-#define MyInterface_iid "io.qt.bugreports.Interface"
-Q_DECLARE_INTERFACE(Interface, MyInterface_iid);
-QT_END_NAMESPACE
-
-class A : public QObject, Interface {
- Q_OBJECT
- Q_INTERFACES(Interface)
-};
-
-class B : public QObject, Interface {
- Q_OBJECT
- Q_INTERFACES(Interface)
-};
-
-class C : public QObject {
- Q_OBJECT
-};
-
-class InterfaceConsumer : public QObject {
- Q_OBJECT
- Q_PROPERTY(Interface* i READ interface WRITE setInterface NOTIFY interfaceChanged)
- Q_PROPERTY(int testValue READ testValue NOTIFY testValueChanged)
-
-
-public:
-
- Interface* interface() const
- {
- return m_interface;
- }
- void setInterface(Interface* interface)
- {
- QObject* object = reinterpret_cast<QObject*>(interface);
- m_testValue = object->property("i").toInt();
- emit testValueChanged();
- if (m_interface == interface)
- return;
-
- m_interface = interface;
- emit interfaceChanged();
- }
-
- int testValue() {
- return m_testValue;
- }
-
-signals:
- void interfaceChanged();
- void testValueChanged();
-
-private:
- Interface* m_interface = nullptr;
- int m_testValue = 0;
-};
void tst_qqmlproperty::interfaceBinding()
{
-
- qmlRegisterInterface<Interface>("Interface");
- qmlRegisterType<A>("io.qt.bugreports", 1, 0, "A");
- qmlRegisterType<B>("io.qt.bugreports", 1, 0, "B");
- qmlRegisterType<C>("io.qt.bugreports", 1, 0, "C");
- qmlRegisterType<InterfaceConsumer>("io.qt.bugreports", 1, 0, "InterfaceConsumer");
-
- const QUrl url = testFileUrl("interfaceBinding.qml");
+ qmlRegisterInterface<Interface>("Interface");
+ qmlRegisterType<A>("io.qt.bugreports", 1, 0, "A");
+ qmlRegisterType<B>("io.qt.bugreports", 1, 0, "B");
+ qmlRegisterType<C>("io.qt.bugreports", 1, 0, "C");
+ qmlRegisterType<InterfaceConsumer>("io.qt.bugreports", 1, 0, "InterfaceConsumer");
+
+ const QVector<QUrl> urls = {
+ testFileUrl("interfaceBinding.qml"),
+ testFileUrl("interfaceBinding2.qml")
+ };
+
+ for (const QUrl &url : urls) {
QQmlEngine engine;
QQmlComponent component(&engine, url);
QScopedPointer<QObject> root(component.create());
@@ -2165,6 +2115,7 @@ void tst_qqmlproperty::interfaceBinding()
QCOMPARE(root->findChild<QObject*>("a1")->property("testValue").toInt(), 42);
QCOMPARE(root->findChild<QObject*>("a2")->property("testValue").toInt(), 43);
QCOMPARE(root->findChild<QObject*>("a3")->property("testValue").toInt(), 44);
+ }
}
void tst_qqmlproperty::floatToStringPrecision_data()
@@ -2214,6 +2165,15 @@ void tst_qqmlproperty::initTestCase()
qmlRegisterType<MyContainer>("Test",1,0,"MyContainer");
}
+// QTBUG-60908
+void tst_qqmlproperty::bindingToAlias()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("aliasToBinding.qml"));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+}
+
void tst_qqmlproperty::nestedQQmlPropertyMap()
{
QQmlPropertyMap mainPropertyMap;
diff --git a/tests/auto/qml/qqmlqt/data/formatting.qml b/tests/auto/qml/qqmlqt/data/formatting.qml
index 7a462c8eeb..f2d1e1b5c8 100644
--- a/tests/auto/qml/qqmlqt/data/formatting.qml
+++ b/tests/auto/qml/qqmlqt/data/formatting.qml
@@ -41,4 +41,9 @@ QtObject {
property string err_dateTime1: Qt.formatDateTime()
property string err_dateTime2: Qt.formatDateTime(new Date, new Object)
+
+ property var qdate
+ property var qtime
+ property var qdatetime
+ property var qvariant
}
diff --git a/tests/auto/qml/qqmlqt/data/formattingLocale.qml b/tests/auto/qml/qqmlqt/data/formattingLocale.qml
new file mode 100644
index 0000000000..9da349b101
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/formattingLocale.qml
@@ -0,0 +1,12 @@
+import QtQml 2.15
+
+QtObject {
+ required property var myDateTime
+ required property var myDate
+ property var myTime
+
+ property string dateTimeString: Qt.formatDateTime(myDateTime, Qt.locale("de_DE"), Locale.NarrowFormat)
+ property string dateString: Qt.formatDate(myDate, Qt.locale("de_DE"))
+
+ function invalidUsage() { Qt.formatTime(myTime, null, "hello") }
+}
diff --git a/tests/auto/qml/qqmlqt/data/timeRoundtrip.qml b/tests/auto/qml/qqmlqt/data/timeRoundtrip.qml
index 9d73640c87..65732442af 100644
--- a/tests/auto/qml/qqmlqt/data/timeRoundtrip.qml
+++ b/tests/auto/qml/qqmlqt/data/timeRoundtrip.qml
@@ -1,6 +1,8 @@
import QtQuick 2.0
+import Test 1.0
QtObject {
+ required property TimeProvider tp
Component.onCompleted: {
var t = tp.time;
tp.time = t;
diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
index 2d8115e867..1a54397f1a 100644
--- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
+++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
@@ -91,6 +91,7 @@ private slots:
void dateTimeFormatting_data();
void dateTimeFormattingVariants();
void dateTimeFormattingVariants_data();
+ void dateTimeFormattingWithLocale();
void isQtObject();
void btoa();
void atob();
@@ -777,24 +778,24 @@ void tst_qqmlqt::dateTimeFormatting()
QQmlEngine eng;
- eng.rootContext()->setContextProperty("qdate", date);
- eng.rootContext()->setContextProperty("qtime", time);
- eng.rootContext()->setContextProperty("qdatetime", dateTime);
-
QQmlComponent component(&eng, testFileUrl("formatting.qml"));
QStringList warnings;
- warnings << component.url().toString() + ":37: Error: Qt.formatDate(): Invalid date format"
- << component.url().toString() + ":36: Error: Qt.formatDate(): Invalid arguments"
- << component.url().toString() + ":40: Error: Qt.formatTime(): Invalid time format"
- << component.url().toString() + ":39: Error: Qt.formatTime(): Invalid arguments"
- << component.url().toString() + ":43: Error: Qt.formatDateTime(): Invalid datetime format"
- << component.url().toString() + ":42: Error: Qt.formatDateTime(): Invalid arguments";
+ warnings << component.url().toString() + ":37: Error: Qt.formatDate(): Bad second argument (must be either string, number or locale)"
+ << component.url().toString() + ":36: Error: Qt.formatDate(): Missing argument"
+ << component.url().toString() + ":40: Error: Qt.formatTime(): Bad second argument (must be either string, number or locale)"
+ << component.url().toString() + ":39: Error: Qt.formatTime(): Missing argument"
+ << component.url().toString() + ":43: Error: Qt.formatDateTime(): Bad second argument (must be either string, number or locale)"
+ << component.url().toString() + ":42: Error: Qt.formatDateTime(): Missing argument";
foreach (const QString &warning, warnings)
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- QObject *object = component.create();
+ QObject *object = component.createWithInitialProperties({
+ {"qdate", date},
+ {"qtime", time},
+ {"qdatetime", dateTime}
+ });
QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
QVERIFY(object != nullptr);
@@ -815,6 +816,8 @@ void tst_qqmlqt::dateTimeFormatting()
void tst_qqmlqt::dateTimeFormatting_data()
{
+ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
+ // Test intentionally uses deprecated enumerators from Qt::DateFormat
QTest::addColumn<QString>("method");
QTest::addColumn<QStringList>("inputProperties");
QTest::addColumn<QStringList>("expectedResults");
@@ -844,6 +847,7 @@ void tst_qqmlqt::dateTimeFormatting_data()
<< (QStringList() << dateTime.toString(Qt::DefaultLocaleShortDate)
<< dateTime.toString(Qt::DefaultLocaleLongDate)
<< dateTime.toString("M/d/yy H:m:s a"));
+ QT_WARNING_POP
}
void tst_qqmlqt::dateTimeFormattingVariants()
@@ -853,21 +857,20 @@ void tst_qqmlqt::dateTimeFormattingVariants()
QFETCH(QStringList, expectedResults);
QQmlEngine eng;
- eng.rootContext()->setContextProperty("qvariant", variant);
QQmlComponent component(&eng, testFileUrl("formatting.qml"));
QStringList warnings;
- warnings << component.url().toString() + ":37: Error: Qt.formatDate(): Invalid date format"
- << component.url().toString() + ":36: Error: Qt.formatDate(): Invalid arguments"
- << component.url().toString() + ":40: Error: Qt.formatTime(): Invalid time format"
- << component.url().toString() + ":39: Error: Qt.formatTime(): Invalid arguments"
- << component.url().toString() + ":43: Error: Qt.formatDateTime(): Invalid datetime format"
- << component.url().toString() + ":42: Error: Qt.formatDateTime(): Invalid arguments";
+ warnings << component.url().toString() + ":37: Error: Qt.formatDate(): Bad second argument (must be either string, number or locale)"
+ << component.url().toString() + ":36: Error: Qt.formatDate(): Missing argument"
+ << component.url().toString() + ":40: Error: Qt.formatTime(): Bad second argument (must be either string, number or locale)"
+ << component.url().toString() + ":39: Error: Qt.formatTime(): Missing argument"
+ << component.url().toString() + ":43: Error: Qt.formatDateTime(): Bad second argument (must be either string, number or locale)"
+ << component.url().toString() + ":42: Error: Qt.formatDateTime(): Missing argument";
foreach (const QString &warning, warnings)
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- QObject *object = component.create();
+ QObject *object = component.createWithInitialProperties({{"qvariant", variant}});
QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
QVERIFY(object != nullptr);
@@ -883,6 +886,8 @@ void tst_qqmlqt::dateTimeFormattingVariants()
void tst_qqmlqt::dateTimeFormattingVariants_data()
{
+ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
+ // Test intentionally uses deprecated enumerators from Qt::DateFormat
QTest::addColumn<QString>("method");
QTest::addColumn<QVariant>("variant");
QTest::addColumn<QStringList>("expectedResults");
@@ -923,6 +928,28 @@ void tst_qqmlqt::dateTimeFormattingVariants_data()
QTest::newRow("formatDate, int") << "formatDate" << QVariant::fromValue(integer) << (QStringList() << temporary.date().toString(Qt::DefaultLocaleShortDate) << temporary.date().toString(Qt::DefaultLocaleLongDate) << temporary.date().toString("ddd MMMM d yy"));
QTest::newRow("formatDateTime, int") << "formatDateTime" << QVariant::fromValue(integer) << (QStringList() << temporary.toString(Qt::DefaultLocaleShortDate) << temporary.toString(Qt::DefaultLocaleLongDate) << temporary.toString("M/d/yy H:m:s a"));
QTest::newRow("formatTime, int") << "formatTime" << QVariant::fromValue(integer) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz"));
+ QT_WARNING_POP
+}
+
+void tst_qqmlqt::dateTimeFormattingWithLocale()
+{
+ QQmlEngine engine;
+ auto url = testFileUrl("formattingLocale.qml");
+ QQmlComponent comp(&engine, url);
+ QDateTime dateTime = QDateTime::fromString("M1d1y9800:01:02",
+ "'M'M'd'd'y'yyhh:mm:ss");
+ QDate date(1995, 5, 17);
+ QScopedPointer<QObject> o(comp.createWithInitialProperties({ {"myDateTime", dateTime}, {"myDate", date} }));
+ QVERIFY(!o.isNull());
+
+ auto dateTimeString = o->property("dateTimeString").toString();
+ QCOMPARE(dateTimeString, QLocale("de_DE").toString(dateTime, QLocale::NarrowFormat));
+ auto dateString = o->property("dateString").toString();
+ QCOMPARE(dateString, QLocale("de_DE").toString(date, QLocale::ShortFormat));
+
+ QString warningMsg = url.toString() + QLatin1String(":11: Error: Qt.formatTime(): Third argument must be a Locale format option");
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, warningMsg.toUtf8().constData());
+ QMetaObject::invokeMethod(o.get(), "invalidUsage");
}
void tst_qqmlqt::isQtObject()
@@ -1174,6 +1201,7 @@ void tst_qqmlqt::qtObjectContents()
class TimeProvider: public QObject
{
Q_OBJECT
+ QML_NAMED_ELEMENT(TimeProvider)
Q_PROPERTY(QTime time READ time WRITE setTime NOTIFY timeChanged)
public:
@@ -1254,13 +1282,14 @@ void tst_qqmlqt::timeRoundtrip()
TimeZoneSwitch tzs(QTest::currentDataTag());
QFETCH(QTime, time);
+ qmlRegisterTypesAndRevisions<TimeProvider>("Test", 1);
TimeProvider tp(time);
QQmlEngine eng;
- eng.rootContext()->setContextProperty(QLatin1String("tp"), &tp);
+ //qmlRegisterSingletonInstance("Test", 1, 0, "TimeProvider", &tp);
QQmlComponent component(&eng, testFileUrl("timeRoundtrip.qml"));
- QObject *obj = component.create();
+ QObject *obj = component.createWithInitialProperties({{"tp", QVariant::fromValue(&tp)}});
QVERIFY(obj != nullptr);
// QML reads m_getTime and saves the result as m_putTime; this should come out the same, without
diff --git a/tests/auto/qml/qqmltablemodel/qqmltablemodel.pro b/tests/auto/qml/qqmltablemodel/qqmltablemodel.pro
index 9d298dfdf2..11b11132aa 100644
--- a/tests/auto/qml/qqmltablemodel/qqmltablemodel.pro
+++ b/tests/auto/qml/qqmltablemodel/qqmltablemodel.pro
@@ -7,4 +7,4 @@ include (../../shared/util.pri)
TESTDATA = data/*
-QT += core gui qml-private qml quick-private quick testlib qmlmodels-private
+QT += core gui qml-private qml quick-private quick testlib
diff --git a/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp b/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
index 321896a8f3..3923824fa2 100644
--- a/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
+++ b/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -29,8 +29,8 @@
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
#include <QtCore/qregularexpression.h>
+#include <QtCore/qabstractitemmodel.h>
#include <QtQml/private/qqmlengine_p.h>
-#include <QtQmlModels/private/qqmltablemodel_p.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
@@ -69,7 +69,7 @@ void tst_QQmlTableModel::appendRemoveRow()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>();
+ auto *model = view.rootObject()->property("testModel") .value<QAbstractTableModel *>();
QVERIFY(model);
QCOMPARE(model->rowCount(), 2);
QCOMPARE(model->columnCount(), 2);
@@ -214,7 +214,7 @@ void tst_QQmlTableModel::appendRowToEmptyModel()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>();
+ auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>();
QVERIFY(model);
QCOMPARE(model->rowCount(), 0);
QCOMPARE(model->columnCount(), 2);
@@ -249,7 +249,7 @@ void tst_QQmlTableModel::clear()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>();
+ auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>();
QVERIFY(model);
QCOMPARE(model->rowCount(), 2);
QCOMPARE(model->columnCount(), 2);
@@ -288,7 +288,7 @@ void tst_QQmlTableModel::getRow()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>();
+ auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>();
QVERIFY(model);
QCOMPARE(model->rowCount(), 2);
QCOMPARE(model->columnCount(), 2);
@@ -319,7 +319,7 @@ void tst_QQmlTableModel::insertRow()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>();
+ auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>();
QVERIFY(model);
QCOMPARE(model->rowCount(), 2);
QCOMPARE(model->columnCount(), 2);
@@ -475,7 +475,7 @@ void tst_QQmlTableModel::moveRow()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>();
+ auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>();
QVERIFY(model);
QCOMPARE(model->columnCount(), 2);
QCOMPARE(model->rowCount(), 2);
@@ -603,7 +603,7 @@ void tst_QQmlTableModel::setRow()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>();
+ auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>();
QVERIFY(model);
QCOMPARE(model->columnCount(), 2);
QCOMPARE(model->rowCount(), 2);
@@ -763,7 +763,7 @@ void tst_QQmlTableModel::setDataThroughDelegate()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>();
+ auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>();
QVERIFY(model);
QCOMPARE(model->rowCount(), 2);
QCOMPARE(model->columnCount(), 2);
@@ -826,7 +826,7 @@ void tst_QQmlTableModel::setRowsImperatively()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>();
+ auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>();
QVERIFY(model);
QCOMPARE(model->rowCount(), 0);
QCOMPARE(model->columnCount(), 2);
@@ -863,7 +863,7 @@ void tst_QQmlTableModel::setRowsMultipleTimes()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>();
+ auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>();
QVERIFY(model);
QCOMPARE(model->rowCount(), 2);
QCOMPARE(model->columnCount(), 2);
@@ -920,7 +920,7 @@ void tst_QQmlTableModel::dataAndEditing()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QQmlTableModel *model = view.rootObject()->property("model").value<QQmlTableModel*>();
+ auto *model = view.rootObject()->property("model").value<QAbstractTableModel*>();
QVERIFY(model);
const QHash<int, QByteArray> roleNames = model->roleNames();
@@ -940,7 +940,7 @@ void tst_QQmlTableModel::omitTableModelColumnIndex()
QQmlComponent component(&engine, testFileUrl("omitTableModelColumnIndex.qml"));
QCOMPARE(component.status(), QQmlComponent::Ready);
- QScopedPointer<QQmlTableModel> model(qobject_cast<QQmlTableModel*>(component.create()));
+ QScopedPointer<QAbstractTableModel> model(qobject_cast<QAbstractTableModel*>(component.create()));
QVERIFY(model);
QCOMPARE(model->rowCount(), 2);
QCOMPARE(model->columnCount(), 2);
@@ -964,7 +964,7 @@ void tst_QQmlTableModel::complexRow()
QCOMPARE(tableView->rows(), 2);
QCOMPARE(tableView->columns(), 2);
- QQmlTableModel *model = tableView->model().value<QQmlTableModel*>();
+ auto *model = tableView->model().value<QAbstractTableModel*>();
QVERIFY(model);
QCOMPARE(model->rowCount(), 2);
QCOMPARE(model->columnCount(), 2);
@@ -983,7 +983,7 @@ void tst_QQmlTableModel::appendRowWithDouble()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>();
+ auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>();
QVERIFY(model);
QCOMPARE(model->rowCount(), 2);
QCOMPARE(model->columnCount(), 2);
diff --git a/tests/auto/qml/qqmltypeloader/data/declarativeCppType.qml b/tests/auto/qml/qqmltypeloader/data/declarativeCppType.qml
new file mode 100644
index 0000000000..9061f3beb5
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/declarativeCppType.qml
@@ -0,0 +1,6 @@
+import QtQml 2.0
+import declarative.import.for.typeloader.test 3.2
+
+DeclarativeTestType {
+ objectName: "ddddd"
+}
diff --git a/tests/auto/qml/qqmltypeloader/declarativetesttype.h b/tests/auto/qml/qqmltypeloader/declarativetesttype.h
new file mode 100644
index 0000000000..a21cdcfd1d
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/declarativetesttype.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DECLARATIVETESTTYPE_H
+#define DECLARATIVETESTTYPE_H
+
+#include <QObject>
+#include <qqml.h>
+
+class DeclarativeTestType : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+public:
+ explicit DeclarativeTestType(QObject *parent = nullptr) : QObject(parent) {}
+};
+
+#endif // DECLARATIVETESTTYPE_H
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
index 9ad53aaa8b..266a4e97d6 100644
--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
+++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
@@ -58,9 +58,11 @@ private slots:
void qmlSingletonWithinModule();
void multiSingletonModule();
void implicitComponentModule();
+ void customDiskCachePath();
void qrcRootPathUrl();
void implicitImport();
void compositeSingletonCycle();
+ void declarativeCppType();
};
void tst_QQMLTypeLoader::testLoadComplete()
@@ -94,6 +96,8 @@ void tst_QQMLTypeLoader::trimCache()
{
QQmlEngine engine;
QQmlTypeLoader &loader = QQmlEnginePrivate::get(&engine)->typeLoader;
+ QVector<QQmlTypeData *> releaseLater;
+ QVector<QV4::ExecutableCompilationUnit *> releaseCompilationUnitLater;
for (int i = 0; i < 256; ++i) {
QUrl url = testFileUrl("trim_cache.qml");
url.setQuery(QString::number(i));
@@ -106,8 +110,10 @@ void tst_QQMLTypeLoader::trimCache()
// QQmlTypeData or its compiledData() should prevent the trimming.
if (i % 10 == 0) {
// keep ref on data, don't add ref on data->compiledData()
+ releaseLater.append(data);
} else if (i % 5 == 0) {
data->compilationUnit()->addref();
+ releaseCompilationUnitLater.append(data->compilationUnit());
data->release();
} else {
data->release();
@@ -123,6 +129,12 @@ void tst_QQMLTypeLoader::trimCache()
QVERIFY(!loader.isTypeLoaded(url));
// The cache is free to keep the others.
}
+
+ for (auto *data : qAsConst(releaseCompilationUnitLater))
+ data->release();
+
+ for (auto *data : qAsConst(releaseLater))
+ data->release();
}
void tst_QQMLTypeLoader::trimCache2()
@@ -508,6 +520,35 @@ void tst_QQMLTypeLoader::implicitComponentModule()
checkCleanCacheLoad(QLatin1String("implicitComponentModule"));
}
+void tst_QQMLTypeLoader::customDiskCachePath()
+{
+#if QT_CONFIG(process)
+ const char *skipKey = "QT_TST_QQMLTYPELOADER_SKIP_MISMATCH";
+ if (qEnvironmentVariableIsSet(skipKey)) {
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("Base.qml"));
+ QCOMPARE(component.status(), QQmlComponent::Ready);
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ return;
+ }
+
+ QTemporaryDir dir;
+ QProcess child;
+ child.setProgram(QCoreApplication::applicationFilePath());
+ child.setArguments(QStringList(QLatin1String("customDiskCachePath")));
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ env.insert(QLatin1String(skipKey), QLatin1String("1"));
+ env.insert(QLatin1String("QML_DISK_CACHE_PATH"), dir.path());
+ child.setProcessEnvironment(env);
+ child.start();
+ QVERIFY(child.waitForFinished());
+ QCOMPARE(child.exitCode(), 0);
+ QDir cacheDir(dir.path());
+ QVERIFY(!cacheDir.isEmpty());
+#endif
+}
+
void tst_QQMLTypeLoader::qrcRootPathUrl()
{
QQmlEngine engine;
@@ -542,6 +583,15 @@ void tst_QQMLTypeLoader::compositeSingletonCycle()
QCOMPARE(qvariant_cast<QColor>(object->property("color")), QColorConstants::Black);
}
+void tst_QQMLTypeLoader::declarativeCppType()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("declarativeCppType.qml"));
+ QCOMPARE(component.status(), QQmlComponent::Ready);
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+}
+
QTEST_MAIN(tst_QQMLTypeLoader)
#include "tst_qqmltypeloader.moc"
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro
index 0352561e03..19834ff537 100644
--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro
+++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro
@@ -1,4 +1,4 @@
-CONFIG += testcase
+CONFIG += testcase qmltypes
TARGET = tst_qqmltypeloader
QT += qml testlib qml-private quick
macx:CONFIG -= app_bundle
@@ -8,7 +8,10 @@ SOURCES += \
../../shared/testhttpserver.cpp
HEADERS += \
- ../../shared/testhttpserver.h
+ ../../shared/testhttpserver.h \
+ declarativetesttype.h
-include (../../shared/util.pri)
+QML_IMPORT_VERSION = 3.2
+QML_IMPORT_NAME = "declarative.import.for.typeloader.test"
+include (../../shared/util.pri)
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/data/userType.qml b/tests/auto/qml/qqmlvaluetypeproviders/data/userType.qml
index d2f748c4c4..2aa03ed39f 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/data/userType.qml
+++ b/tests/auto/qml/qqmlvaluetypeproviders/data/userType.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
import Test 1.0
Item {
+ required property TestValueExporter testValueExporter
property bool success: false
// Test user value type stored as both var and variant
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp
index 22074602b7..b44889798c 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp
+++ b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp
@@ -256,6 +256,7 @@ class TestValueExporter : public QObject
{
Q_OBJECT
Q_PROPERTY(TestValue testValue READ testValue WRITE setTestValue)
+ QML_NAMED_ELEMENT(TestValueExporter)
public:
TestValue testValue() const { return m_testValue; }
void setTestValue(const TestValue &v) { m_testValue = v; }
@@ -275,15 +276,14 @@ void tst_qqmlvaluetypeproviders::userType()
qRegisterMetaType<TestValue>();
QMetaType::registerComparators<TestValue>();
- qmlRegisterType<TestValueExporter>("Test", 1, 0, "TestValueExporter");
+ qmlRegisterTypesAndRevisions<TestValueExporter>("Test", 1);
TestValueExporter exporter;
QQmlEngine e;
- e.rootContext()->setContextProperty("testValueExporter", &exporter);
QQmlComponent component(&e, testFileUrl("userType.qml"));
- QScopedPointer<QObject> obj(component.create());
+ QScopedPointer<QObject> obj(component.createWithInitialProperties({{"testValueExporter", QVariant::fromValue(&exporter)}}));
QVERIFY(obj != nullptr);
QCOMPARE(obj->property("success").toBool(), true);
}
diff --git a/tests/auto/qml/qqmlvaluetypes/data/qmlproperty_read.qml b/tests/auto/qml/qqmlvaluetypes/data/qmlproperty_read.qml
new file mode 100644
index 0000000000..b9c9ee779b
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypes/data/qmlproperty_read.qml
@@ -0,0 +1,9 @@
+import Test 1.0
+import QtQml 2.0
+
+MyTypeObject {
+ property QtObject colorPropertyObject: colorProperty.object
+ property string colorPropertyName: colorProperty.name
+ property QtObject invalidPropertyObject: invalidProperty.object
+ property string invalidPropertyName: invalidProperty.name
+}
diff --git a/tests/auto/qml/qqmlvaluetypes/testtypes.h b/tests/auto/qml/qqmlvaluetypes/testtypes.h
index 798c96e188..78797f06b1 100644
--- a/tests/auto/qml/qqmlvaluetypes/testtypes.h
+++ b/tests/auto/qml/qqmlvaluetypes/testtypes.h
@@ -48,6 +48,8 @@
#include <private/qqmlproperty_p.h>
#include <private/qqmlpropertyvalueinterceptor_p.h>
+Q_DECLARE_METATYPE(QQmlProperty)
+
class MyTypeObject : public QObject
{
Q_OBJECT
@@ -71,6 +73,8 @@ class MyTypeObject : public QObject
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY changed)
Q_PROPERTY(QColor invalidColor READ invalidColor CONSTANT)
Q_PROPERTY(QVariant variant READ variant NOTIFY changed)
+ Q_PROPERTY(QQmlProperty colorProperty READ colorProperty CONSTANT)
+ Q_PROPERTY(QQmlProperty invalidProperty READ invalidProperty CONSTANT)
public:
MyTypeObject() :
@@ -173,6 +177,10 @@ public:
QVariant variant() const { return sizef(); }
+ QQmlProperty colorProperty() { return QQmlProperty(this, "color"); }
+
+ QQmlProperty invalidProperty() const { return QQmlProperty(); }
+
void emitRunScript() { emit runScript(); }
signals:
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index 3e9047cc5a..7c75743311 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -67,6 +67,7 @@ private slots:
void color();
void variant();
void locale();
+ void qmlproperty();
void bindingAssignment();
void bindingRead();
@@ -360,6 +361,20 @@ 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);
+
+ QCOMPARE(object->property("colorPropertyObject").value<QObject *>(), object);
+ QCOMPARE(object->property("colorPropertyName").toString(), "color");
+ QCOMPARE(object->property("invalidPropertyObject").value<QObject *>(), nullptr);
+ QCOMPARE(object->property("invalidPropertyName").toString(), "");
+
+ delete object;
+}
+
void tst_qqmlvaluetypes::sizereadonly()
{
{
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/file_request.qml b/tests/auto/qml/qqmlxmlhttprequest/data/file_request.qml
new file mode 100644
index 0000000000..51020c185e
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/file_request.qml
@@ -0,0 +1,32 @@
+import QtQuick 2.0
+
+QtObject {
+ // Inputs
+
+ id: root
+
+ property string writeURL
+ property string readURL
+ // Outputs
+ property bool writeDone: false
+ property variant readResult
+
+ Component.onCompleted: {
+ // PUT
+ var xhrWrite = new XMLHttpRequest;
+ xhrWrite.open("PUT", writeURL);
+ xhrWrite.onreadystatechange = function() {
+ if (xhrWrite.readyState === XMLHttpRequest.DONE)
+ writeDone = true;
+ };
+ xhrWrite.send("Test-String");
+ // GET
+ var xhrRead = new XMLHttpRequest;
+ xhrRead.open("GET", readURL);
+ xhrRead.onreadystatechange = function() {
+ if (xhrRead.readyState === XMLHttpRequest.DONE)
+ readResult = xhrRead.responseText;
+ };
+ xhrRead.send();
+ }
+}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
index 6cf80ccfdb..ae794e76a9 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
+++ b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
@@ -35,6 +35,13 @@
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
+#include <QTemporaryFile>
+
+#if QT_CONFIG(process)
+#include <QProcess>
+#include <QProcessEnvironment>
+#endif
+
#include "testhttpserver.h"
#include "../../shared/util.h"
@@ -45,6 +52,8 @@ public:
tst_qqmlxmlhttprequest() {}
private slots:
+ void initTestCase();
+
void domExceptionCodes();
void callbackException();
void callbackException_data();
@@ -97,6 +106,14 @@ private slots:
void nonUtf8();
void nonUtf8_data();
+ void sendFileRequest();
+
+#if QT_CONFIG(process)
+ void sendFileRequestNotSet();
+ void sendFileRequestNoWrite();
+ void sendFileRequestNoRead();
+#endif
+
// WebDAV
void sendPropfind();
void sendPropfind_data();
@@ -119,13 +136,27 @@ private slots:
void stateChangeCallingContext();
private:
- QQmlEngine engine;
+ void doFileRequest(std::function<void(QObject *component, QTemporaryFile &writeFile)> verifyFunction);
+
+ QScopedPointer<QQmlEngine> engine;
};
+void tst_qqmlxmlhttprequest::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+
+ if (!qEnvironmentVariableIsSet("TEST_CUSTOM_PERMISSIONS")) {
+ qputenv("QML_XHR_ALLOW_FILE_READ", "1");
+ qputenv("QML_XHR_ALLOW_FILE_WRITE", "1");
+ }
+
+ engine.reset(new QQmlEngine);
+}
+
// Test that the dom exception codes are correct
void tst_qqmlxmlhttprequest::domExceptionCodes()
{
- QQmlComponent component(&engine, testFileUrl("domExceptionCodes.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("domExceptionCodes.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -168,8 +199,8 @@ void tst_qqmlxmlhttprequest::callbackException()
QString expect = testFileUrl("callbackException.qml").toString() + ":"+QString::number(line)+": Error: Exception from Callback";
QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
- QQmlComponent component(&engine, testFileUrl("callbackException.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("callbackException.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", "testdocument.html");
object->setProperty("which", which);
@@ -182,7 +213,7 @@ void tst_qqmlxmlhttprequest::callbackException()
// ### WebKit does not do this, but it seems to fit the standard and QML better
void tst_qqmlxmlhttprequest::staticStateValues()
{
- QQmlComponent component(&engine, testFileUrl("staticStateValues.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("staticStateValues.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -196,7 +227,7 @@ void tst_qqmlxmlhttprequest::staticStateValues()
// Test that the state value properties on instances have the correct values.
void tst_qqmlxmlhttprequest::instanceStateValues()
{
- QQmlComponent component(&engine, testFileUrl("instanceStateValues.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("instanceStateValues.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -210,7 +241,7 @@ void tst_qqmlxmlhttprequest::instanceStateValues()
// Test calling constructor
void tst_qqmlxmlhttprequest::constructor()
{
- QQmlComponent component(&engine, testFileUrl("constructor.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("constructor.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -221,7 +252,7 @@ void tst_qqmlxmlhttprequest::constructor()
// Test that all the properties are set correctly before any request is sent
void tst_qqmlxmlhttprequest::defaultState()
{
- QQmlComponent component(&engine, testFileUrl("defaultState.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("defaultState.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -248,8 +279,8 @@ void tst_qqmlxmlhttprequest::open()
url = server.urlString(url);
}
- QQmlComponent component(&engine, qmlFile);
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), qmlFile);
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", url);
component.completeCreate();
@@ -281,7 +312,7 @@ void tst_qqmlxmlhttprequest::open_data()
// Test that calling XMLHttpRequest.open() with an invalid method raises an exception
void tst_qqmlxmlhttprequest::open_invalid_method()
{
- QQmlComponent component(&engine, testFileUrl("open_invalid_method.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("open_invalid_method.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -330,8 +361,8 @@ void tst_qqmlxmlhttprequest::open_sync()
{
TestThreadedHTTPServer server(testFileUrl("open_network.expect"), testFileUrl("open_network.reply"), testFileUrl("testdocument.html"));
- QQmlComponent component(&engine, testFileUrl("open_sync.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("open_sync.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.serverBaseUrl.resolved(QStringLiteral("/testdocument.html")).toString());
component.completeCreate();
@@ -343,7 +374,7 @@ void tst_qqmlxmlhttprequest::open_sync()
void tst_qqmlxmlhttprequest::open_arg_count()
{
{
- QQmlComponent component(&engine, testFileUrl("open_arg_count.1.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("open_arg_count.1.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -351,7 +382,7 @@ void tst_qqmlxmlhttprequest::open_arg_count()
}
{
- QQmlComponent component(&engine, testFileUrl("open_arg_count.2.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("open_arg_count.2.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -368,8 +399,8 @@ void tst_qqmlxmlhttprequest::setRequestHeader()
testFileUrl("setRequestHeader.reply"),
testFileUrl("testdocument.html")));
- QQmlComponent component(&engine, testFileUrl("setRequestHeader.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("setRequestHeader.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/testdocument.html"));
component.completeCreate();
@@ -386,8 +417,8 @@ void tst_qqmlxmlhttprequest::setRequestHeader_caseInsensitive()
testFileUrl("setRequestHeader.reply"),
testFileUrl("testdocument.html")));
- QQmlComponent component(&engine, testFileUrl("setRequestHeader_caseInsensitive.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("setRequestHeader_caseInsensitive.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/testdocument.html"));
component.completeCreate();
@@ -397,7 +428,7 @@ void tst_qqmlxmlhttprequest::setRequestHeader_caseInsensitive()
// Test setting headers before open() throws exception
void tst_qqmlxmlhttprequest::setRequestHeader_unsent()
{
- QQmlComponent component(&engine, testFileUrl("setRequestHeader_unsent.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("setRequestHeader_unsent.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -443,8 +474,8 @@ void tst_qqmlxmlhttprequest::setRequestHeader_illegalName()
testFileUrl("open_network.reply"),
testFileUrl("testdocument.html")));
- QQmlComponent component(&engine, testFileUrl("setRequestHeader_illegalName.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("setRequestHeader_illegalName.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/testdocument.html"));
object->setProperty("header", name);
@@ -469,8 +500,8 @@ void tst_qqmlxmlhttprequest::setRequestHeader_sent()
testFileUrl("open_network.reply"),
testFileUrl("testdocument.html")));
- QQmlComponent component(&engine, testFileUrl("setRequestHeader_sent.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("setRequestHeader_sent.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/testdocument.html"));
component.completeCreate();
@@ -483,7 +514,7 @@ void tst_qqmlxmlhttprequest::setRequestHeader_sent()
// Invalid arg count throws exception
void tst_qqmlxmlhttprequest::setRequestHeader_args()
{
- QQmlComponent component(&engine, testFileUrl("setRequestHeader_args.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("setRequestHeader_args.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -493,7 +524,7 @@ void tst_qqmlxmlhttprequest::setRequestHeader_args()
// Test that calling send() in UNSENT state throws an exception
void tst_qqmlxmlhttprequest::send_unsent()
{
- QQmlComponent component(&engine, testFileUrl("send_unsent.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("send_unsent.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -503,7 +534,7 @@ void tst_qqmlxmlhttprequest::send_unsent()
// Test attempting to resend a sent request throws an exception
void tst_qqmlxmlhttprequest::send_alreadySent()
{
- QQmlComponent component(&engine, testFileUrl("send_alreadySent.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("send_alreadySent.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -521,8 +552,8 @@ void tst_qqmlxmlhttprequest::send_ignoreData()
testFileUrl("send_ignoreData.reply"),
testFileUrl("testdocument.html")));
- QQmlComponent component(&engine, testFileUrl("send_ignoreData.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("send_ignoreData.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("reqType", "GET");
object->setProperty("url", server.urlString("/testdocument.html"));
@@ -538,8 +569,8 @@ void tst_qqmlxmlhttprequest::send_ignoreData()
testFileUrl("send_ignoreData.reply"),
QUrl()));
- QQmlComponent component(&engine, testFileUrl("send_ignoreData.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("send_ignoreData.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("reqType", "HEAD");
object->setProperty("url", server.urlString("/testdocument.html"));
@@ -555,8 +586,8 @@ void tst_qqmlxmlhttprequest::send_ignoreData()
testFileUrl("send_ignoreData.reply"),
QUrl()));
- QQmlComponent component(&engine, testFileUrl("send_ignoreData.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("send_ignoreData.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("reqType", "DELETE");
object->setProperty("url", server.urlString("/testdocument.html"));
@@ -578,8 +609,8 @@ void tst_qqmlxmlhttprequest::send_withdata()
testFileUrl("send_data.reply"),
testFileUrl("testdocument.html")));
- QQmlComponent component(&engine, testFileUrl(file_qml));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl(file_qml));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/testdocument.html"));
component.completeCreate();
@@ -615,8 +646,8 @@ void tst_qqmlxmlhttprequest::send_options()
testFileUrl(file_reply),
testFileUrl("testdocument.html")));
- QQmlComponent component(&engine, testFileUrl(file_qml));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl(file_qml));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
QString url = server.baseUrl().toString();
if (url_suffix != "/")
@@ -652,8 +683,8 @@ void tst_qqmlxmlhttprequest::send_patch()
// the content of response file will be ignored due to 204 status code
testFileUrl("testdocument.html")));
- QQmlComponent component(&engine, testFileUrl("send_patch.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("send_patch.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/qqmlxmlhttprequest.cpp"));
component.completeCreate();
@@ -666,8 +697,8 @@ void tst_qqmlxmlhttprequest::send_patch()
// Test abort() has no effect in unsent state
void tst_qqmlxmlhttprequest::abort_unsent()
{
- QQmlComponent component(&engine, testFileUrl("abort_unsent.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("abort_unsent.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", "testdocument.html");
component.completeCreate();
@@ -685,8 +716,8 @@ void tst_qqmlxmlhttprequest::abort_unsent()
// Test abort() cancels an open (but unsent) request
void tst_qqmlxmlhttprequest::abort_opened()
{
- QQmlComponent component(&engine, testFileUrl("abort_opened.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("abort_opened.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", "testdocument.html");
component.completeCreate();
@@ -710,8 +741,8 @@ void tst_qqmlxmlhttprequest::abort()
testFileUrl("abort.reply"),
testFileUrl("testdocument.html")));
- QQmlComponent component(&engine, testFileUrl("abort.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("abort.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
const QUrl url = server.url("/testdocument.html");
QUrl dummyUrl = url;
@@ -767,7 +798,7 @@ void tst_qqmlxmlhttprequest::getResponseHeader()
// Test getResponseHeader throws an exception in an invalid state
void tst_qqmlxmlhttprequest::getResponseHeader_unsent()
{
- QQmlComponent component(&engine, testFileUrl("getResponseHeader_unsent.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("getResponseHeader_unsent.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -777,7 +808,7 @@ void tst_qqmlxmlhttprequest::getResponseHeader_unsent()
// Test getResponseHeader throws an exception in an invalid state
void tst_qqmlxmlhttprequest::getResponseHeader_sent()
{
- QQmlComponent component(&engine, testFileUrl("getResponseHeader_sent.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("getResponseHeader_sent.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -787,7 +818,7 @@ void tst_qqmlxmlhttprequest::getResponseHeader_sent()
// Invalid arg count throws exception
void tst_qqmlxmlhttprequest::getResponseHeader_args()
{
- QQmlComponent component(&engine, testFileUrl("getResponseHeader_args.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("getResponseHeader_args.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -827,7 +858,7 @@ void tst_qqmlxmlhttprequest::getAllResponseHeaders()
// Test getAllResponseHeaders throws an exception in an invalid state
void tst_qqmlxmlhttprequest::getAllResponseHeaders_unsent()
{
- QQmlComponent component(&engine, testFileUrl("getAllResponseHeaders_unsent.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("getAllResponseHeaders_unsent.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -837,7 +868,7 @@ void tst_qqmlxmlhttprequest::getAllResponseHeaders_unsent()
// Test getAllResponseHeaders throws an exception in an invalid state
void tst_qqmlxmlhttprequest::getAllResponseHeaders_sent()
{
- QQmlComponent component(&engine, testFileUrl("getAllResponseHeaders_sent.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("getAllResponseHeaders_sent.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -847,7 +878,7 @@ void tst_qqmlxmlhttprequest::getAllResponseHeaders_sent()
// Invalid arg count throws exception
void tst_qqmlxmlhttprequest::getAllResponseHeaders_args()
{
- QQmlComponent component(&engine, testFileUrl("getAllResponseHeaders_args.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("getAllResponseHeaders_args.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -862,8 +893,8 @@ void tst_qqmlxmlhttprequest::getBinaryData()
testFileUrl("receive_binary_data.reply"),
testFileUrl("qml_logo.png")));
- QQmlComponent component(&engine, testFileUrl("receiveBinaryData.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("receiveBinaryData.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/gml_logo.png"));
component.completeCreate();
@@ -881,8 +912,8 @@ void tst_qqmlxmlhttprequest::getJsonData()
testFileUrl("receive_binary_data.reply"),
testFileUrl("json.data")));
- QQmlComponent component(&engine, testFileUrl("receiveJsonData.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("receiveJsonData.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/json.data"));
component.completeCreate();
@@ -901,8 +932,8 @@ void tst_qqmlxmlhttprequest::status()
replyUrl,
testFileUrl("testdocument.html")));
- QQmlComponent component(&engine, testFileUrl("status.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("status.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/testdocument.html"));
object->setProperty("expectedStatus", status);
@@ -943,8 +974,8 @@ void tst_qqmlxmlhttprequest::statusText()
replyUrl,
testFileUrl("testdocument.html")));
- QQmlComponent component(&engine, testFileUrl("statusText.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("statusText.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/testdocument.html"));
object->setProperty("expectedStatus", statusText);
@@ -983,8 +1014,8 @@ void tst_qqmlxmlhttprequest::responseText()
replyUrl,
bodyUrl));
- QQmlComponent component(&engine, testFileUrl("responseText.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("responseText.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/testdocument.html"));
object->setProperty("expectedText", responseText);
@@ -1020,7 +1051,7 @@ void tst_qqmlxmlhttprequest::nonUtf8()
QFETCH(QString, responseText);
QFETCH(QString, xmlRootNodeValue);
- QQmlComponent component(&engine, testFileUrl("utf16.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("utf16.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -1053,6 +1084,163 @@ void tst_qqmlxmlhttprequest::nonUtf8_data()
QTest::newRow("responseXML") << "utf16.xml" << "<?xml version=\"1.0\" encoding=\"UTF-16\" standalone='yes'?>\n<root>\n" + uc + "\n</root>\n" << QString('\n' + uc + '\n');
}
+static const QString testString = QStringLiteral("Test-String");
+
+void tst_qqmlxmlhttprequest::doFileRequest(std::function<void(QObject *component, QTemporaryFile &writeFile)> verifyFunction)
+{
+ // Create test files
+ QTemporaryFile writeFile;
+ QTemporaryFile readFile;
+
+ writeFile.open();
+ writeFile.close();
+
+ QVERIFY(readFile.open());
+ readFile.write(testString.toUtf8());
+ readFile.close();
+
+ // Avoid cached environment variables
+ QQmlEngine engine;
+
+ QQmlComponent component(&engine, testFileUrl("file_request.qml"));
+
+ const QVariantMap properties = {
+ {"writeURL", QUrl::fromLocalFile(writeFile.fileName()).toString()},
+ {"readURL", QUrl::fromLocalFile(readFile.fileName()).toString()}
+ };
+
+ QScopedPointer<QObject> object(component.createWithInitialProperties(properties, engine.rootContext()));
+ QVERIFY(!object.isNull());
+
+ verifyFunction(object.get(), writeFile);
+}
+
+// Test file:// requests
+void tst_qqmlxmlhttprequest::sendFileRequest()
+{
+ // Test with both writing and reading allowed
+ doFileRequest([](QObject* object, QTemporaryFile &writeFile) {
+ QTRY_COMPARE(object->property("readResult").toString(), testString);
+
+ QTRY_VERIFY(object->property("writeDone").toBool());
+
+ QVERIFY(writeFile.open());
+ QCOMPARE(QString::fromUtf8(writeFile.readAll()), testString);
+ writeFile.close();
+ });
+}
+
+#if QT_CONFIG(process)
+void tst_qqmlxmlhttprequest::sendFileRequestNotSet() {
+ if (qEnvironmentVariableIsSet("TEST_CUSTOM_PERMISSIONS")) {
+ // Test with no settings
+ // Should just result in warnings in Qt 5
+ doFileRequest([](QObject* object, QTemporaryFile &writeFile) {
+ QTRY_COMPARE(object->property("readResult").toString(), testString);
+
+ QTRY_VERIFY(object->property("writeDone").toBool());
+
+ QVERIFY(writeFile.open());
+ QCOMPARE(QString::fromUtf8(writeFile.readAll()), testString);
+ writeFile.close();
+ });
+ return;
+ }
+
+ QProcess child;
+ child.setProgram(QCoreApplication::applicationFilePath());
+ child.setArguments(QStringList(QLatin1String("sendFileRequestNotSet")));
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ env.insert(QLatin1String("TEST_CUSTOM_PERMISSIONS"), QLatin1String("1"));
+ env.remove("QML_XHR_ALLOW_FILE_WRITE");
+ env.remove("QML_XHR_ALLOW_FILE_READ");
+ child.setProcessEnvironment(env);
+ child.start();
+ QVERIFY(child.waitForFinished());
+
+ // Check exit code
+ QCOMPARE(child.exitCode(), 0);
+
+ // Check if all warnings were printed
+ QString output = QString::fromUtf8(child.readAllStandardOutput());
+
+
+ const QString readingWarning = QLatin1String(
+ "XMLHttpRequest: Using GET on a local file is dangerous "
+ "and will be disabled by default in a future Qt version."
+ "Set QML_XHR_ALLOW_FILE_READ to 1 if you wish to continue using this feature.");
+
+ const QString writingWarning = QLatin1String(
+ "XMLHttpRequest: Using PUT on a local file is dangerous "
+ "and will be disabled by default in a future Qt version."
+ "Set QML_XHR_ALLOW_FILE_WRITE to 1 if you wish to continue using this feature.");
+
+ QVERIFY(output.contains(readingWarning));
+ QVERIFY(output.contains(writingWarning));
+}
+#endif
+
+#if QT_CONFIG(process)
+void tst_qqmlxmlhttprequest::sendFileRequestNoWrite() {
+ if (qEnvironmentVariableIsSet("TEST_CUSTOM_PERMISSIONS")) {
+ // Test with no writing enabled
+ doFileRequest([](QObject* object, QTemporaryFile &writeFile) {
+ QTRY_COMPARE(object->property("readResult").toString(), testString);
+
+ // Check that the file stays empty
+ QVERIFY(writeFile.open());
+ QCOMPARE(QString::fromUtf8(writeFile.readAll()), "");
+ writeFile.close();
+ });
+ return;
+ }
+
+ QProcess child;
+ child.setProgram(QCoreApplication::applicationFilePath());
+ child.setArguments(QStringList(QLatin1String("sendFileRequestNoWrite")));
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ env.insert(QLatin1String("TEST_CUSTOM_PERMISSIONS"), QLatin1String("1"));
+ env.insert(QLatin1String("QML_XHR_ALLOW_FILE_WRITE"), QLatin1String("0"));
+ env.insert(QLatin1String("QML_XHR_ALLOW_FILE_READ"), QLatin1String("1"));
+ child.setProcessEnvironment(env);
+ child.start();
+ QVERIFY(child.waitForFinished());
+ QCOMPARE(child.exitCode(), 0);
+}
+#endif
+
+#if QT_CONFIG(process)
+void tst_qqmlxmlhttprequest::sendFileRequestNoRead() {
+ if (qEnvironmentVariableIsSet("TEST_CUSTOM_PERMISSIONS")) {
+ // Test with no reading enabled
+ doFileRequest([](QObject* object, QTemporaryFile &writeFile) {
+ // Check that the write happens
+ QTRY_VERIFY(object->property("writeDone").toBool());
+
+ QVERIFY(writeFile.open());
+ QCOMPARE(QString::fromUtf8(writeFile.readAll()), testString);
+ writeFile.close();
+
+ // Verify that the read has not yielded any value
+ QVERIFY(object->property("readResult").isNull());
+ });
+ return;
+ }
+
+ QProcess child;
+ child.setProgram(QCoreApplication::applicationFilePath());
+ child.setArguments(QStringList(QLatin1String("sendFileRequestNoRead")));
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ env.insert(QLatin1String("TEST_CUSTOM_PERMISSIONS"), QLatin1String("1"));
+ env.insert(QLatin1String("QML_XHR_ALLOW_FILE_WRITE"), QLatin1String("1"));
+ env.insert(QLatin1String("QML_XHR_ALLOW_FILE_READ"), QLatin1String("0"));
+ child.setProcessEnvironment(env);
+ child.start();
+ QVERIFY(child.waitForFinished());
+ QCOMPARE(child.exitCode(), 0);
+}
+#endif
+
void tst_qqmlxmlhttprequest::sendPropfind()
{
const QString prefix = "WebDAV//";
@@ -1070,8 +1258,8 @@ void tst_qqmlxmlhttprequest::sendPropfind()
testFileUrl(prefix + replyHeader),
testFileUrl(prefix + replyBody)));
- QQmlComponent component(&engine, testFileUrl(prefix + qml));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl(prefix + qml));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString(resource));
component.completeCreate();
@@ -1097,7 +1285,7 @@ void tst_qqmlxmlhttprequest::sendPropfind_data()
// throws an exception
void tst_qqmlxmlhttprequest::invalidMethodUsage()
{
- QQmlComponent component(&engine, testFileUrl("invalidMethodUsage.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("invalidMethodUsage.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -1124,8 +1312,8 @@ void tst_qqmlxmlhttprequest::redirects()
server.addRedirect("redirect.html", server.urlString("/redirecttarget.html"));
server.serveDirectory(dataDirectory());
- QQmlComponent component(&engine, testFileUrl("redirects.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("redirects.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/redirect.html"));
object->setProperty("expectedText", "");
@@ -1141,8 +1329,8 @@ void tst_qqmlxmlhttprequest::redirects()
server.addRedirect("redirect.html", server.urlString("/redirectmissing.html"));
server.serveDirectory(dataDirectory());
- QQmlComponent component(&engine, testFileUrl("redirectError.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("redirectError.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/redirect.html"));
object->setProperty("expectedText", "");
@@ -1158,8 +1346,8 @@ void tst_qqmlxmlhttprequest::redirects()
server.addRedirect("redirect.html", server.urlString("/redirect.html"));
server.serveDirectory(dataDirectory());
- QQmlComponent component(&engine, testFileUrl("redirectRecur.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("redirectRecur.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/redirect.html"));
object->setProperty("expectedText", "");
@@ -1177,7 +1365,7 @@ void tst_qqmlxmlhttprequest::redirects()
void tst_qqmlxmlhttprequest::responseXML_invalid()
{
- QQmlComponent component(&engine, testFileUrl("responseXML_invalid.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("responseXML_invalid.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -1189,7 +1377,7 @@ void tst_qqmlxmlhttprequest::responseXML_invalid()
// Test the Document DOM element
void tst_qqmlxmlhttprequest::document()
{
- QQmlComponent component(&engine, testFileUrl("document.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("document.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -1201,7 +1389,7 @@ void tst_qqmlxmlhttprequest::document()
// Test the Element DOM element
void tst_qqmlxmlhttprequest::element()
{
- QQmlComponent component(&engine, testFileUrl("element.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("element.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -1213,7 +1401,7 @@ void tst_qqmlxmlhttprequest::element()
// Test the Attr DOM element
void tst_qqmlxmlhttprequest::attr()
{
- QQmlComponent component(&engine, testFileUrl("attr.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("attr.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -1225,7 +1413,7 @@ void tst_qqmlxmlhttprequest::attr()
// Test the Text DOM element
void tst_qqmlxmlhttprequest::text()
{
- QQmlComponent component(&engine, testFileUrl("text.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("text.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -1238,7 +1426,7 @@ void tst_qqmlxmlhttprequest::text()
// Test the CDataSection DOM element
void tst_qqmlxmlhttprequest::cdata()
{
- QQmlComponent component(&engine, testFileUrl("cdata.qml"));
+ QQmlComponent component(engine.get(), testFileUrl("cdata.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -1285,8 +1473,8 @@ void tst_qqmlxmlhttprequest::stateChangeCallingContext()
QVERIFY2(server.listen(), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
- QQmlComponent component(&engine, testFileUrl("stateChangeCallingContext.qml"));
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQmlComponent component(engine.get(), testFileUrl("stateChangeCallingContext.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("serverBaseUrl", server.baseUrl().toString());
component.completeCreate();
diff --git a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
index ae99e35467..dccd3951b3 100644
--- a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
+++ b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
@@ -76,6 +76,7 @@ private slots:
void sortCaseSensitive_data();
void sortCaseSensitive();
void updateProperties();
+ void importBothVersions();
private:
void checkNoErrors(const QQmlComponent& component);
QQmlEngine engine;
@@ -467,6 +468,22 @@ void tst_qquickfolderlistmodel::updateProperties()
QCOMPARE(showHidden.toBool(), true);
}
+void tst_qquickfolderlistmodel::importBothVersions()
+{
+ {
+ QQmlComponent component(&engine, testFileUrl("sortReversed.qml"));
+ checkNoErrors(component);
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj);
+ }
+ {
+ QQmlComponent component(&engine, testFileUrl("qrc.qml"));
+ checkNoErrors(component);
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj);
+ }
+}
+
QTEST_MAIN(tst_qquickfolderlistmodel)
#include "tst_qquickfolderlistmodel.moc"
diff --git a/tests/auto/qml/qquickworkerscript/data/BaseWorker.qml b/tests/auto/qml/qquickworkerscript/data/BaseWorker.qml
index 0ac56d9b66..1d3420e186 100644
--- a/tests/auto/qml/qquickworkerscript/data/BaseWorker.qml
+++ b/tests/auto/qml/qquickworkerscript/data/BaseWorker.qml
@@ -1,11 +1,14 @@
import QtQuick 2.0
+import QtQml.WorkerScript 2.15
WorkerScript {
id: worker
property variant response
+ property bool readyChangedCalled : false
signal done()
+ signal ready()
function testSend(value) {
worker.sendMessage(value)
@@ -20,5 +23,7 @@ WorkerScript {
worker.response = messageObject
worker.done()
}
+
+ onReadyChanged: worker.readyChangedCalled = true
}
diff --git a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
index d11e7bde4b..2f79f7157f 100644
--- a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
+++ b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
@@ -47,6 +47,7 @@ public:
tst_QQuickWorkerScript() {}
private slots:
void source();
+ void ready();
void messaging();
void messaging_data();
void messaging_sendQObjectList();
@@ -105,6 +106,22 @@ void tst_QQuickWorkerScript::source()
qApp->processEvents();
}
+void tst_QQuickWorkerScript::ready()
+{
+ QQmlComponent component(&m_engine, testFileUrl("worker.qml"));
+ QScopedPointer<QQuickWorkerScript>worker(qobject_cast<QQuickWorkerScript*>(component.create()));
+ QVERIFY(worker != nullptr);
+
+ const QMetaObject *mo = worker->metaObject();
+
+ QTRY_VERIFY(worker->ready());
+
+ QVariant readyChangedCalled = mo->property(mo->indexOfProperty("readyChangedCalled")).read(worker.data()).value<QVariant>();
+
+ QVERIFY(!readyChangedCalled.isNull());
+ QVERIFY(readyChangedCalled.toBool());
+}
+
void tst_QQuickWorkerScript::messaging()
{
QFETCH(QVariant, value);
@@ -152,6 +169,7 @@ void tst_QQuickWorkerScript::messaging_data()
QRegExp::RegExp2));
QTest::newRow("regularexpression") << QVariant::fromValue(QRegularExpression(
"^\\d\\d?$", QRegularExpression::CaseInsensitiveOption));
+ QTest::newRow("url") << QVariant::fromValue(QUrl("http://example.com/foo/bar"));
}
void tst_QQuickWorkerScript::messaging_sendQObjectList()
diff --git a/tests/auto/qmltest/listview/data/MultiDelegate3.qml b/tests/auto/qmltest/listview/data/MultiDelegate3.qml
new file mode 100644
index 0000000000..75116e0f9b
--- /dev/null
+++ b/tests/auto/qmltest/listview/data/MultiDelegate3.qml
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQml.Models 2.12
+import Qt.labs.qmlmodels 1.0
+
+ListView {
+ width: 400
+ height: 400
+
+ property var item1: QtObject {
+ property string dataType: "rect"
+ property color color: "red"
+ }
+ property var item2: QtObject {
+ property string dataType: "text"
+ property string text: "Hello world"
+ }
+ model: [ item1, item2 ]
+
+ delegate: DelegateChooser {
+ role: "dataType"
+ DelegateChoice {
+ roleValue: "rect"
+ delegate: Rectangle {
+ width: parent.width
+ height: 50
+ color: modelData.color
+ }
+ }
+ DelegateChoice {
+ roleValue: "text"
+ delegate: Text {
+ width: parent.width
+ height: 50
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: modelData.text
+ }
+ }
+
+ DelegateChoice {
+ delegate: Item {
+ width: parent.width
+ height: 50
+ }
+ }
+ }
+}
diff --git a/tests/auto/qmltest/listview/tst_listview.qml b/tests/auto/qmltest/listview/tst_listview.qml
index 5e9bb22e8e..bea6b45c3a 100644
--- a/tests/auto/qmltest/listview/tst_listview.qml
+++ b/tests/auto/qmltest/listview/tst_listview.qml
@@ -213,6 +213,10 @@ Item {
id: multiDelegate2
}
+ MultiDelegate3 {
+ id: multiDelegate3
+ }
+
TestCase {
name: "ListView"
when: windowShown
@@ -414,5 +418,18 @@ Item {
var delegate = multiDelegate2.itemAt(10, row.y)
compare(delegate.choiceType, row.type)
}
+
+ function test_multipleDelegates3_data() {
+ return [
+ { y: 25, type: "Rectangle", property: "color", value: "#ff0000" },
+ { y: 75, type: "Text", property: "text", value: "Hello world" }
+ ]
+ }
+
+ function test_multipleDelegates3(row) {
+ var delegate = multiDelegate3.itemAt(10, row.y)
+ verify(delegate.toString().includes(row.type))
+ compare(delegate[row.property], row.value)
+ }
}
}
diff --git a/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp b/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp
index 9bcc21c77d..5d69bf3b21 100644
--- a/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp
+++ b/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp
@@ -154,7 +154,7 @@ void tst_drawingmodes::points()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
#ifdef Q_OS_WIN
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES)
@@ -197,7 +197,7 @@ void tst_drawingmodes::lines()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QImage fb = runTest("DrawingModes.qml");
@@ -228,7 +228,7 @@ void tst_drawingmodes::lineStrip()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QImage fb = runTest("DrawingModes.qml");
@@ -261,7 +261,7 @@ void tst_drawingmodes::lineLoop()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
if (isRunningOnRhi())
QSKIP("Line loops are not supported by some modern graphics APIs - skipping test");
@@ -297,7 +297,7 @@ void tst_drawingmodes::triangles()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QImage fb = runTest("DrawingModes.qml");
@@ -326,7 +326,7 @@ void tst_drawingmodes::triangleStrip()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QImage fb = runTest("DrawingModes.qml");
@@ -354,7 +354,7 @@ void tst_drawingmodes::triangleFan()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
if (isRunningOnRhi())
QSKIP("Triangle fans are not supported by some modern graphics APIs - skipping test");
diff --git a/tests/auto/quick/nodes/tst_nodestest.cpp b/tests/auto/quick/nodes/tst_nodestest.cpp
index bd5e6c6383..249ecd5aa5 100644
--- a/tests/auto/quick/nodes/tst_nodestest.cpp
+++ b/tests/auto/quick/nodes/tst_nodestest.cpp
@@ -121,9 +121,6 @@ class DummyRenderer : public QSGBatchRenderer::Renderer
public:
DummyRenderer(QSGRootNode *root, QSGDefaultRenderContext *renderContext)
: QSGBatchRenderer::Renderer(renderContext)
- , changedNode(nullptr)
- , changedState(nullptr)
- , renderCount(0)
{
setRootNode(root);
}
@@ -139,11 +136,11 @@ public:
QSGBatchRenderer::Renderer::nodeChanged(node, state);
}
- QSGNode *changedNode;
+ QSGNode *changedNode = nullptr;
QSGNode::DirtyState changedState;
- int renderCount;
- int renderingOrder;
+ int renderCount = 0;
+ int renderingOrder = 0;
static int globalRendereringOrder;
};
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 35fed99e8b..4a7a132be2 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
@@ -295,10 +295,10 @@ void tst_MptaInterop::unloadHandlerWithPassiveGrab()
QVERIFY(mpta);
QPoint point(90, 90);
- QTest::mousePress(window, Qt::LeftButton, 0, point);
+ QTest::mousePress(window, Qt::LeftButton, {}, point);
QCOMPARE(window->mouseGrabberItem(), mpta);
QTRY_VERIFY(handler.isNull()); // it got unloaded
- QTest::mouseRelease(window, Qt::LeftButton, 0, point); // QTBUG-73819: don't crash
+ QTest::mouseRelease(window, Qt::LeftButton, {}, point); // QTBUG-73819: don't crash
}
void tst_MptaInterop::dragHandlerInParentStealingGrabFromItem() // QTBUG-75025
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml
index 7b3601bea0..81fa20f3bb 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the manual tests of the Qt Toolkit.
@@ -26,7 +26,7 @@
**
****************************************************************************/
-import QtQuick 2.12
+import QtQuick 2.15
Item {
id: root
@@ -47,6 +47,7 @@ Item {
DragHandler {
id: dragHandler
objectName: "DragHandler " + (index + 1)
+ cursorShape: Qt.ClosedHandCursor
}
Text {
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
index 66314f88a2..47cfd27817 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
@@ -53,9 +53,12 @@ private slots:
void initTestCase();
void defaultPropertyValues();
+ void touchDrag_data();
void touchDrag();
void mouseDrag_data();
void mouseDrag();
+ void mouseDragThreshold_data();
+ void mouseDragThreshold();
void dragFromMargin();
void snapMode_data();
void snapMode();
@@ -131,9 +134,18 @@ void tst_DragHandler::defaultPropertyValues()
QCOMPARE(dragHandler->centroid().sceneGrabPosition(), QPointF());
}
+void tst_DragHandler::touchDrag_data()
+{
+ QTest::addColumn<int>("dragThreshold");
+ QTest::newRow("threshold zero") << 0;
+ QTest::newRow("threshold one") << 1;
+ QTest::newRow("threshold 20") << 20;
+ QTest::newRow("threshold default") << -1;
+}
+
void tst_DragHandler::touchDrag()
{
- const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QFETCH(int, dragThreshold);
QScopedPointer<QQuickView> windowPtr;
createView(windowPtr, "draggables.qml");
QQuickView * window = windowPtr.data();
@@ -142,6 +154,12 @@ void tst_DragHandler::touchDrag()
QVERIFY(ball);
QQuickDragHandler *dragHandler = ball->findChild<QQuickDragHandler*>();
QVERIFY(dragHandler);
+ if (dragThreshold < 0) {
+ dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QCOMPARE(dragHandler->dragThreshold(), dragThreshold);
+ } else {
+ dragHandler->setDragThreshold(dragThreshold);
+ }
QSignalSpy translationChangedSpy(dragHandler, SIGNAL(translationChanged()));
QSignalSpy centroidChangedSpy(dragHandler, SIGNAL(centroidChanged()));
@@ -161,7 +179,9 @@ void tst_DragHandler::touchDrag()
p1 += QPoint(dragThreshold, 0);
QTest::touchEvent(window, touchDevice).move(1, p1, window);
QQuickTouchUtils::flush(window);
- QTRY_VERIFY(dragHandler->centroid().velocity().x() > 0);
+ qCDebug(lcPointerTests) << "velocity after drag" << dragHandler->centroid().velocity();
+ if (dragThreshold > 0)
+ QTRY_VERIFY(!qFuzzyIsNull(dragHandler->centroid().velocity().x()));
QCOMPARE(centroidChangedSpy.count(), 2);
QVERIFY(!dragHandler->active());
p1 += QPoint(1, 0);
@@ -229,8 +249,11 @@ void tst_DragHandler::mouseDrag()
QPointF ballCenter = ball->clipRect().center();
QPointF scenePressPos = ball->mapToScene(ballCenter);
QPoint p1 = scenePressPos.toPoint();
- QTest::mousePress(window, static_cast<Qt::MouseButton>(int(dragButton)), Qt::NoModifier, p1);
+ QTest::mousePress(window, static_cast<Qt::MouseButton>(int(dragButton)), Qt::NoModifier, p1, 500);
QVERIFY(!dragHandler->active());
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
+#endif
if (shouldDrag) {
QCOMPARE(dragHandler->centroid().position(), ballCenter);
QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter);
@@ -245,6 +268,9 @@ void tst_DragHandler::mouseDrag()
QTRY_VERIFY(dragHandler->centroid().velocity().x() > 0);
QCOMPARE(centroidChangedSpy.count(), 2);
QVERIFY(!dragHandler->active());
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
+#endif
}
p1 += QPoint(1, 0);
QTest::mouseMove(window, p1);
@@ -272,6 +298,9 @@ void tst_DragHandler::mouseDrag()
QCOMPARE(dragHandler->translation().y(), 0.0);
QVERIFY(dragHandler->centroid().velocity().x() > 0);
QCOMPARE(centroidChangedSpy.count(), 4);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::ClosedHandCursor);
+#endif
}
QTest::mouseRelease(window, static_cast<Qt::MouseButton>(int(dragButton)), Qt::NoModifier, p1);
QTRY_VERIFY(!dragHandler->active());
@@ -280,6 +309,85 @@ void tst_DragHandler::mouseDrag()
QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1);
QCOMPARE(translationChangedSpy.count(), shouldDrag ? 1 : 0);
QCOMPARE(centroidChangedSpy.count(), shouldDrag ? 5 : 0);
+#if QT_CONFIG(cursor)
+ QTest::mouseMove(window, p1 + QPoint(1, 0)); // TODO after fixing QTBUG-53987, don't send mouseMove
+ QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
+#endif
+}
+
+void tst_DragHandler::mouseDragThreshold_data()
+{
+ QTest::addColumn<int>("dragThreshold");
+ QTest::newRow("threshold zero") << 0;
+ QTest::newRow("threshold one") << 1;
+ QTest::newRow("threshold 20") << 20;
+ QTest::newRow("threshold default") << -1;
+}
+
+void tst_DragHandler::mouseDragThreshold()
+{
+ QFETCH(int, dragThreshold);
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "draggables.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *ball = window->rootObject()->childItems().first();
+ QVERIFY(ball);
+ QQuickDragHandler *dragHandler = ball->findChild<QQuickDragHandler*>();
+ QVERIFY(dragHandler);
+ if (dragThreshold < 0) {
+ dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QCOMPARE(dragHandler->dragThreshold(), dragThreshold);
+ } else {
+ dragHandler->setDragThreshold(dragThreshold);
+ }
+
+ QSignalSpy translationChangedSpy(dragHandler, SIGNAL(translationChanged()));
+ QSignalSpy centroidChangedSpy(dragHandler, SIGNAL(centroidChanged()));
+
+ QPointF ballCenter = ball->clipRect().center();
+ QPointF scenePressPos = ball->mapToScene(ballCenter);
+ QPoint p1 = scenePressPos.toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QVERIFY(!dragHandler->active());
+ QCOMPARE(dragHandler->centroid().position(), ballCenter);
+ QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter);
+ QCOMPARE(dragHandler->centroid().scenePosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().velocity(), QVector2D());
+ QCOMPARE(centroidChangedSpy.count(), 1);
+ p1 += QPoint(dragThreshold, 0);
+ QTest::mouseMove(window, p1);
+ if (dragThreshold > 0)
+ QTRY_VERIFY(dragHandler->centroid().velocity().x() > 0);
+ QCOMPARE(centroidChangedSpy.count(), 2);
+ QVERIFY(!dragHandler->active());
+ p1 += QPoint(1, 0);
+ QTest::mouseMove(window, p1);
+ QTRY_VERIFY(dragHandler->active());
+ QCOMPARE(translationChangedSpy.count(), 0);
+ QCOMPARE(centroidChangedSpy.count(), 3);
+ QCOMPARE(dragHandler->translation().x(), 0.0);
+ QPointF sceneGrabPos = p1;
+ QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
+ p1 += QPoint(19, 0);
+ QTest::mouseMove(window, p1);
+ QTRY_VERIFY(dragHandler->active());
+ QCOMPARE(dragHandler->centroid().position(), ballCenter);
+ QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter);
+ QCOMPARE(dragHandler->centroid().scenePosition(), ball->mapToScene(ballCenter));
+ QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
+ QCOMPARE(dragHandler->translation().x(), dragThreshold + 20.0);
+ QCOMPARE(dragHandler->translation().y(), 0.0);
+ QVERIFY(dragHandler->centroid().velocity().x() > 0);
+ QCOMPARE(centroidChangedSpy.count(), 4);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(!dragHandler->active());
+ QCOMPARE(dragHandler->centroid().pressedButtons(), Qt::NoButton);
+ QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1);
+ QCOMPARE(translationChangedSpy.count(), 1);
+ QCOMPARE(centroidChangedSpy.count(), 5);
}
void tst_DragHandler::dragFromMargin() // QTBUG-74966
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml
index 011dc4e75f..38a19c57c5 100644
--- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -26,7 +26,7 @@
**
****************************************************************************/
-import QtQuick 2.12
+import QtQuick 2.15
Rectangle {
id: root
@@ -52,6 +52,7 @@ Rectangle {
id: buttonMA
objectName: "buttonMA"
hoverEnabled: true
+ cursorShape: Qt.UpArrowCursor
anchors.fill: parent
onClicked: console.log("clicked MA")
}
@@ -74,9 +75,12 @@ Rectangle {
id: buttonHH
objectName: "buttonHH"
acceptedDevices: PointerDevice.AllDevices
+ cursorShape: tapHandler.pressed ? Qt.BusyCursor : Qt.PointingHandCursor
}
- TapHandler { }
+ TapHandler {
+ id: tapHandler
+ }
Text {
anchors.centerIn: parent
@@ -127,6 +131,7 @@ Rectangle {
HoverHandler {
id: topSidebarHH
objectName: "topSidebarHH"
+ cursorShape: Qt.OpenHandCursor
}
Loader {
@@ -152,6 +157,7 @@ Rectangle {
id: bottomSidebarMA
objectName: "bottomSidebarMA"
hoverEnabled: true
+ cursorShape: Qt.ClosedHandCursor
anchors.fill: parent
}
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
index 575139f851..61f2752dd2 100644
--- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
@@ -104,30 +104,45 @@ void tst_HoverHandler::hoverHandlerAndUnderlyingHoverHandler()
QCOMPARE(sidebarHoveredSpy.count(), 0);
QCOMPARE(buttonHH->isHovered(), false);
QCOMPARE(buttonHoveredSpy.count(), 0);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
+#endif
QTest::mouseMove(window, rightOfButton);
QCOMPARE(topSidebarHH->isHovered(), true);
QCOMPARE(sidebarHoveredSpy.count(), 1);
QCOMPARE(buttonHH->isHovered(), false);
QCOMPARE(buttonHoveredSpy.count(), 0);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::OpenHandCursor);
+#endif
QTest::mouseMove(window, buttonCenter);
QCOMPARE(topSidebarHH->isHovered(), true);
QCOMPARE(sidebarHoveredSpy.count(), 1);
QCOMPARE(buttonHH->isHovered(), true);
QCOMPARE(buttonHoveredSpy.count(), 1);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::PointingHandCursor);
+#endif
QTest::mouseMove(window, rightOfButton);
QCOMPARE(topSidebarHH->isHovered(), true);
QCOMPARE(sidebarHoveredSpy.count(), 1);
QCOMPARE(buttonHH->isHovered(), false);
QCOMPARE(buttonHoveredSpy.count(), 2);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::OpenHandCursor);
+#endif
QTest::mouseMove(window, outOfSidebar);
QCOMPARE(topSidebarHH->isHovered(), false);
QCOMPARE(sidebarHoveredSpy.count(), 2);
QCOMPARE(buttonHH->isHovered(), false);
QCOMPARE(buttonHoveredSpy.count(), 2);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
+#endif
}
void tst_HoverHandler::mouseAreaAndUnderlyingHoverHandler()
@@ -153,30 +168,45 @@ void tst_HoverHandler::mouseAreaAndUnderlyingHoverHandler()
QCOMPARE(sidebarHoveredSpy.count(), 0);
QCOMPARE(buttonMA->hovered(), false);
QCOMPARE(buttonHoveredSpy.count(), 0);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
+#endif
QTest::mouseMove(window, rightOfButton);
QCOMPARE(topSidebarHH->isHovered(), true);
QCOMPARE(sidebarHoveredSpy.count(), 1);
QCOMPARE(buttonMA->hovered(), false);
QCOMPARE(buttonHoveredSpy.count(), 0);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::OpenHandCursor);
+#endif
QTest::mouseMove(window, buttonCenter);
QCOMPARE(topSidebarHH->isHovered(), true);
QCOMPARE(sidebarHoveredSpy.count(), 1);
QCOMPARE(buttonMA->hovered(), true);
QCOMPARE(buttonHoveredSpy.count(), 1);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::UpArrowCursor);
+#endif
QTest::mouseMove(window, rightOfButton);
QCOMPARE(topSidebarHH->isHovered(), true);
QCOMPARE(sidebarHoveredSpy.count(), 1);
QCOMPARE(buttonMA->hovered(), false);
QCOMPARE(buttonHoveredSpy.count(), 2);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::OpenHandCursor);
+#endif
QTest::mouseMove(window, outOfSidebar);
QCOMPARE(topSidebarHH->isHovered(), false);
QCOMPARE(sidebarHoveredSpy.count(), 2);
QCOMPARE(buttonMA->hovered(), false);
QCOMPARE(buttonHoveredSpy.count(), 2);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
+#endif
}
void tst_HoverHandler::hoverHandlerAndUnderlyingMouseArea()
@@ -204,30 +234,45 @@ void tst_HoverHandler::hoverHandlerAndUnderlyingMouseArea()
QCOMPARE(sidebarHoveredSpy.count(), 0);
QCOMPARE(buttonHH->isHovered(), false);
QCOMPARE(buttonHoveredSpy.count(), 0);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
+#endif
QTest::mouseMove(window, rightOfButton);
QCOMPARE(bottomSidebarMA->hovered(), true);
QCOMPARE(sidebarHoveredSpy.count(), 1);
QCOMPARE(buttonHH->isHovered(), false);
QCOMPARE(buttonHoveredSpy.count(), 0);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::ClosedHandCursor);
+#endif
QTest::mouseMove(window, buttonCenter);
QCOMPARE(bottomSidebarMA->hovered(), false);
QCOMPARE(sidebarHoveredSpy.count(), 2);
QCOMPARE(buttonHH->isHovered(), true);
QCOMPARE(buttonHoveredSpy.count(), 1);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::PointingHandCursor);
+#endif
QTest::mouseMove(window, rightOfButton);
QCOMPARE(bottomSidebarMA->hovered(), true);
QCOMPARE(sidebarHoveredSpy.count(), 3);
QCOMPARE(buttonHH->isHovered(), false);
QCOMPARE(buttonHoveredSpy.count(), 2);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::ClosedHandCursor);
+#endif
QTest::mouseMove(window, outOfSidebar);
QCOMPARE(bottomSidebarMA->hovered(), false);
QCOMPARE(sidebarHoveredSpy.count(), 4);
QCOMPARE(buttonHH->isHovered(), false);
QCOMPARE(buttonHoveredSpy.count(), 2);
+#if QT_CONFIG(cursor)
+ QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
+#endif
}
void tst_HoverHandler::movingItemWithHoverHandler()
@@ -255,6 +300,7 @@ void tst_HoverHandler::movingItemWithHoverHandler()
QVERIFY(QTest::qWaitForWindowExposed(window));
QTRY_COMPARE(paddleHH->isHovered(), true);
+ // TODO check the cursor shape after fixing QTBUG-53987
paddle->setX(100);
QTRY_COMPARE(paddleHH->isHovered(), false);
diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp
index d0b3bc3d36..ca6463f365 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp
@@ -55,6 +55,7 @@ private slots:
void initTestCase();
void singleTouch();
+ void tabletStylus();
void simultaneousMultiTouch();
void pressedMultipleButtons_data();
void pressedMultipleButtons();
@@ -136,6 +137,65 @@ void tst_PointHandler::singleTouch()
QCOMPARE(translationSpy.count(), 3);
}
+void tst_PointHandler::tabletStylus()
+{
+ qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents, false);
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "pointTracker.qml");
+ QQuickView * window = windowPtr.data();
+ QQuickPointHandler *handler = window->rootObject()->findChild<QQuickPointHandler *>("pointHandler");
+ QVERIFY(handler);
+ handler->setAcceptedDevices(QQuickPointerDevice::Stylus);
+
+ QSignalSpy activeSpy(handler, SIGNAL(activeChanged()));
+ QSignalSpy pointSpy(handler, SIGNAL(pointChanged()));
+ QSignalSpy translationSpy(handler, SIGNAL(translationChanged()));
+
+ QPoint point(100,100);
+ const qint64 stylusId = 1234567890;
+
+ QWindowSystemInterface::handleTabletEvent(window, point, window->mapToGlobal(point),
+ QTabletEvent::Stylus, QTabletEvent::Pen, Qt::LeftButton, 0.5, 25, 35, 0.6, 12.3, 3, stylusId, Qt::NoModifier);
+ QTRY_COMPARE(handler->active(), true);
+ QCOMPARE(activeSpy.count(), 1);
+ QCOMPARE(pointSpy.count(), 1);
+ QCOMPARE(handler->point().position().toPoint(), point);
+ QCOMPARE(handler->point().scenePosition().toPoint(), point);
+ QCOMPARE(handler->point().pressedButtons(), Qt::LeftButton);
+ QCOMPARE(handler->point().pressure(), 0.5);
+ QCOMPARE(handler->point().rotation(), 12.3);
+ QCOMPARE(handler->point().uniqueId().numericId(), stylusId);
+ QCOMPARE(handler->translation(), QVector2D());
+ QCOMPARE(translationSpy.count(), 1);
+
+ point += QPoint(10, 10);
+ QWindowSystemInterface::handleTabletEvent(window, point, window->mapToGlobal(point),
+ QTabletEvent::Stylus, QTabletEvent::Pen, Qt::LeftButton, 0.45, 23, 33, 0.57, 15.6, 3.4, stylusId, Qt::NoModifier);
+ QTRY_COMPARE(pointSpy.count(), 2);
+ QCOMPARE(handler->active(), true);
+ QCOMPARE(activeSpy.count(), 1);
+ QCOMPARE(handler->point().position().toPoint(), point);
+ QCOMPARE(handler->point().scenePosition().toPoint(), point);
+ QCOMPARE(handler->point().pressPosition().toPoint(), QPoint(100, 100));
+ QCOMPARE(handler->point().scenePressPosition().toPoint(), QPoint(100, 100));
+ QCOMPARE(handler->point().pressedButtons(), Qt::LeftButton);
+ QCOMPARE(handler->point().pressure(), 0.45);
+ QCOMPARE(handler->point().rotation(), 15.6);
+ QCOMPARE(handler->point().uniqueId().numericId(), stylusId);
+ QVERIFY(handler->point().velocity().x() > 0);
+ QVERIFY(handler->point().velocity().y() > 0);
+ QCOMPARE(handler->translation(), QVector2D(10, 10));
+ QCOMPARE(translationSpy.count(), 2);
+
+ QWindowSystemInterface::handleTabletEvent(window, point, window->mapToGlobal(point),
+ QTabletEvent::Stylus, QTabletEvent::Pen, Qt::NoButton, 0, 0, 0, 0, 0, 0, stylusId, Qt::NoModifier);
+ QTRY_COMPARE(handler->active(), false);
+ QCOMPARE(activeSpy.count(), 2);
+ QCOMPARE(pointSpy.count(), 3);
+ QCOMPARE(handler->translation(), QVector2D());
+ QCOMPARE(translationSpy.count(), 3);
+}
+
void tst_PointHandler::simultaneousMultiTouch()
{
QScopedPointer<QQuickView> windowPtr;
diff --git a/tests/auto/quick/qquickanimatedsprite/data/finishBehavior.qml b/tests/auto/quick/qquickanimatedsprite/data/finishBehavior.qml
new file mode 100644
index 0000000000..13a0ef4622
--- /dev/null
+++ b/tests/auto/quick/qquickanimatedsprite/data/finishBehavior.qml
@@ -0,0 +1,18 @@
+import QtQuick 2.15
+
+Rectangle {
+ color: "black"
+ width: 320
+ height: 320
+
+ AnimatedSprite {
+ objectName: "sprite"
+ loops: 1
+ source: "squarefacesprite.png"
+ frameCount: 6
+ frameDuration: 64
+ width: 160
+ height: 160
+ finishBehavior: AnimatedSprite.FinishAtFinalFrame
+ }
+}
diff --git a/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp b/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
index d2bbf9e6b1..9f616c56e2 100644
--- a/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
+++ b/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
@@ -49,6 +49,7 @@ private slots:
void initTestCase();
void test_properties();
void test_runningChangedSignal();
+ void test_startStop();
void test_frameChangedSignal();
void test_largeAnimation_data();
void test_largeAnimation();
@@ -56,6 +57,7 @@ private slots:
void test_changeSourceToSmallerImgKeepingBigFrameSize();
void test_infiniteLoops();
void test_implicitSize();
+ void test_finishBehavior();
};
void tst_qquickanimatedsprite::initTestCase()
@@ -118,6 +120,42 @@ void tst_qquickanimatedsprite::test_runningChangedSignal()
QCOMPARE(finishedSpy.count(), 1);
}
+void tst_qquickanimatedsprite::test_startStop()
+{
+ QScopedPointer<QQuickView> window(new QQuickView);
+
+ window->setSource(testFileUrl("runningChange.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QVERIFY(window->rootObject());
+ QQuickAnimatedSprite* sprite = window->rootObject()->findChild<QQuickAnimatedSprite*>("sprite");
+ QVERIFY(sprite);
+
+ QVERIFY(!sprite->running());
+
+ QSignalSpy runningChangedSpy(sprite, SIGNAL(runningChanged(bool)));
+ QSignalSpy finishedSpy(sprite, SIGNAL(finished()));
+ QVERIFY(finishedSpy.isValid());
+
+ sprite->start();
+ QVERIFY(sprite->running());
+ QTRY_COMPARE(runningChangedSpy.count(), 1);
+ QCOMPARE(finishedSpy.count(), 0);
+ sprite->stop();
+ QVERIFY(!sprite->running());
+ QTRY_COMPARE(runningChangedSpy.count(), 2);
+ QCOMPARE(finishedSpy.count(), 0);
+
+ sprite->setCurrentFrame(2);
+ sprite->start();
+ QVERIFY(sprite->running());
+ QCOMPARE(sprite->currentFrame(), 0);
+ QTRY_VERIFY(sprite->currentFrame() > 0);
+ sprite->stop();
+ QVERIFY(!sprite->running());
+}
+
template <typename T>
static bool isWithinRange(T min, T value, T max)
{
@@ -391,6 +429,31 @@ void tst_qquickanimatedsprite::test_infiniteLoops()
QCOMPARE(finishedSpy.count(), 0);
}
+void tst_qquickanimatedsprite::test_finishBehavior()
+{
+ QQuickView window;
+ window.setSource(testFileUrl("finishBehavior.qml"));
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(window.rootObject());
+
+ QQuickAnimatedSprite* sprite = window.rootObject()->findChild<QQuickAnimatedSprite*>("sprite");
+ QVERIFY(sprite);
+
+ QTRY_VERIFY(sprite->running());
+
+ // correctly stops at last frame
+ QSignalSpy finishedSpy(sprite, SIGNAL(finished()));
+ QVERIFY(finishedSpy.wait(2000));
+ QCOMPARE(sprite->running(), false);
+ QCOMPARE(sprite->currentFrame(), 5);
+
+ // correctly starts a second time
+ sprite->start();
+ QTRY_VERIFY(sprite->running());
+ QTRY_COMPARE(sprite->currentFrame(), 5);
+}
+
QTEST_MAIN(tst_qquickanimatedsprite)
#include "tst_qquickanimatedsprite.moc"
diff --git a/tests/auto/quick/qquickanimations/data/signalorder.qml b/tests/auto/quick/qquickanimations/data/signalorder.qml
new file mode 100644
index 0000000000..35029b0c84
--- /dev/null
+++ b/tests/auto/quick/qquickanimations/data/signalorder.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.12
+
+
+Item {
+ id: wrapper
+ width: 400; height: 400
+
+ Rectangle {
+ id: greenRect
+ width: 50; height: 50
+ color: "red"
+
+ ColorAnimation on color {
+ id: colorAnimation
+ objectName: "ColorAnimation"
+ to: "green"
+ duration: 10
+ running: false
+ }
+
+ ParallelAnimation {
+ id: parallelAnimation
+ objectName: "ParallelAnimation"
+ running: false
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimations/qquickanimations.pro b/tests/auto/quick/qquickanimations/qquickanimations.pro
index 94f694181d..6998c023db 100644
--- a/tests/auto/quick/qquickanimations/qquickanimations.pro
+++ b/tests/auto/quick/qquickanimations/qquickanimations.pro
@@ -64,6 +64,7 @@ OTHER_FILES += \
data/scriptActionCrash.qml \
data/sequentialAnimationNullChildBug.qml \
data/signals.qml \
+ data/signalorder.qml \
data/transitionAssignmentBug.qml \
data/valuesource.qml \
data/valuesource2.qml
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index 9bd0cd777f..b4eb33eb7a 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -89,6 +89,8 @@ private slots:
void easingProperties();
void rotation();
void startStopSignals();
+ void signalOrder_data();
+ void signalOrder();
void runningTrueBug();
void nonTransitionBug();
void registrationBug();
@@ -266,7 +268,8 @@ void tst_qquickanimations::simplePath()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathAnimation.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
@@ -300,14 +303,13 @@ void tst_qquickanimations::simplePath()
pathAnim->start();
QTRY_VERIFY(redRect->rotation() != 0);
pathAnim->stop();
-
- delete rect;
}
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathAnimation2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
@@ -335,8 +337,6 @@ void tst_qquickanimations::simplePath()
QCOMPARE(redRect->x(), qreal(300));
QCOMPARE(redRect->y(), qreal(300));
QCOMPARE(redRect->rotation(), qreal(0));
-
- delete rect;
}
}
@@ -344,7 +344,8 @@ void tst_qquickanimations::simpleAnchor()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("reanchor.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *greenRect = rect->findChild<QQuickRectangle*>();
@@ -412,15 +413,14 @@ void tst_qquickanimations::simpleAnchor()
QCOMPARE(greenRect->y(), qreal(50));
QCOMPARE(greenRect->width(), qreal(150));
QCOMPARE(greenRect->height(), qreal(125));
-
- delete rect;
}
void tst_qquickanimations::reparent()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("reparent.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *target = rect->findChild<QQuickRectangle*>("target");
@@ -461,15 +461,14 @@ void tst_qquickanimations::reparent()
QCOMPARE(target->height(), qreal(50));
QCOMPARE(target->rotation(), qreal(0));
QCOMPARE(target->scale(), qreal(1));
-
- delete rect;
}
void tst_qquickanimations::pathInterpolator()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathInterpolator.qml"));
- QQuickPathInterpolator *interpolator = qobject_cast<QQuickPathInterpolator*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *interpolator = qobject_cast<QQuickPathInterpolator*>(obj.data());
QVERIFY(interpolator);
QCOMPARE(interpolator->progress(), qreal(0));
@@ -505,7 +504,8 @@ void tst_qquickanimations::pathInterpolatorBackwardJump()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathInterpolatorBack.qml"));
- QQuickPathInterpolator *interpolator = qobject_cast<QQuickPathInterpolator*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *interpolator = qobject_cast<QQuickPathInterpolator*>(obj.data());
QVERIFY(interpolator);
QCOMPARE(interpolator->progress(), qreal(0));
@@ -536,7 +536,8 @@ void tst_qquickanimations::pathInterpolatorBackwardJump()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathInterpolatorBack2.qml"));
- QQuickPathInterpolator *interpolator = qobject_cast<QQuickPathInterpolator*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *interpolator = qobject_cast<QQuickPathInterpolator*>(obj.data());
QVERIFY(interpolator);
QCOMPARE(interpolator->progress(), qreal(0));
@@ -563,7 +564,8 @@ void tst_qquickanimations::pathWithNoStart()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathAnimationNoStart.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
@@ -729,12 +731,9 @@ void tst_qquickanimations::badTypes()
{
//don't crash
{
- QQuickView *view = new QQuickView;
+ QScopedPointer<QQuickView> view(new QQuickView);
view->setSource(testFileUrl("badtype1.qml"));
-
qApp->processEvents();
-
- delete view;
}
//make sure we get a compiler error
@@ -742,7 +741,8 @@ void tst_qquickanimations::badTypes()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("badtype2.qml"));
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
- c.create();
+ QScopedPointer<QObject> obj(c.create());
+ QVERIFY(obj.isNull());
QCOMPARE(c.errors().count(), 1);
QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: number expected"));
@@ -753,7 +753,8 @@ void tst_qquickanimations::badTypes()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("badtype3.qml"));
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
- c.create();
+ QScopedPointer<QObject> obj(c.create());
+ QVERIFY(obj.isNull());
QCOMPARE(c.errors().count(), 1);
QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: color expected"));
@@ -763,7 +764,8 @@ void tst_qquickanimations::badTypes()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("badtype4.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickItemPrivate::get(rect)->setState("state1");
@@ -783,13 +785,15 @@ void tst_qquickanimations::badProperties()
QQmlComponent c1(&engine, testFileUrl("badproperty1.qml"));
QByteArray message = testFileUrl("badproperty1.qml").toString().toUtf8() + ":18:9: QML ColorAnimation: Cannot animate non-existent property \"border.colr\"";
QTest::ignoreMessage(QtWarningMsg, message);
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c1.create());
+ QScopedPointer<QObject> obj(c1.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQmlComponent c2(&engine, testFileUrl("badproperty2.qml"));
message = testFileUrl("badproperty2.qml").toString().toUtf8() + ":18:9: QML ColorAnimation: Cannot animate read-only property \"border\"";
QTest::ignoreMessage(QtWarningMsg, message);
- rect = qobject_cast<QQuickRectangle*>(c2.create());
+ QScopedPointer<QObject> obj2(c2.create());
+ rect = qobject_cast<QQuickRectangle*>(obj2.data());
QVERIFY(rect);
//### should we warn here are well?
@@ -805,7 +809,8 @@ void tst_qquickanimations::mixedTypes()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("mixedtype1.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickItemPrivate::get(rect)->setState("state1");
@@ -821,7 +826,8 @@ void tst_qquickanimations::mixedTypes()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("mixedtype2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickItemPrivate::get(rect)->setState("state1");
@@ -841,7 +847,8 @@ void tst_qquickanimations::properties()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("properties.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -853,7 +860,8 @@ void tst_qquickanimations::properties()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("properties2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -865,7 +873,8 @@ void tst_qquickanimations::properties()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("properties3.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -877,7 +886,8 @@ void tst_qquickanimations::properties()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("properties4.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -890,7 +900,8 @@ void tst_qquickanimations::properties()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("properties5.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -907,7 +918,8 @@ void tst_qquickanimations::propertiesTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("propertiesTransition.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickItemPrivate::get(rect)->setState("moved");
@@ -920,7 +932,8 @@ void tst_qquickanimations::propertiesTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("propertiesTransition2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -935,7 +948,8 @@ void tst_qquickanimations::propertiesTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("propertiesTransition3.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -948,7 +962,8 @@ void tst_qquickanimations::propertiesTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("propertiesTransition4.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -962,7 +977,8 @@ void tst_qquickanimations::propertiesTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("propertiesTransition5.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -976,7 +992,8 @@ void tst_qquickanimations::propertiesTransition()
/*{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("propertiesTransition6.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -990,7 +1007,8 @@ void tst_qquickanimations::propertiesTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("propertiesTransition7.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickItemPrivate::get(rect)->setState("moved");
@@ -1006,7 +1024,8 @@ void tst_qquickanimations::pathTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathTransition.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("redRect");
@@ -1026,7 +1045,8 @@ void tst_qquickanimations::disabledTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("disabledTransition.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -1054,12 +1074,12 @@ void tst_qquickanimations::disabledTransition()
void tst_qquickanimations::invalidDuration()
{
- QQuickPropertyAnimation *animation = new QQuickPropertyAnimation;
+ QScopedPointer<QQuickPropertyAnimation> animation(new QQuickPropertyAnimation);
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML PropertyAnimation: Cannot set a duration of < 0");
animation->setDuration(-1);
QCOMPARE(animation->duration(), 250);
- QQuickPauseAnimation *pauseAnimation = new QQuickPauseAnimation;
+ QScopedPointer<QQuickPauseAnimation> pauseAnimation(new QQuickPauseAnimation);
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML PauseAnimation: Cannot set a duration of < 0");
pauseAnimation->setDuration(-1);
QCOMPARE(pauseAnimation->duration(), 250);
@@ -1072,7 +1092,8 @@ void tst_qquickanimations::attached()
QQmlComponent c(&engine, testFileUrl("attached.qml"));
QTest::ignoreMessage(QtDebugMsg, "off");
QTest::ignoreMessage(QtDebugMsg, "on");
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
}
@@ -1083,7 +1104,8 @@ void tst_qquickanimations::propertyValueSourceDefaultStart()
QQmlComponent c(&engine, testFileUrl("valuesource.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
@@ -1096,7 +1118,8 @@ void tst_qquickanimations::propertyValueSourceDefaultStart()
QQmlComponent c(&engine, testFileUrl("valuesource2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
@@ -1109,7 +1132,8 @@ void tst_qquickanimations::propertyValueSourceDefaultStart()
QQmlComponent c(&engine, testFileUrl("dontAutoStart.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
@@ -1128,7 +1152,8 @@ void tst_qquickanimations::dontStart()
QString warning = c.url().toString() + ":14:13: QML NumberAnimation: setRunning() cannot be used on non-root animation nodes.";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
@@ -1143,7 +1168,8 @@ void tst_qquickanimations::dontStart()
QString warning = c.url().toString() + ":15:17: QML NumberAnimation: setRunning() cannot be used on non-root animation nodes.";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
@@ -1159,7 +1185,8 @@ void tst_qquickanimations::easingProperties()
QString componentStr = "import QtQuick 2.0\nNumberAnimation { easing.type: \"InOutQuad\" }";
QQmlComponent animationComponent(&engine);
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
+ QScopedPointer<QObject> obj(animationComponent.create());
+ auto *animObject = qobject_cast<QQuickPropertyAnimation *>(obj.data());
QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::InOutQuad);
@@ -1170,7 +1197,8 @@ void tst_qquickanimations::easingProperties()
QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"OutBounce\"; easing.amplitude: 5.0 }";
QQmlComponent animationComponent(&engine);
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
+ QScopedPointer<QObject> obj(animationComponent.create());
+ auto *animObject = qobject_cast<QQuickPropertyAnimation *>(obj.data());
QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::OutBounce);
@@ -1182,7 +1210,8 @@ void tst_qquickanimations::easingProperties()
QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"OutElastic\"; easing.amplitude: 5.0; easing.period: 3.0}";
QQmlComponent animationComponent(&engine);
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
+ QScopedPointer<QObject> obj(animationComponent.create());
+ auto *animObject = qobject_cast<QQuickPropertyAnimation *>(obj.data());
QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::OutElastic);
@@ -1195,7 +1224,8 @@ void tst_qquickanimations::easingProperties()
QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"InOutBack\"; easing.overshoot: 2 }";
QQmlComponent animationComponent(&engine);
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
+ QScopedPointer<QObject> obj(animationComponent.create());
+ auto *animObject = qobject_cast<QQuickPropertyAnimation *>(obj.data());
QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::InOutBack);
@@ -1207,7 +1237,8 @@ void tst_qquickanimations::easingProperties()
QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"Bezier\"; easing.bezierCurve: [0.5, 0.2, 0.13, 0.65, 1.0, 1.0] }";
QQmlComponent animationComponent(&engine);
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
+ QScopedPointer<QObject> obj(animationComponent.create());
+ auto *animObject = qobject_cast<QQuickPropertyAnimation *>(obj.data());
QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::BezierSpline);
@@ -1223,7 +1254,8 @@ void tst_qquickanimations::rotation()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("rotation.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *rr = rect->findChild<QQuickRectangle*>("rr");
@@ -1253,7 +1285,8 @@ void tst_qquickanimations::startStopSignals()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("signals.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *root = qobject_cast<QQuickItem *>(obj.data());
QVERIFY(root);
QCOMPARE(root->property("startedCount").toInt(), 1); //autostart
@@ -1293,12 +1326,63 @@ void tst_qquickanimations::startStopSignals()
QVERIFY(timer.elapsed() >= 200);
}
+void tst_qquickanimations::signalOrder_data()
+{
+ QTest::addColumn<QByteArray>("animationType");
+ QTest::addColumn<int>("duration");
+
+ QTest::addRow("ColorAnimation, duration = 10") << QByteArray("ColorAnimation") << 10;
+ QTest::addRow("ColorAnimation, duration = 0") << QByteArray("ColorAnimation") << 0;
+ QTest::addRow("ParallelAnimation, duration = 0") << QByteArray("ParallelAnimation") << 0;
+}
+
+void tst_qquickanimations::signalOrder()
+{
+ QFETCH(QByteArray, animationType);
+ QFETCH(int, duration);
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("signalorder.qml"));
+ QScopedPointer<QObject> obj(c.create());
+ auto *root = qobject_cast<QQuickItem *>(obj.data());
+ QVERIFY(root);
+ QQuickAbstractAnimation *animation = root->findChild<QQuickAbstractAnimation*>(animationType);
+
+ const QVector<void (QQuickAbstractAnimation::*)()> signalsToConnect = {
+ &QQuickAbstractAnimation::started,
+ &QQuickAbstractAnimation::stopped,
+ &QQuickAbstractAnimation::finished
+ };
+ const QVector<const char*> expectedSignalOrder = {
+ "started",
+ "stopped",
+ "finished"
+ };
+
+ QVector<const char*> actualSignalOrder;
+
+ for (int i = 0; i < signalsToConnect.size(); ++i) {
+ const char *str = expectedSignalOrder.at(i);
+ connect(animation, signalsToConnect.at(i) , [str, &actualSignalOrder] () {
+ actualSignalOrder.append(str);
+ });
+ }
+ QSignalSpy finishedSpy(animation, SIGNAL(finished()));
+ if (QQuickColorAnimation *colorAnimation = qobject_cast<QQuickColorAnimation*>(animation))
+ colorAnimation->setDuration(duration);
+
+ animation->start();
+ QTRY_VERIFY(finishedSpy.count());
+ QCOMPARE(actualSignalOrder, expectedSignalOrder);
+}
+
void tst_qquickanimations::runningTrueBug()
{
//ensure we start correctly when "running: true" is explicitly set
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("runningTrueBug.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *cloud = rect->findChild<QQuickRectangle*>("cloud");
@@ -1313,7 +1397,8 @@ void tst_qquickanimations::pathAnimationInOutBackBug()
//ensure we don't pass bad progress value (out of [0,1]) to QQuickPath::backwardsPointAt()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathAnimationInOutBackCrash.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *item = qobject_cast<QQuickItem *>(obj.data());
QVERIFY(item);
QQuickRectangle *rect = item->findChild<QQuickRectangle *>("rect");
@@ -1331,7 +1416,8 @@ void tst_qquickanimations::nonTransitionBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("nonTransitionBug.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QQuickRectangle *mover = rect->findChild<QQuickRectangle*>("mover");
@@ -1357,7 +1443,8 @@ void tst_qquickanimations::registrationBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("registrationBug.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect != nullptr);
QTRY_COMPARE(rect->property("value"), QVariant(int(100)));
}
@@ -1367,7 +1454,8 @@ void tst_qquickanimations::doubleRegistrationBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("doubleRegistrationBug.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect != nullptr);
QQuickAbstractAnimation *anim = rect->findChild<QQuickAbstractAnimation*>("animation");
@@ -1408,7 +1496,8 @@ void tst_qquickanimations::transitionAssignmentBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("transitionAssignmentBug.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect != nullptr);
QCOMPARE(rect->property("nullObject").toBool(), false);
@@ -1420,12 +1509,11 @@ void tst_qquickanimations::pauseBindingBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pauseBindingBug.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect != nullptr);
QQuickAbstractAnimation *anim = rect->findChild<QQuickAbstractAnimation*>("animation");
QCOMPARE(anim->qtAnimation()->state(), QAbstractAnimationJob::Paused);
-
- delete rect;
}
//QTBUG-13598
@@ -1434,13 +1522,12 @@ void tst_qquickanimations::pauseBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pauseBug.qml"));
- QQuickAbstractAnimation *anim = qobject_cast<QQuickAbstractAnimation*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *anim = qobject_cast<QQuickAbstractAnimation*>(obj.data());
QVERIFY(anim != nullptr);
QCOMPARE(anim->qtAnimation()->state(), QAbstractAnimationJob::Paused);
QCOMPARE(anim->isPaused(), true);
QCOMPARE(anim->isRunning(), true);
-
- delete anim;
}
//QTBUG-23092
@@ -1449,7 +1536,7 @@ void tst_qquickanimations::loopingBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("looping.qml"));
- QObject *obj = c.create();
+ QScopedPointer<QObject> obj(c.create());
QQuickAbstractAnimation *anim = obj->findChild<QQuickAbstractAnimation*>();
QVERIFY(anim != nullptr);
@@ -1461,8 +1548,6 @@ void tst_qquickanimations::loopingBug()
QQuickRectangle *rect = obj->findChild<QQuickRectangle*>();
QVERIFY(rect != nullptr);
QCOMPARE(rect->rotation(), qreal(90));
-
- delete obj;
}
//QTBUG-24532
@@ -1483,7 +1568,7 @@ void tst_qquickanimations::scriptActionBug()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("scriptActionBug.qml"));
- QObject *obj = c.create();
+ QScopedPointer<QObject> obj(c.create());
//Both the ScriptAction and StateChangeScript should be triggered
QCOMPARE(obj->property("actionTriggered").toBool(), true);
@@ -1497,20 +1582,16 @@ void tst_qquickanimations::groupAnimationNullChildBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("sequentialAnimationNullChildBug.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QScopedPointer<QObject> root(c.create());
QVERIFY(root);
-
- delete root;
}
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("parallelAnimationNullChildBug.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QScopedPointer<QObject> root(c.create());
QVERIFY(root);
-
- delete root;
}
}
@@ -1519,12 +1600,10 @@ void tst_qquickanimations::scriptActionCrash()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("scriptActionCrash.qml"));
- QObject *obj = c.create();
+ QScopedPointer<QObject> obj(c.create());
//just testing that we don't crash
QTest::qWait(1000); //5x transition duration
-
- delete obj;
}
// QTBUG-49364
@@ -1535,12 +1614,10 @@ void tst_qquickanimations::animatorInvalidTargetCrash()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("animatorInvalidTargetCrash.qml"));
- QObject *obj = c.create();
+ QScopedPointer<QObject> obj(c.create());
//just testing that we don't crash
QTest::qWait(5000); //animator duration
-
- delete obj;
}
Q_DECLARE_METATYPE(QList<QQmlError>)
@@ -1556,7 +1633,8 @@ void tst_qquickanimations::defaultPropertyWarning()
QVERIFY(warnings.isValid());
QQmlComponent component(&engine, testFileUrl("defaultRotationAnimation.qml"));
- QScopedPointer<QQuickItem> root(qobject_cast<QQuickItem*>(component.create()));
+ QScopedPointer<QObject> obj(component.create());
+ auto *root = qobject_cast<QQuickItem *>(obj.data());
QVERIFY(root);
QVERIFY(warnings.isEmpty());
@@ -1567,7 +1645,8 @@ void tst_qquickanimations::pathSvgAnimation()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("pathSvgAnimation.qml"));
- QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(component.create()));
+ QScopedPointer<QObject> obj(component.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
@@ -1588,7 +1667,8 @@ void tst_qquickanimations::pathLineUnspecifiedXYBug()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("pathLineUnspecifiedXYBug.qml"));
- QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(component.create()));
+ QScopedPointer<QObject> obj(component.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
@@ -1624,7 +1704,8 @@ void tst_qquickanimations::finished()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("finished.qml"));
- QScopedPointer<QObject> root(component.create());
+ QScopedPointer<QObject> obj(component.create());
+ auto *root = qobject_cast<QQuickItem *>(obj.data());
QVERIFY(root);
// Test that finished() is emitted for a simple top-level animation.
@@ -1697,7 +1778,8 @@ void tst_qquickanimations::replacingTransitions()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("replacingTransitions.qml"));
- QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
if (!c.errors().isEmpty())
qDebug() << c.errorString();
QVERIFY(rect);
@@ -1733,13 +1815,14 @@ void tst_qquickanimations::animationJobSelfDestruction()
QQmlEngine engine;
engine.clearComponentCache();
QQmlComponent c(&engine, testFileUrl("animationJobSelfDestructionBug.qml"));
- QScopedPointer<QQuickWindow> win(qobject_cast<QQuickWindow*>(c.create()));
+ QScopedPointer<QObject> obj(c.create());
+ auto *win = qobject_cast<QQuickWindow *>(obj.data());
if (!c.errors().isEmpty())
qDebug() << c.errorString();
QVERIFY(win);
win->setTitle(QTest::currentTestFunction());
win->show();
- QVERIFY(QTest::qWaitForWindowExposed(win.data()));
+ QVERIFY(QTest::qWaitForWindowExposed(win));
QQmlTimer *timer = win->property("timer").value<QQmlTimer*>();
QVERIFY(timer);
QCOMPARE(timer->isRunning(), false);
@@ -1753,13 +1836,14 @@ void tst_qquickanimations::fastFlickingBug()
QQmlEngine engine;
engine.clearComponentCache();
QQmlComponent c(&engine, testFileUrl("fastFlickingBug.qml"));
- QScopedPointer<QQuickWindow> win(qobject_cast<QQuickWindow*>(c.create()));
+ QScopedPointer<QObject> obj(c.create());
+ auto *win = qobject_cast<QQuickWindow *>(obj.data());
if (!c.errors().isEmpty())
qDebug() << c.errorString();
QVERIFY(win);
win->setTitle(QTest::currentTestFunction());
win->show();
- QVERIFY(QTest::qWaitForWindowExposed(win.data()));
+ QVERIFY(QTest::qWaitForWindowExposed(win));
auto timer = win->property("timer").value<QQmlTimer*>();
QVERIFY(timer);
QCOMPARE(timer->isRunning(), false);
diff --git a/tests/auto/quick/qquickbehaviors/data/targetProperty.qml b/tests/auto/quick/qquickbehaviors/data/targetProperty.qml
new file mode 100644
index 0000000000..18abd46010
--- /dev/null
+++ b/tests/auto/quick/qquickbehaviors/data/targetProperty.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.15
+
+Item {
+ readonly property QtObject xBehaviorObject: xBehavior.targetProperty.object
+ readonly property string xBehaviorName: xBehavior.targetProperty.name
+ readonly property QtObject emptyBehaviorObject: emptyBehavior.targetProperty.object
+ readonly property string emptyBehaviorName: emptyBehavior.targetProperty.name
+ Behavior on x {
+ id: xBehavior
+ objectName: "xBehavior"
+ }
+ Behavior {
+ id: emptyBehavior
+ objectName: "emptyBehavior"
+ }
+}
diff --git a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
index 64e32dcdfd..3b46019f64 100644
--- a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
+++ b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
@@ -75,6 +75,7 @@ private slots:
void innerBehaviorOverwritten();
void oneWay();
void safeToDelete();
+ void targetProperty();
};
void tst_qquickbehaviors::simpleBehavior()
@@ -656,6 +657,27 @@ void tst_qquickbehaviors::safeToDelete()
QVERIFY(c.create());
}
+Q_DECLARE_METATYPE(QQmlProperty)
+void tst_qquickbehaviors::targetProperty()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("targetProperty.qml"));
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(c.create()));
+ QVERIFY2(!item.isNull(), qPrintable(c.errorString()));
+
+ QQuickBehavior* xBehavior =
+ qobject_cast<QQuickBehavior*>(item->findChild<QQuickBehavior*>("xBehavior"));
+ QCOMPARE(xBehavior->property("targetProperty").value<QQmlProperty>(), QQmlProperty(item.data(), "x"));
+ QCOMPARE(item->property("xBehaviorObject").value<QObject*>(), item.data());
+ QCOMPARE(item->property("xBehaviorName").toString(), "x");
+
+ QQuickBehavior* emptyBehavior =
+ qobject_cast<QQuickBehavior*>(item->findChild<QQuickBehavior*>("emptyBehavior"));
+ QCOMPARE(emptyBehavior->property("targetProperty").value<QQmlProperty>().isValid(), false);
+ QCOMPARE(item->property("emptyBehaviorObject").value<QObject*>(), nullptr);
+ QCOMPARE(item->property("emptyBehaviorName").toString(), "");
+}
+
QTEST_MAIN(tst_qquickbehaviors)
diff --git a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
index dc3a783600..858a685796 100644
--- a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
+++ b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
@@ -619,7 +619,7 @@ void tst_qquickborderimage::multiFrame()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QFETCH(QString, qmlfile);
QFETCH(bool, asynchronous);
diff --git a/tests/auto/quick/qquickboundaryrule/data/dragHandler.qml b/tests/auto/quick/qquickboundaryrule/data/dragHandler.qml
index c66fd76ff1..769a5b2c7d 100644
--- a/tests/auto/quick/qquickboundaryrule/data/dragHandler.qml
+++ b/tests/auto/quick/qquickboundaryrule/data/dragHandler.qml
@@ -14,6 +14,7 @@ Rectangle {
}
BoundaryRule on x {
+ objectName: "boundaryRule"
id: xbr
minimum: -50
maximum: 100
diff --git a/tests/auto/quick/qquickboundaryrule/qquickboundaryrule.pro b/tests/auto/quick/qquickboundaryrule/qquickboundaryrule.pro
index ef43f4526a..c41f798d33 100644
--- a/tests/auto/quick/qquickboundaryrule/qquickboundaryrule.pro
+++ b/tests/auto/quick/qquickboundaryrule/qquickboundaryrule.pro
@@ -9,4 +9,4 @@ include (../shared/util.pri)
TESTDATA = data/*
-QT += core-private gui-private qml-private quick-private testlib
+QT += quick-private qml testlib
diff --git a/tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp b/tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp
index 44f1c9a2f9..75639dba49 100644
--- a/tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp
+++ b/tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp
@@ -30,7 +30,6 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQuick/qquickview.h>
-#include <QtQuick/private/qquickboundaryrule_p.h>
#include <QtQuick/private/qquickdraghandler_p.h>
#include "../../shared/util.h"
#include "../shared/viewtestutil.h"
@@ -57,7 +56,7 @@ void tst_qquickboundaryrule::dragHandler()
QVERIFY(target);
QQuickDragHandler *dragHandler = target->findChild<QQuickDragHandler*>();
QVERIFY(dragHandler);
- QQuickBoundaryRule *boundaryRule = target->findChild<QQuickBoundaryRule*>();
+ QObject *boundaryRule = target->findChild<QObject *>(QLatin1String("boundaryRule"));
QVERIFY(boundaryRule);
QSignalSpy overshootChangedSpy(boundaryRule, SIGNAL(currentOvershootChanged()));
@@ -68,29 +67,34 @@ void tst_qquickboundaryrule::dragHandler()
QTest::mouseMove(&window, p1);
QTRY_VERIFY(dragHandler->active());
QCOMPARE(target->position().x(), 100);
- QCOMPARE(boundaryRule->currentOvershoot(), 0);
- QCOMPARE(boundaryRule->peakOvershoot(), 0);
+ bool ok = false;
+ QCOMPARE(boundaryRule->property("currentOvershoot").toReal(&ok), 0);
+ QVERIFY(ok);
+ QCOMPARE(boundaryRule->property("peakOvershoot").toReal(&ok), 0);
+ QVERIFY(ok);
QCOMPARE(overshootChangedSpy.count(), 0);
// restricted drag: halfway into overshoot
p1 += QPoint(20, 0);
QTest::mouseMove(&window, p1);
QCOMPARE(target->position().x(), 117.5);
- QCOMPARE(boundaryRule->currentOvershoot(), 20);
- QCOMPARE(boundaryRule->peakOvershoot(), 20);
+ QCOMPARE(boundaryRule->property("currentOvershoot").toReal(), 20);
+ QCOMPARE(boundaryRule->property("peakOvershoot").toReal(), 20);
QCOMPARE(overshootChangedSpy.count(), 1);
// restricted drag: maximum overshoot
p1 += QPoint(80, 0);
QTest::mouseMove(&window, p1);
QCOMPARE(target->position().x(), 140);
- QCOMPARE(boundaryRule->currentOvershoot(), 100);
- QCOMPARE(boundaryRule->peakOvershoot(), 100);
+ QCOMPARE(boundaryRule->property("currentOvershoot").toReal(), 100);
+ QCOMPARE(boundaryRule->property("peakOvershoot").toReal(), 100);
QCOMPARE(overshootChangedSpy.count(), 2);
// release and let it return to bounds
QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_COMPARE(dragHandler->active(), false);
QTRY_COMPARE(overshootChangedSpy.count(), 3);
- QCOMPARE(boundaryRule->currentOvershoot(), 0);
- QCOMPARE(boundaryRule->peakOvershoot(), 0);
+ QCOMPARE(boundaryRule->property("currentOvershoot").toReal(&ok), 0);
+ QVERIFY(ok);
+ QCOMPARE(boundaryRule->property("peakOvershoot").toReal(&ok), 0);
+ QVERIFY(ok);
QCOMPARE(target->position().x(), 100);
}
diff --git a/tests/auto/quick/qquickflickable/data/resize.qml b/tests/auto/quick/qquickflickable/data/resize.qml
index 2f7ae7b8bb..131691d012 100644
--- a/tests/auto/quick/qquickflickable/data/resize.qml
+++ b/tests/auto/quick/qquickflickable/data/resize.qml
@@ -1,6 +1,7 @@
import QtQuick 2.0
Rectangle {
+ required property bool setRebound
function resizeContent() {
flick.resizeContent(600, 600, Qt.point(100, 100))
}
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index da4bf5dae3..f3659290eb 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -227,7 +227,7 @@ void tst_qquickflickable::create()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("flickable01.qml"));
- QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
+ QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.createWithInitialProperties({{"setRebound", false}}));
QVERIFY(obj != nullptr);
QCOMPARE(obj->isAtXBeginning(), true);
@@ -783,9 +783,8 @@ void tst_qquickflickable::flickableDirection()
void tst_qquickflickable::resizeContent()
{
QQmlEngine engine;
- engine.rootContext()->setContextProperty("setRebound", QVariant::fromValue(false));
QQmlComponent c(&engine, testFileUrl("resize.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QQuickItem *root = qobject_cast<QQuickItem*>(c.createWithInitialProperties({{"setRebound", false}}));
QQuickFlickable *obj = findItem<QQuickFlickable>(root, "flick");
QVERIFY(obj != nullptr);
@@ -817,7 +816,7 @@ void tst_qquickflickable::returnToBounds()
QScopedPointer<QQuickView> window(new QQuickView);
- window->rootContext()->setContextProperty("setRebound", setRebound);
+ window->setInitialProperties({{"setRebound", setRebound}});
window->setSource(testFileUrl("resize.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
diff --git a/tests/auto/quick/qquickimage/data/ProPhoto.jpg b/tests/auto/quick/qquickimage/data/ProPhoto.jpg
new file mode 100644
index 0000000000..481d35ca8e
--- /dev/null
+++ b/tests/auto/quick/qquickimage/data/ProPhoto.jpg
Binary files differ
diff --git a/tests/auto/quick/qquickimage/data/image.qml b/tests/auto/quick/qquickimage/data/image.qml
new file mode 100644
index 0000000000..09a577cc6f
--- /dev/null
+++ b/tests/auto/quick/qquickimage/data/image.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Image {
+ source: "heart.png"
+}
diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
index abc7cd86bd..cf54208d8c 100644
--- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp
+++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
@@ -51,6 +51,7 @@
#include "../../shared/testhttpserver.h"
#include "../shared/visualtestutil.h"
+// #define DEBUG_WRITE_OUTPUT
using namespace QQuickVisualTestUtil;
@@ -89,6 +90,8 @@ private slots:
void imageCrash_QTBUG_32513();
void sourceSize_data();
void sourceSize();
+ void sourceClipRect_data();
+ void sourceClipRect();
void progressAndStatusChanges();
void sourceSizeChanges();
void correctStatus();
@@ -99,6 +102,7 @@ private slots:
void urlInterceptor();
void multiFrame_data();
void multiFrame();
+ void colorSpace();
private:
QQmlEngine engine;
@@ -337,7 +341,7 @@ void tst_qquickimage::mirror()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QMap<QQuickImage::FillMode, QImage> screenshots;
QList<QQuickImage::FillMode> fillModes;
@@ -552,7 +556,7 @@ void tst_qquickimage::tiling_QTBUG_6716()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QFETCH(QString, source);
@@ -879,6 +883,72 @@ void tst_qquickimage::sourceSizeChanges()
delete img;
}
+void tst_qquickimage::sourceClipRect_data()
+{
+ QTest::addColumn<QRectF>("sourceClipRect");
+ QTest::addColumn<QSize>("sourceSize");
+ QTest::addColumn<QList<QPoint>>("redPixelLocations");
+ QTest::addColumn<QList<QPoint>>("bluePixelLocations");
+
+ QTest::newRow("unclipped") << QRectF() << QSize()
+ << (QList<QPoint>() << QPoint(80, 80) << QPoint(150, 256))
+ << (QList<QPoint>() << QPoint(28, 28) << QPoint(215, 215));
+ QTest::newRow("upperLeft") << QRectF(10, 10, 100, 100) << QSize()
+ << (QList<QPoint>() << QPoint(99, 99))
+ << (QList<QPoint>() << QPoint(100, 100) << QPoint(28, 28));
+ QTest::newRow("lowerRight") << QRectF(200, 200, 20, 20) << QSize()
+ << (QList<QPoint>() << QPoint(0, 0))
+ << (QList<QPoint>() << QPoint(14, 14));
+ QTest::newRow("miniMiddle") << QRectF(20, 20, 60, 60) << QSize(100, 100)
+ << (QList<QPoint>() << QPoint(59, 0) << QPoint(6, 12) << QPoint(42, 42))
+ << (QList<QPoint>() << QPoint(54, 54) << QPoint(15, 59));
+}
+
+void tst_qquickimage::sourceClipRect()
+{
+ QFETCH(QRectF, sourceClipRect);
+ QFETCH(QSize, sourceSize);
+ QFETCH(QList<QPoint>, redPixelLocations);
+ QFETCH(QList<QPoint>, bluePixelLocations);
+
+ QScopedPointer<QQuickView> window(new QQuickView(nullptr));
+
+ window->setColor(Qt::blue);
+ window->setSource(testFileUrl("image.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickImage *image = qobject_cast<QQuickImage*>(window->rootObject());
+ QVERIFY(image);
+
+ image->setSourceSize(sourceSize);
+ QCOMPARE(image->implicitWidth(), sourceSize.isValid() ? sourceSize.width() : 300);
+ QCOMPARE(image->implicitHeight(), sourceSize.isValid() ? sourceSize.height() : 300);
+ image->setSourceClipRect(sourceClipRect);
+ QCOMPARE(image->implicitWidth(), sourceClipRect.isNull() ? 300 : sourceClipRect.width());
+ QCOMPARE(image->implicitHeight(), sourceClipRect.isNull() ? 300 : sourceClipRect.height());
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ QImage contents = window->grabWindow();
+ if (contents.width() < sourceClipRect.width())
+ QSKIP("Skipping due to grabWindow not functional");
+#ifdef DEBUG_WRITE_OUTPUT
+ contents.save("/tmp/sourceClipRect_" + QLatin1String(QTest::currentDataTag()) + ".png");
+#endif
+ for (auto p : redPixelLocations) {
+ QRgb color = contents.pixel(p);
+ QVERIFY(qRed(color) > 0xc0);
+ QVERIFY(qBlue(color) < 0x0f);
+ }
+ for (auto p : bluePixelLocations){
+ QRgb color = contents.pixel(p);
+ QVERIFY(qBlue(color) > 0xc0);
+ QVERIFY(qRed(color) < 0x0f);
+ }
+}
+
void tst_qquickimage::progressAndStatusChanges()
{
TestHTTPServer server;
@@ -1089,7 +1159,7 @@ void tst_qquickimage::hugeImages()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QQuickView view;
view.setSource(testFileUrl("hugeImages.qml"));
@@ -1147,7 +1217,7 @@ void tst_qquickimage::multiFrame()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QFETCH(QString, qmlfile);
QFETCH(bool, asynchronous);
@@ -1190,6 +1260,34 @@ void tst_qquickimage::multiFrame()
QVERIFY(qBlue(color) < 0xc0);
}
+void tst_qquickimage::colorSpace()
+{
+ QString componentStr1 = "import QtQuick 2.15\n"
+ "Image { source: srcImage; }";
+ QQmlComponent component1(&engine);
+ component1.setData(componentStr1.toLatin1(), QUrl::fromLocalFile(""));
+ engine.rootContext()->setContextProperty("srcImage", testFileUrl("ProPhoto.jpg"));
+
+ QScopedPointer<QQuickImage> object1 { qobject_cast<QQuickImage*>(component1.create())};
+ QVERIFY(object1);
+ QTRY_COMPARE(object1->status(), QQuickImageBase::Ready);
+ QCOMPARE(object1->colorSpace(), QColorSpace(QColorSpace::ProPhotoRgb));
+
+ QString componentStr2 = "import QtQuick 2.15\n"
+ "Image {\n"
+ " source: srcImage;\n"
+ " colorSpace.namedColorSpace: ColorSpace.SRgb;\n"
+ "}";
+
+ QQmlComponent component2(&engine);
+ component2.setData(componentStr2.toLatin1(), QUrl::fromLocalFile(""));
+
+ QScopedPointer<QQuickImage> object2 { qobject_cast<QQuickImage*>(component2.create())};
+ QVERIFY(object2);
+ QTRY_COMPARE(object2->status(), QQuickImageBase::Ready);
+ QCOMPARE(object2->colorSpace(), QColorSpace(QColorSpace::SRgb));
+}
+
QTEST_MAIN(tst_qquickimage)
#include "tst_qquickimage.moc"
diff --git a/tests/auto/quick/qquickitem/data/hellotr_la.qm b/tests/auto/quick/qquickitem/data/hellotr_la.qm
new file mode 100644
index 0000000000..25c0aad583
--- /dev/null
+++ b/tests/auto/quick/qquickitem/data/hellotr_la.qm
Binary files differ
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index 8aab13e095..b5e001a2b7 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -40,6 +40,7 @@
#include "../../shared/util.h"
#include "../shared/viewtestutil.h"
#include <QSignalSpy>
+#include <QTranslator>
#ifdef TEST_QTBUG_60123
#include <QWidget>
@@ -70,6 +71,7 @@ public:
ulong timestamp;
QPoint lastWheelEventPos;
QPoint lastWheelEventGlobalPos;
+ int languageChangeEventCount = 0;
protected:
virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
@@ -86,6 +88,12 @@ protected:
lastWheelEventPos = event->position().toPoint();
lastWheelEventGlobalPos = event->globalPosition().toPoint();
}
+ bool event(QEvent *e) override
+ {
+ if (e->type() == QEvent::LanguageChange)
+ languageChangeEventCount++;
+ return QQuickItem::event(e);
+ }
};
class TestWindow: public QQuickWindow
@@ -198,6 +206,7 @@ private slots:
#endif
void setParentCalledInOnWindowChanged();
+ void receivesLanguageChangeEvent();
private:
@@ -2155,6 +2164,32 @@ void tst_qquickitem::setParentCalledInOnWindowChanged()
QVERIFY(ensureFocus(&view)); // should not crash
}
+void tst_qquickitem::receivesLanguageChangeEvent()
+{
+ QQuickWindow window;
+ window.setFramePosition(QPoint(100, 100));
+ window.resize(200, 200);
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ QScopedPointer<TestItem> child1(new TestItem);
+ child1->setObjectName(QStringLiteral("child1"));
+ child1->setSize(QSizeF(200, 100));
+ child1->setParentItem(window.contentItem());
+
+ QScopedPointer<TestItem> child2(new TestItem);
+ child2->setObjectName(QStringLiteral("child2"));
+ child2->setSize(QSizeF(50, 50));
+ child2->setParentItem(child1.data());
+
+ QTranslator t;
+ QVERIFY(t.load("hellotr_la.qm", dataDirectory()));
+ QVERIFY(QCoreApplication::installTranslator(&t));
+
+ QTRY_COMPARE(child1->languageChangeEventCount, 1);
+ QCOMPARE(child2->languageChangeEventCount, 1);
+}
+
QTEST_MAIN(tst_qquickitem)
#include "tst_qquickitem.moc"
diff --git a/tests/auto/quick/qquickitem2/data/mapCoordinates.qml b/tests/auto/quick/qquickitem2/data/mapCoordinates.qml
index 596dedab90..3e34633338 100644
--- a/tests/auto/quick/qquickitem2/data/mapCoordinates.qml
+++ b/tests/auto/quick/qquickitem2/data/mapCoordinates.qml
@@ -49,11 +49,21 @@ Item {
return Qt.point(pos.x, pos.y)
}
+ function mapAToBPoint(x, y) {
+ var pos = itemA.mapToItem(itemB, Qt.point(x, y))
+ return Qt.point(pos.x, pos.y)
+ }
+
function mapAFromB(x, y) {
var pos = itemA.mapFromItem(itemB, x, y)
return Qt.point(pos.x, pos.y)
}
+ function mapAFromBPoint(x, y) {
+ var pos = itemA.mapFromItem(itemB, Qt.point(x, y))
+ return Qt.point(pos.x, pos.y)
+ }
+
function mapAToNull(x, y) {
var pos = itemA.mapToItem(null, x, y)
return Qt.point(pos.x, pos.y)
@@ -69,11 +79,21 @@ Item {
return Qt.point(pos.x, pos.y)
}
+ function mapAToGlobalPoint(x, y) {
+ var pos = itemA.mapToGlobal(Qt.point(x, y))
+ return Qt.point(pos.x, pos.y)
+ }
+
function mapAFromGlobal(x, y) {
var pos = itemA.mapFromGlobal(x, y)
return Qt.point(pos.x, pos.y)
}
+ function mapAFromGlobalPoint(x, y) {
+ var pos = itemA.mapFromGlobal(Qt.point(x, y))
+ return Qt.point(pos.x, pos.y)
+ }
+
function mapOrphanToGlobal(x, y) {
var obj = itemComponent.createObject(null);
var pos = obj.mapToGlobal(x, y)
diff --git a/tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml b/tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml
index 2b856a27fc..c66d1e89b6 100644
--- a/tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml
+++ b/tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml
@@ -45,11 +45,21 @@ Item {
return Qt.rect(pos.x, pos.y, pos.width, pos.height)
}
+ function mapAToBRect(x, y, w, h) {
+ var pos = itemA.mapToItem(itemB, Qt.rect(x, y, w, h))
+ return Qt.rect(pos.x, pos.y, pos.width, pos.height)
+ }
+
function mapAFromB(x, y, w, h) {
var pos = itemA.mapFromItem(itemB, x, y, w, h)
return Qt.rect(pos.x, pos.y, pos.width, pos.height)
}
+ function mapAFromBRect(x, y, w, h) {
+ var pos = itemA.mapFromItem(itemB, Qt.rect(x, y, w, h))
+ return Qt.rect(pos.x, pos.y, pos.width, pos.height)
+ }
+
function mapAToNull(x, y, w, h) {
var pos = itemA.mapToItem(null, x, y, w, h)
return Qt.rect(pos.x, pos.y, pos.width, pos.height)
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index 767994ec7d..f01b3e25f1 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -77,8 +77,10 @@ private slots:
void qtbug_50516_2();
void keys();
+#if QT_CONFIG(shortcut)
void standardKeys_data();
void standardKeys();
+#endif
void keysProcessingOrder();
void keysim();
void keysForward();
@@ -1440,6 +1442,8 @@ void tst_QQuickItem::keys()
delete testObject;
}
+#if QT_CONFIG(shortcut)
+
Q_DECLARE_METATYPE(QEvent::Type);
Q_DECLARE_METATYPE(QKeySequence::StandardKey);
@@ -1498,6 +1502,8 @@ void tst_QQuickItem::standardKeys()
QCOMPARE(item->property("released").toBool(), released);
}
+#endif // QT_CONFIG(shortcut)
+
void tst_QQuickItem::keysProcessingOrder()
{
QQuickView *window = new QQuickView(nullptr);
@@ -2396,10 +2402,18 @@ void tst_QQuickItem::mapCoordinates()
Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToItem(b, QPointF(x, y)));
+ QVERIFY(QMetaObject::invokeMethod(root, "mapAToBPoint",
+ Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
+ QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToItem(b, QPointF(x, y)));
+
QVERIFY(QMetaObject::invokeMethod(root, "mapAFromB",
Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromItem(b, QPointF(x, y)));
+ QVERIFY(QMetaObject::invokeMethod(root, "mapAFromBPoint",
+ Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
+ QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromItem(b, QPointF(x, y)));
+
QVERIFY(QMetaObject::invokeMethod(root, "mapAToNull",
Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToScene(QPointF(x, y)));
@@ -2412,10 +2426,18 @@ void tst_QQuickItem::mapCoordinates()
Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToGlobal(QPointF(x, y)));
+ QVERIFY(QMetaObject::invokeMethod(root, "mapAToGlobalPoint",
+ Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
+ QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToGlobal(QPointF(x, y)));
+
QVERIFY(QMetaObject::invokeMethod(root, "mapAFromGlobal",
Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromGlobal(QPointF(x, y)));
+ QVERIFY(QMetaObject::invokeMethod(root, "mapAFromGlobalPoint",
+ Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
+ QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromGlobal(QPointF(x, y)));
+
// for orphans we are primarily testing that we don't crash.
// when orphaned the final position is the original position of the item translated by x,y
QVERIFY(QMetaObject::invokeMethod(root, "mapOrphanToGlobal",
@@ -2477,10 +2499,18 @@ void tst_QQuickItem::mapCoordinatesRect()
Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
QCOMPARE(result.value<QRectF>(), qobject_cast<QQuickItem*>(a)->mapRectToItem(b, QRectF(x, y, width, height)));
+ QVERIFY(QMetaObject::invokeMethod(root, "mapAToBRect",
+ Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
+ QCOMPARE(result.value<QRectF>(), qobject_cast<QQuickItem*>(a)->mapRectToItem(b, QRectF(x, y, width, height)));
+
QVERIFY(QMetaObject::invokeMethod(root, "mapAFromB",
Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
QCOMPARE(result.value<QRectF>(), qobject_cast<QQuickItem*>(a)->mapRectFromItem(b, QRectF(x, y, width, height)));
+ QVERIFY(QMetaObject::invokeMethod(root, "mapAFromBRect",
+ Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
+ QCOMPARE(result.value<QRectF>(), qobject_cast<QQuickItem*>(a)->mapRectFromItem(b, QRectF(x, y, width, height)));
+
QVERIFY(QMetaObject::invokeMethod(root, "mapAToNull",
Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
QCOMPARE(result.value<QRectF>(), qobject_cast<QQuickItem*>(a)->mapRectToScene(QRectF(x, y, width, height)));
@@ -3369,7 +3399,7 @@ void tst_QQuickItem::grab()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabToImage not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabToImage not functional on offscreen/minimal platforms");
QQuickView view;
view.setSource(testFileUrl("grabToImage.qml"));
diff --git a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
index 2f90632841..824db1b080 100644
--- a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
+++ b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
@@ -149,7 +149,7 @@ void tst_QQuickItemLayer::layerSmooth()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QImage fb = runTest("Smooth.qml");
QVERIFY(!fb.size().isEmpty());
@@ -174,7 +174,7 @@ void tst_QQuickItemLayer::layerEnabled()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QImage fb = runTest("Enabled.qml");
QVERIFY(!fb.size().isEmpty());
@@ -210,7 +210,7 @@ void tst_QQuickItemLayer::layerEffect()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QImage fb = runTest("Effect.qml");
QVERIFY(!fb.size().isEmpty());
@@ -475,7 +475,7 @@ void tst_QQuickItemLayer::rectangleEffect()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QImage fb = runTest("RectangleEffect.qml");
QVERIFY(!fb.size().isEmpty());
diff --git a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
index 0732884c97..f61e2e0f48 100644
--- a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
+++ b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
@@ -118,10 +118,10 @@ Item {
function test_warnAboutLayoutItemsWithAnchors()
{
- var fullPath = Qt.resolvedUrl("tst_rowlayout.qml")
+ var regex = new RegExp("QML Item: Detected anchors on an item that is managed by a layout. "
+ + "This is undefined behavior; use Layout.alignment instead.")
for (var i = 0; i < 7; ++i) {
- ignoreWarning(fullPath + ":" + (75 + 5*i) +":17: QML Item: Detected anchors on an item that is managed by a layout. "
- + "This is undefined behavior; use Layout.alignment instead.")
+ ignoreWarning(regex)
}
var layout = itemsWithAnchorsLayout_Component.createObject(container)
waitForRendering(layout)
diff --git a/tests/auto/quick/qquicklistview/data/delegatesWithRequiredProperties.qml b/tests/auto/quick/qquicklistview/data/delegatesWithRequiredProperties.qml
new file mode 100644
index 0000000000..f354517678
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/delegatesWithRequiredProperties.qml
@@ -0,0 +1,47 @@
+import QtQuick 2.12
+import Qt.fruit 1.0
+
+Rectangle {
+ id: root
+ required property bool useCpp
+ width: 200; height: 200
+
+
+ ListModel {
+ id: fruitModel
+
+ ListElement {
+ name: "Apple"
+ cost: 2
+ }
+ ListElement {
+ name: "Orange"
+ cost: 3
+ }
+ ListElement {
+ name: "Banana"
+ cost: 1
+ }
+ }
+
+
+ Component {
+ id: fruitDelegate
+ Row {
+ id: row
+ spacing: 10
+ required property string name
+ required property int cost
+ Text { text: row.name }
+ Text { text: '$' + row.cost }
+ Component.onCompleted: () => { console.debug(row.name+row.cost) };
+ }
+ }
+
+ ListView {
+ anchors.fill: parent
+ model: root.useCpp ? FruitModelCpp : fruitModel
+ delegate: fruitDelegate
+ }
+
+}
diff --git a/tests/auto/quick/qquicklistview/data/listview-sections_delegate_required.qml b/tests/auto/quick/qquicklistview/data/listview-sections_delegate_required.qml
new file mode 100644
index 0000000000..18ce406e3f
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/listview-sections_delegate_required.qml
@@ -0,0 +1,77 @@
+import QtQuick 2.0
+
+Rectangle {
+ property string sectionProperty: "number"
+ property int sectionPositioning: ViewSection.InlineLabels
+ width: 240
+ height: 320
+ color: "#ffffff"
+ resources: [
+ Component {
+ id: myDelegate
+ Item {
+ id: wrapper
+ objectName: "wrapper"
+ property string section: ListView.section
+ property string nextSection: ListView.nextSection
+ property string prevSection: ListView.previousSection
+ height: 20;
+ width: 240
+ Rectangle {
+ height: 20
+ width: parent.width
+ color: wrapper.ListView.isCurrentItem ? "lightsteelblue" : "white"
+ Text {
+ text: index
+ }
+ Text {
+ x: 30
+ id: textName
+ objectName: "textName"
+ text: name
+ }
+ Text {
+ x: 100
+ id: textNumber
+ objectName: "textNumber"
+ text: number
+ }
+ Text {
+ objectName: "nextSection"
+ x: 150
+ text: wrapper.ListView.nextSection
+ }
+ Text {
+ x: 200
+ text: wrapper.y
+ }
+ }
+ ListView.onRemove: SequentialAnimation {
+ PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: true }
+ NumberAnimation { target: wrapper; property: "height"; to: 0; duration: 100; easing.type: Easing.InOutQuad }
+ PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: false }
+ }
+ }
+ }
+ ]
+ ListView {
+ id: list
+ objectName: "list"
+ width: 240
+ height: 320
+ cacheBuffer: 60
+ model: testModel
+ delegate: myDelegate
+ section.property: sectionProperty
+ section.delegate: Rectangle {
+ id: myDelegate
+ required property string section
+ objectName: "sect_" + section
+ color: "#99bb99"
+ height: 20
+ width: list.width
+ Text { text: myDelegate.section + ", " + parent.y + ", " + parent.objectName }
+ }
+ section.labelPositioning: sectionPositioning
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/requiredObjectListModel.qml b/tests/auto/quick/qquicklistview/data/requiredObjectListModel.qml
new file mode 100644
index 0000000000..f6380ed5aa
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/requiredObjectListModel.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.0
+
+ListView {
+ width: 100
+ height: 100
+ required model
+
+ delegate: Rectangle {
+ required color
+ required property string name
+
+ height: 25
+ width: 100
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/reusedelegateitems.qml b/tests/auto/quick/qquicklistview/data/reusedelegateitems.qml
new file mode 100644
index 0000000000..773fb50f81
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/reusedelegateitems.qml
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.15
+
+Rectangle {
+ id: root
+ width: 640
+ height: 480
+
+ property int rows: 500
+ property int columns: 20
+ property real delegateHeight: 30
+ property real delegateWidth: 50
+
+ ListView {
+ id: list
+ anchors.fill: parent
+ anchors.margins: 10
+ objectName: "list"
+
+ model: reuseModel
+ reuseItems: true
+
+ cacheBuffer: 0
+ contentWidth: columns * delegateWidth
+ contentHeight: rows * delegateHeight
+ clip: true
+
+ property int delegatesCreatedCount: 0
+
+ delegate: Item {
+ objectName: "delegate"
+ width: list.contentWidth
+ height: delegateHeight
+
+ property int modelIndex: index
+ property int reusedCount: 0
+ property int pooledCount: 0
+ property string displayBinding: display
+
+ ListView.onPooled: pooledCount++
+ ListView.onReused: reusedCount++
+ Component.onCompleted: list.delegatesCreatedCount++
+
+ Text {
+ id: text1
+ text: display + " (Model index: " + modelIndex + ", Reused count: " + reusedCount + ")"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/qquicklistview.pro b/tests/auto/quick/qquicklistview/qquicklistview.pro
index b08fca2b1d..10edb06549 100644
--- a/tests/auto/quick/qquicklistview/qquicklistview.pro
+++ b/tests/auto/quick/qquicklistview/qquicklistview.pro
@@ -5,7 +5,8 @@ macx:CONFIG -= app_bundle
HEADERS += incrementalmodel.h \
proxytestinnermodel.h \
- randomsortmodel.h
+ randomsortmodel.h \
+ reusemodel.h
SOURCES += tst_qquicklistview.cpp \
incrementalmodel.cpp \
proxytestinnermodel.cpp \
diff --git a/tests/auto/quick/qquicklistview/reusemodel.h b/tests/auto/quick/qquicklistview/reusemodel.h
new file mode 100644
index 0000000000..21e6739384
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/reusemodel.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef REUSEMODEL_H
+#define REUSEMODEL_H
+
+#include <QAbstractListModel>
+#include <QList>
+#include <QStringList>
+
+class ReuseModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ ReuseModel(int rowCount, QObject *parent = nullptr)
+ : QAbstractListModel(parent)
+ , m_rowCount(rowCount)
+ {}
+
+ int rowCount(const QModelIndex & = QModelIndex()) const override
+ {
+ return m_rowCount;
+ }
+
+ QVariant data(const QModelIndex &index, int role) const override
+ {
+ if (!index.isValid())
+ return QVariant();
+
+ switch (role) {
+ case Qt::DisplayRole:
+ return displayStringForRow(index.row());
+ default:
+ break;
+ }
+
+ return QVariant();
+ }
+
+ QString displayStringForRow(int row) const
+ {
+ return row % 2 == 0 ?
+ QStringLiteral("Even%1").arg(row) :
+ QStringLiteral("Odd%1").arg(row);
+ }
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return {
+ {Qt::DisplayRole, "display"},
+ };
+ }
+
+private:
+ int m_rowCount;
+};
+
+#endif
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index 20d71aa0d7..4e49344bc0 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -41,6 +41,7 @@
#include <QtQuick/private/qquicklistview_p.h>
#include <QtQuick/private/qquickmousearea_p.h>
#include <QtQuick/private/qquicktext_p.h>
+#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQmlModels/private/qqmlobjectmodel_p.h>
#include <QtQmlModels/private/qqmllistmodel_p.h>
#include <QtQmlModels/private/qqmldelegatemodel_p.h>
@@ -50,6 +51,7 @@
#include "incrementalmodel.h"
#include "proxytestinnermodel.h"
#include "randomsortmodel.h"
+#include "reusemodel.h"
#include <math.h>
Q_DECLARE_METATYPE(Qt::LayoutDirection)
@@ -128,6 +130,7 @@ private slots:
void qAbstractItemModel_package_sections();
void qAbstractItemModel_sections();
void sectionsPositioning();
+ void sectionsDelegate_data();
void sectionsDelegate();
void sectionsDragOutsideBounds_data();
void sectionsDragOutsideBounds();
@@ -283,9 +286,17 @@ private slots:
void setPositionOnLayout();
void touchCancel();
void resizeAfterComponentComplete();
+ void dragOverFloatingHeaderOrFooter();
+
+ void delegateWithRequiredProperties();
+
+ void reuse_reuseIsOffByDefault();
+ void reuse_checkThatItemsAreReused();
void moveObjectModelItemToAnotherObjectModel();
void changeModelAndDestroyTheOldOne();
+ void requiredObjectListModel();
+
private:
template <class T> void items(const QUrl &source);
template <class T> void changed(const QUrl &source);
@@ -395,7 +406,7 @@ void tst_QQuickListView::init()
m_view = nullptr;
}
#endif
- qmlRegisterType<QAbstractItemModel>();
+ qmlRegisterAnonymousType<QAbstractItemModel>("Proxy", 1);
qmlRegisterType<ProxyTestInnerModel>("Proxy", 1, 0, "ProxyTestInnerModel");
qmlRegisterType<QSortFilterProxyModel>("Proxy", 1, 0, "QSortFilterProxyModel");
}
@@ -422,8 +433,8 @@ void tst_QQuickListView::items(const QUrl &source)
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(source);
qApp->processEvents();
@@ -487,8 +498,6 @@ void tst_QQuickListView::items(const QUrl &source)
QTRY_COMPARE(listview->highlightResizeVelocity(), 1000.0);
QTRY_COMPARE(listview->highlightMoveVelocity(), 100000.0);
-
- delete testObject;
}
@@ -505,8 +514,8 @@ void tst_QQuickListView::changed(const QUrl &source)
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(source);
qApp->processEvents();
@@ -528,8 +537,6 @@ void tst_QQuickListView::changed(const QUrl &source)
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(1));
-
- delete testObject;
}
template <class T>
@@ -547,8 +554,8 @@ void tst_QQuickListView::inserted(const QUrl &source)
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(source);
qApp->processEvents();
@@ -625,8 +632,6 @@ void tst_QQuickListView::inserted(const QUrl &source)
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
QVERIFY(item);
QTRY_COMPARE(item->y() - listview->contentY(), 0.);
-
- delete testObject;
}
template <class T>
@@ -645,8 +650,8 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("listviewtest.qml"));
window->show();
@@ -704,7 +709,7 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v
break;
}
}
- QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
+ QVERIFY2(firstVisibleIndex >= 0, QByteArray::number(firstVisibleIndex));
// Confirm items positioned correctly and indexes correct
QQuickText *name;
@@ -713,14 +718,14 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v
const qreal visibleToPos = listview->contentY() + listview->height() + listview->displayMarginEnd() + listview->cacheBuffer();
for (int i = firstVisibleIndex; i < model.count() && i < items.count(); ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i)));
qreal pos = i*20.0 + itemsOffsetAfterMove;
if (verticalLayoutDirection == QQuickItemView::BottomToTop)
pos = -item->height() - pos;
// Items outside the visible area (including cache buffer) should be skipped
if (pos > visibleToPos || pos < visibleFromPos) {
QTRY_VERIFY2(QQuickItemPrivate::get(item)->culled || item->y() < visibleFromPos || item->y() > visibleToPos,
- QTest::toString(QString("index %5, y %1, from %2, to %3, expected pos %4, culled %6").
+ qPrintable(QString("index %5, y %1, from %2, to %3, expected pos %4, culled %6").
arg(item->y()).arg(visibleFromPos).arg(visibleToPos).arg(pos).arg(i).arg(bool(QQuickItemPrivate::get(item)->culled))));
continue;
}
@@ -734,7 +739,6 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v
}
releaseView(window);
- delete testObject;
}
void tst_QQuickListView::inserted_more_data()
@@ -840,8 +844,8 @@ void tst_QQuickListView::insertBeforeVisible()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("listviewtest.qml"));
window->show();
@@ -889,7 +893,7 @@ void tst_QQuickListView::insertBeforeVisible()
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
for (int i = 0; i < model.count() && i < itemCount; ++i) {
item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i)));
QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
name = findItem<QQuickText>(contentItem, "textName", i);
QVERIFY(name != nullptr);
@@ -897,7 +901,6 @@ void tst_QQuickListView::insertBeforeVisible()
}
releaseView(window);
- delete testObject;
}
void tst_QQuickListView::insertBeforeVisible_data()
@@ -953,8 +956,8 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */)
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(source);
window->show();
@@ -1116,8 +1119,6 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */)
for (int i = 0; i < 18; ++i)
model.removeItems(model.count() - 1, 1);
QTRY_VERIFY(findItems<QQuickItem>(contentItem, "wrapper").count() > 16);
-
- delete testObject;
}
template <class T>
@@ -1137,8 +1138,8 @@ void tst_QQuickListView::removed_more(const QUrl &source, QQuickItemView::Vertic
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(source);
window->show();
@@ -1180,14 +1181,14 @@ void tst_QQuickListView::removed_more(const QUrl &source, QQuickItemView::Vertic
break;
}
}
- QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
+ QVERIFY2(firstVisibleIndex >= 0, QByteArray::number(firstVisibleIndex));
// Confirm items positioned correctly and indexes correct
QQuickText *name;
QQuickText *number;
for (int i = firstVisibleIndex; i < model.count() && i < items.count(); ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i)));
qreal pos = i*20.0 + itemsOffsetAfterMove;
if (verticalLayoutDirection == QQuickItemView::BottomToTop)
pos = -item0->height() - pos;
@@ -1201,7 +1202,6 @@ void tst_QQuickListView::removed_more(const QUrl &source, QQuickItemView::Vertic
}
releaseView(window);
- delete testObject;
}
void tst_QQuickListView::removed_more_data()
@@ -1319,8 +1319,8 @@ void tst_QQuickListView::clear(const QUrl &source, QQuickItemView::VerticalLayou
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(source);
window->show();
@@ -1353,8 +1353,6 @@ void tst_QQuickListView::clear(const QUrl &source, QQuickItemView::VerticalLayou
QTRY_COMPARE(listview->count(), 1);
QVERIFY(listview->currentItem() != nullptr);
QCOMPARE(listview->currentIndex(), 0);
-
- delete testObject;
}
template <class T>
@@ -1377,8 +1375,8 @@ void tst_QQuickListView::moved(const QUrl &source, QQuickItemView::VerticalLayou
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(source);
window->show();
@@ -1414,12 +1412,12 @@ void tst_QQuickListView::moved(const QUrl &source, QQuickItemView::VerticalLayou
break;
}
}
- QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
+ QVERIFY2(firstVisibleIndex >= 0, QByteArray::number(firstVisibleIndex));
// Confirm items positioned correctly and indexes correct
for (int i = firstVisibleIndex; i < model.count() && i < items.count(); ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i)));
qreal pos = i*20.0 + itemsOffsetAfterMove;
if (verticalLayoutDirection == QQuickItemView::BottomToTop)
pos = -item->height() - pos;
@@ -1437,7 +1435,6 @@ void tst_QQuickListView::moved(const QUrl &source, QQuickItemView::VerticalLayou
}
releaseView(window);
- delete testObject;
}
void tst_QQuickListView::moved_data()
@@ -1607,8 +1604,8 @@ void tst_QQuickListView::multipleChanges(bool condensed)
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("listviewtest.qml"));
window->show();
@@ -1660,7 +1657,7 @@ void tst_QQuickListView::multipleChanges(bool condensed)
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
for (int i=0; i < model.count() && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i)));
name = findItem<QQuickText>(contentItem, "textName", i);
QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
@@ -1669,7 +1666,6 @@ void tst_QQuickListView::multipleChanges(bool condensed)
QTRY_COMPARE(number->text(), model.number(i));
}
- delete testObject;
releaseView(window);
}
@@ -1855,8 +1851,8 @@ void tst_QQuickListView::swapWithFirstItem()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("listviewtest.qml"));
window->show();
@@ -1870,8 +1866,6 @@ void tst_QQuickListView::swapWithFirstItem()
listview->setContentY(0);
model.moveItem(1, 0);
QTRY_COMPARE(listview->contentY(), qreal(0));
-
- delete testObject;
}
void tst_QQuickListView::checkCountForMultiColumnModels()
@@ -2039,8 +2033,8 @@ void tst_QQuickListView::spacing()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("listviewtest.qml"));
window->show();
@@ -2084,8 +2078,6 @@ void tst_QQuickListView::spacing()
QTRY_VERIFY(item);
QTRY_COMPARE(item->y(), i*20.0);
}
-
- delete testObject;
}
template <typename T>
@@ -2189,8 +2181,17 @@ void tst_QQuickListView::sections(const QUrl &source)
QTRY_COMPARE(item->height(), 40.0);
}
+void tst_QQuickListView::sectionsDelegate_data()
+{
+ QTest::addColumn<QUrl>("path");
+ QTest::addRow("implicit") << testFileUrl("listview-sections_delegate.qml");
+ QTest::addRow("required") << testFileUrl("listview-sections_delegate_required.qml");
+}
+
void tst_QQuickListView::sectionsDelegate()
{
+ QFETCH(QUrl, path);
+
QScopedPointer<QQuickView> window(createView());
QaimModel model;
@@ -2200,7 +2201,7 @@ void tst_QQuickListView::sectionsDelegate()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- window->setSource(testFileUrl("listview-sections_delegate.qml"));
+ window->setSource(path);
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
@@ -2803,7 +2804,7 @@ void tst_QQuickListView::currentIndex()
for (int i = 0; i < 30; i++)
initModel.addItem("Item" + QString::number(i), QString::number(i));
- QQuickView *window = new QQuickView(nullptr);
+ QScopedPointer<QQuickView> window(new QQuickView(nullptr));
window->setGeometry(0,0,240,320);
QQmlContext *ctxt = window->rootContext();
@@ -2813,7 +2814,7 @@ void tst_QQuickListView::currentIndex()
QString filename(testFile("listview-initCurrent.qml"));
window->setSource(QUrl::fromLocalFile(filename));
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
QTRY_VERIFY(listview != nullptr);
@@ -2901,8 +2902,6 @@ void tst_QQuickListView::currentIndex()
QCOMPARE(QQmlProperty(window->rootObject(), "s").read().toString(), "-1");
QCOMPARE(window->rootObject()->property("currentItemChangedCount").toInt(), 1);
QCOMPARE(listview->currentIndex(), -1);
-
- delete window;
}
void tst_QQuickListView::noCurrentIndex()
@@ -2911,7 +2910,7 @@ void tst_QQuickListView::noCurrentIndex()
for (int i = 0; i < 30; i++)
model.addItem("Item" + QString::number(i), QString::number(i));
- QQuickView *window = new QQuickView(nullptr);
+ QScopedPointer<QQuickView> window(new QQuickView(nullptr));
window->setGeometry(0,0,240,320);
QQmlContext *ctxt = window->rootContext();
@@ -2920,7 +2919,7 @@ void tst_QQuickListView::noCurrentIndex()
QString filename(testFile("listview-noCurrent.qml"));
window->setSource(QUrl::fromLocalFile(filename));
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
QTRY_VERIFY(listview != nullptr);
@@ -2939,8 +2938,6 @@ void tst_QQuickListView::noCurrentIndex()
QCOMPARE(listview->currentIndex(), 2);
QVERIFY(listview->highlightItem());
QVERIFY(listview->currentItem());
-
- delete window;
}
void tst_QQuickListView::keyNavigation()
@@ -2958,9 +2955,9 @@ void tst_QQuickListView::keyNavigation()
model.addItem("Item" + QString::number(i), "");
QQuickView *window = getView();
- TestObject *testObject = new TestObject;
+ QScopedPointer<TestObject> testObject(new TestObject);
window->rootContext()->setContextProperty("testModel", &model);
- window->rootContext()->setContextProperty("testObject", testObject);
+ window->rootContext()->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("listviewtest.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowActive(window));
@@ -3030,7 +3027,6 @@ void tst_QQuickListView::keyNavigation()
QTRY_COMPARE(listview->contentY(), contentPosAtFirstItem.y());
releaseView(window);
- delete testObject;
}
void tst_QQuickListView::keyNavigation_data()
@@ -3172,8 +3168,8 @@ void tst_QQuickListView::cacheBuffer()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("listviewtest.qml"));
window->show();
@@ -3261,8 +3257,6 @@ void tst_QQuickListView::cacheBuffer()
// negative cache buffer is ignored
listview->setCacheBuffer(-1);
QCOMPARE(listview->cacheBuffer(), 200);
-
- delete testObject;
}
void tst_QQuickListView::positionViewAtBeginningEnd()
@@ -3276,8 +3270,8 @@ void tst_QQuickListView::positionViewAtBeginningEnd()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->show();
window->setSource(testFileUrl("listviewtest.qml"));
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
@@ -3315,8 +3309,6 @@ void tst_QQuickListView::positionViewAtBeginningEnd()
QTRY_COMPARE(listview->contentY(), -30.);
QVERIFY(listview->highlightItem());
QCOMPARE(listview->highlightItem()->y(), 20.);
-
- delete testObject;
}
void tst_QQuickListView::positionViewAtIndex()
@@ -3336,8 +3328,8 @@ void tst_QQuickListView::positionViewAtIndex()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->show();
window->setSource(testFileUrl("listviewtest.qml"));
QVERIFY(QTest::qWaitForWindowExposed(window));
@@ -3642,7 +3634,7 @@ void tst_QQuickListView::QTBUG_33568()
void tst_QQuickListView::manualHighlight()
{
- QQuickView *window = new QQuickView(nullptr);
+ QScopedPointer<QQuickView> window(new QQuickView(nullptr));
window->setGeometry(0,0,240,320);
QString filename(testFile("manual-highlight.qml"));
@@ -3672,8 +3664,6 @@ void tst_QQuickListView::manualHighlight()
QTRY_COMPARE(listview->currentIndex(), 2);
QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
-
- delete window;
}
void tst_QQuickListView::QTBUG_11105()
@@ -3686,8 +3676,8 @@ void tst_QQuickListView::QTBUG_11105()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("listviewtest.qml"));
window->show();
@@ -3719,8 +3709,6 @@ void tst_QQuickListView::QTBUG_11105()
itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
QCOMPARE(itemCount, 5);
-
- delete testObject;
}
void tst_QQuickListView::initialZValues()
@@ -4358,8 +4346,8 @@ void tst_QQuickListView::resizeView()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("listviewtest.qml"));
window->show();
@@ -4422,8 +4410,6 @@ void tst_QQuickListView::resizeView()
QTRY_COMPARE(item->y(), i*20.);
QCOMPARE(delegateVisible(item), i < 6); // inside view visible, outside not visible
}
-
- delete testObject;
}
void tst_QQuickListView::resizeViewAndRepaint()
@@ -4470,8 +4456,8 @@ void tst_QQuickListView::sizeLessThan1()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("sizelessthan1.qml"));
window->show();
@@ -4491,8 +4477,6 @@ void tst_QQuickListView::sizeLessThan1()
QTRY_VERIFY(item);
QTRY_COMPARE(item->y(), i*0.5);
}
-
- delete testObject;
}
void tst_QQuickListView::QTBUG_14821()
@@ -4603,8 +4587,8 @@ void tst_QQuickListView::resizeFirstDelegate()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("listviewtest.qml"));
window->show();
@@ -4659,8 +4643,6 @@ void tst_QQuickListView::resizeFirstDelegate()
for (int i=0; i<3; i++) {
QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", i));
}
-
- delete testObject;
}
void tst_QQuickListView::repositionResizedDelegate()
@@ -4812,8 +4794,8 @@ void tst_QQuickListView::indexAt_itemAt()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("listviewtest.qml"));
window->show();
@@ -4835,7 +4817,6 @@ void tst_QQuickListView::indexAt_itemAt()
QCOMPARE(listview->itemAt(x,y), item);
releaseView(window);
- delete testObject;
}
void tst_QQuickListView::itemAtIndex()
@@ -6466,7 +6447,7 @@ void tst_QQuickListView::unrequestedVisibility()
for (int i = 0; i < 30; i++)
model.addItem("Item" + QString::number(i), QString::number(i));
- QQuickView *window = new QQuickView(nullptr);
+ QScopedPointer<QQuickView> window(new QQuickView(nullptr));
window->setGeometry(0,0,240,320);
QQmlContext *ctxt = window->rootContext();
@@ -6475,7 +6456,7 @@ void tst_QQuickListView::unrequestedVisibility()
window->setSource(testFileUrl("unrequestedItems.qml"));
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *leftview;
@@ -6662,8 +6643,6 @@ void tst_QQuickListView::unrequestedVisibility()
item = findItem<QQuickItem>(rightContent, wrapperObjectName, 17);
QVERIFY(item);
QCOMPARE(delegateVisible(item), false);
-
- delete window;
}
void tst_QQuickListView::populateTransitions()
@@ -6684,8 +6663,9 @@ void tst_QQuickListView::populateTransitions()
}
QQuickView *window = getView();
+ QScopedPointer<TestObject> testObject(new TestObject(window->rootContext()));
window->rootContext()->setContextProperty("testModel", &model);
- window->rootContext()->setContextProperty("testObject", new TestObject(window->rootContext()));
+ window->rootContext()->setContextProperty("testObject", testObject.data());
window->rootContext()->setContextProperty("usePopulateTransition", usePopulateTransition);
window->rootContext()->setContextProperty("dynamicallyPopulate", dynamicallyPopulate);
window->rootContext()->setContextProperty("transitionFrom", transitionFrom);
@@ -6716,7 +6696,7 @@ void tst_QQuickListView::populateTransitions()
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
for (int i=0; i < model.count() && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i)));
QTRY_COMPARE(item->x(), 0.0);
QTRY_COMPARE(item->y(), i*20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
@@ -6751,7 +6731,7 @@ void tst_QQuickListView::populateTransitions()
itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
for (int i=0; i < model.count() && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i)));
QTRY_COMPARE(item->x(), 0.0);
QTRY_COMPARE(item->y(), i*20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
@@ -6769,7 +6749,7 @@ void tst_QQuickListView::populateTransitions()
itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
for (int i=0; i < model.count() && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i)));
QTRY_COMPARE(item->x(), 0.0);
QTRY_COMPARE(item->y(), i*20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
@@ -6811,7 +6791,7 @@ void tst_QQuickListView::sizeTransitions()
QaimModel model;
ctxt->setContextProperty("testModel", &model);
ctxt->setContextProperty("topToBottom", topToBottom);
- TestObject *testObject = new TestObject;
+ QScopedPointer<TestObject> testObject(new TestObject);
ctxt->setContextProperty("testObject", &model);
window->setSource(testFileUrl("sizeTransitions.qml"));
window->show();
@@ -6832,7 +6812,6 @@ void tst_QQuickListView::sizeTransitions()
QCOMPARE(listview->property("transitionFinished").toBool(), true);
releaseView(window);
- delete testObject;
}
void tst_QQuickListView::sizeTransitions_data()
@@ -6869,13 +6848,13 @@ void tst_QQuickListView::addTransitions()
QQuickView *window = getView();
QQmlContext *ctxt = window->rootContext();
- TestObject *testObject = new TestObject;
+ QScopedPointer<TestObject> testObject(new TestObject);
ctxt->setContextProperty("testModel", &model);
ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
- ctxt->setContextProperty("testObject", testObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("addTransitions.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
@@ -6954,12 +6933,12 @@ void tst_QQuickListView::addTransitions()
break;
}
}
- QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
+ QVERIFY2(firstVisibleIndex >= 0, QByteArray::number(firstVisibleIndex));
// verify all items moved to the correct final positions
for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i)));
QTRY_COMPARE(item->y(), i*20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
QVERIFY(name != nullptr);
@@ -6967,7 +6946,6 @@ void tst_QQuickListView::addTransitions()
}
releaseView(window);
- delete testObject;
}
void tst_QQuickListView::addTransitions_data()
@@ -7065,13 +7043,13 @@ void tst_QQuickListView::moveTransitions()
QQuickView *window = getView();
QQmlContext *ctxt = window->rootContext();
- TestObject *testObject = new TestObject;
+ QScopedPointer<TestObject> testObject(new TestObject);
ctxt->setContextProperty("testModel", &model);
ctxt->setContextProperty("model_targetItems_transitionVia", &model_targetItems_transitionVia);
ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
ctxt->setContextProperty("targetItems_transitionVia", targetItems_transitionVia);
ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
- ctxt->setContextProperty("testObject", testObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("moveTransitions.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
@@ -7138,13 +7116,13 @@ void tst_QQuickListView::moveTransitions()
break;
}
}
- QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
+ QVERIFY2(firstVisibleIndex >= 0, QByteArray::number(firstVisibleIndex));
// verify all items moved to the correct final positions
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i)));
QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
name = findItem<QQuickText>(contentItem, "textName", i);
QVERIFY(name != nullptr);
@@ -7152,7 +7130,6 @@ void tst_QQuickListView::moveTransitions()
}
releaseView(window);
- delete testObject;
}
void tst_QQuickListView::moveTransitions_data()
@@ -7268,13 +7245,13 @@ void tst_QQuickListView::removeTransitions()
QQuickView *window = getView();
QQmlContext *ctxt = window->rootContext();
- TestObject *testObject = new TestObject;
+ QScopedPointer<TestObject> testObject(new TestObject);
ctxt->setContextProperty("testModel", &model);
ctxt->setContextProperty("model_targetItems_transitionTo", &model_targetItems_transitionTo);
ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
ctxt->setContextProperty("targetItems_transitionTo", targetItems_transitionTo);
ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
- ctxt->setContextProperty("testObject", testObject);
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("removeTransitions.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
@@ -7352,12 +7329,12 @@ void tst_QQuickListView::removeTransitions()
if (index < 0)
itemCount--; // exclude deleted items
}
- QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
+ QVERIFY2(firstVisibleIndex >= 0, QByteArray::number(firstVisibleIndex));
// verify all items moved to the correct final positions
for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "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->x(), 0.0);
QCOMPARE(item->y(), contentY + (i-firstVisibleIndex) * 20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
@@ -7366,7 +7343,6 @@ void tst_QQuickListView::removeTransitions()
}
releaseView(window);
- delete testObject;
}
void tst_QQuickListView::removeTransitions_data()
@@ -7467,9 +7443,9 @@ void tst_QQuickListView::displacedTransitions()
QQuickView *window = getView();
QQmlContext *ctxt = window->rootContext();
- TestObject *testObject = new TestObject(window);
+ QScopedPointer<TestObject> testObject(new TestObject(window));
ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testObject", testObject);
+ ctxt->setContextProperty("testObject", testObject.data());
ctxt->setContextProperty("model_displaced_transitionVia", &model_displaced_transitionVia);
ctxt->setContextProperty("model_addDisplaced_transitionVia", &model_addDisplaced_transitionVia);
ctxt->setContextProperty("model_moveDisplaced_transitionVia", &model_moveDisplaced_transitionVia);
@@ -7490,7 +7466,6 @@ void tst_QQuickListView::displacedTransitions()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
-
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
@@ -7572,7 +7547,7 @@ void tst_QQuickListView::displacedTransitions()
QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
for (int i=0; i < model.count() && i < items.count(); ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "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->x(), 0.0);
QCOMPARE(item->y(), i * 20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
@@ -7694,9 +7669,9 @@ void tst_QQuickListView::multipleTransitions()
QQuickView *window = getView();
QQmlContext *ctxt = window->rootContext();
- TestObject *testObject = new TestObject;
+ QScopedPointer<TestObject> testObject(new TestObject);
ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testObject", testObject);
+ ctxt->setContextProperty("testObject", testObject.data());
ctxt->setContextProperty("addTargets_transitionFrom", addTargets_transitionFrom);
ctxt->setContextProperty("addDisplaced_transitionFrom", addDisplaced_transitionFrom);
ctxt->setContextProperty("moveTargets_transitionFrom", moveTargets_transitionFrom);
@@ -7780,7 +7755,7 @@ void tst_QQuickListView::multipleTransitions()
QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
for (int i=0; i < model.count() && i < items.count(); ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i)));
QTRY_COMPARE(item->x(), 0.0);
QTRY_COMPARE(item->y(), i*20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
@@ -7789,7 +7764,6 @@ void tst_QQuickListView::multipleTransitions()
}
releaseView(window);
- delete testObject;
}
void tst_QQuickListView::multipleTransitions_data()
@@ -7862,8 +7836,9 @@ void tst_QQuickListView::multipleDisplaced()
QQuickView *window = getView();
QQmlContext *ctxt = window->rootContext();
+ QScopedPointer<TestObject> testObject(new TestObject(window));
ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testObject", new TestObject(window));
+ ctxt->setContextProperty("testObject", testObject.data());
window->setSource(testFileUrl("multipleDisplaced.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
@@ -7882,14 +7857,14 @@ void tst_QQuickListView::multipleDisplaced()
QVariantMap transitionsStarted = listview->property("displaceTransitionsStarted").toMap();
foreach (const QString &name, transitionsStarted.keys()) {
QVERIFY2(transitionsStarted[name] == 1,
- QTest::toString(QString("%1 was displaced %2 times").arg(name).arg(transitionsStarted[name].toInt())));
+ qPrintable(QString("%1 was displaced %2 times").arg(name).arg(transitionsStarted[name].toInt())));
}
// verify all items moved to the correct final positions
QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
for (int i=0; i < model.count() && i < items.count(); ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i)));
QTRY_COMPARE(item->x(), 0.0);
QTRY_COMPARE(item->y(), i*20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
@@ -7931,7 +7906,7 @@ void tst_QQuickListView::matchItemsAndIndexes(const QVariantMap &items, const Qa
QCOMPARE(it.value().type(), QVariant::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);
@@ -7946,8 +7921,8 @@ void tst_QQuickListView::matchItemLists(const QVariantList &itemLists, const QLi
QVariantList current = itemLists[i].toList();
for (int j=0; j<current.count(); 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.count(), expectedItems.count());
}
@@ -8121,7 +8096,7 @@ void tst_QQuickListView::defaultHighlightMoveDuration()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; ListView {}", QUrl::fromLocalFile(""));
- QObject *obj = component.create();
+ QScopedPointer<QObject> obj(component.create());
QVERIFY(obj);
QCOMPARE(obj->property("highlightMoveDuration").toInt(), -1);
@@ -8937,15 +8912,15 @@ void tst_QQuickListView::programmaticFlickAtBounds3()
void tst_QQuickListView::layoutChange()
{
- RandomSortModel *model = new RandomSortModel;
- QSortFilterProxyModel *sortModel = new QSortFilterProxyModel;
- sortModel->setSourceModel(model);
+ QScopedPointer<RandomSortModel> model(new RandomSortModel);
+ QScopedPointer<QSortFilterProxyModel> sortModel(new QSortFilterProxyModel);
+ sortModel->setSourceModel(model.data());
sortModel->setSortRole(Qt::UserRole);
sortModel->setDynamicSortFilter(true);
sortModel->sort(0);
QScopedPointer<QQuickView> window(createView());
- window->rootContext()->setContextProperty("testModel", QVariant::fromValue(sortModel));
+ window->rootContext()->setContextProperty("testModel", QVariant::fromValue(sortModel.data()));
window->setSource(testFileUrl("layoutChangeSort.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
@@ -9093,7 +9068,8 @@ void tst_QQuickListView::objectModel()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("objectmodel.qml"));
- QQuickListView *listview = qobject_cast<QQuickListView *>(component.create());
+ QScopedPointer<QObject> obj(component.create());
+ QQuickListView *listview = qobject_cast<QQuickListView *>(obj.data());
QVERIFY(listview);
QQmlObjectModel *model = listview->model().value<QQmlObjectModel *>();
@@ -9133,8 +9109,6 @@ void tst_QQuickListView::objectModel()
model->clear();
QCOMPARE(model->count(), 0);
QCOMPARE(listview->count(), 0);
-
- delete listview;
}
void tst_QQuickListView::contentHeightWithDelayRemove_data()
@@ -9552,13 +9526,13 @@ void tst_QQuickListView::releaseItems()
void tst_QQuickListView::QTBUG_34576_velocityZero()
{
- QQuickView *window = new QQuickView(nullptr);
+ QScopedPointer<QQuickView> window(new QQuickView(nullptr));
window->setGeometry(0,0,240,320);
QString filename(testFile("qtbug34576.qml"));
window->setSource(QUrl::fromLocalFile(filename));
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
QVERIFY(listview);
@@ -9581,8 +9555,8 @@ void tst_QQuickListView::QTBUG_34576_velocityZero()
QSignalSpy currentIndexChangedSpy(listview, SIGNAL(currentIndexChanged()));
// click button which increases currentIndex
- QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(295,215));
- QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(295,215));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(295,215));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(295,215));
// verify that currentIndexChanged is triggered
QTRY_VERIFY(currentIndexChangedSpy.count() > 0);
@@ -9593,8 +9567,6 @@ void tst_QQuickListView::QTBUG_34576_velocityZero()
// velocity should be always > 0.0
QTRY_COMPARE(window->rootObject()->property("horizontalVelocityZeroCount").toInt(), 0);
-
- delete window;
}
void tst_QQuickListView::QTBUG_61537_modelChangesAsync()
@@ -9726,6 +9698,247 @@ void tst_QQuickListView::resizeAfterComponentComplete() // QTBUG-76487
QTRY_COMPARE(lastItem->property("y").toInt(), 9 * lastItem->property("height").toInt());
}
+class Animal
+{
+public:
+ Animal(const int cost, const QString &name) {m_name = name; m_cost = cost;}
+
+ int cost() const {return m_cost;}
+ QString name() const {return m_name;}
+
+ QString m_name;
+ int m_cost;
+};
+
+class FruitModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ enum AnimalRoles {
+ NameRole = Qt::UserRole + 1,
+ CostRole
+ };
+
+ FruitModel(QObject* = nullptr) {
+ m_animals.push_back(Animal {4, QLatin1String("Melon")});
+ m_animals.push_back(Animal {5, QLatin1String("Cherry")});
+ }
+
+ int rowCount(const QModelIndex & = QModelIndex()) const override {return m_animals.count();}
+
+ QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override {
+ if (!checkIndex(index))
+ return {};
+ const Animal &animal = m_animals[index.row()];
+ if (role == CostRole)
+ return animal.cost();
+ else if (role == NameRole)
+ return animal.name();
+ return QVariant();
+ }
+
+protected:
+ QHash<int, QByteArray> roleNames() const override {
+ QHash<int, QByteArray> roles;
+ roles[CostRole] = "cost";
+ roles[NameRole] = "name";
+ return roles;
+ }
+private:
+ QList<Animal> m_animals;
+};
+
+void tst_QQuickListView::delegateWithRequiredProperties()
+{
+ FruitModel myModel;
+ qmlRegisterSingletonInstance("Qt.fruit", 1, 0, "FruitModelCpp", &myModel);
+ {
+ // ListModel
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Apple2");
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Orange3");
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Banana1");
+ QScopedPointer<QQuickView> window(createView());
+ window->setInitialProperties({{QLatin1String("useCpp"), false}});
+ window->setSource(testFileUrl("delegatesWithRequiredProperties.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QObject *listView = window->rootObject();
+ QVERIFY(listView);
+ }
+ {
+ // C++ model
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Melon4");
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Cherry5");
+ QScopedPointer<QQuickView> window(createView());
+ window->setInitialProperties({{QLatin1String("useCpp"), true}});
+ window->setSource(testFileUrl("delegatesWithRequiredProperties.qml"));
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QObject *listView = window->rootObject();
+ QVERIFY(listView);
+ }
+}
+
+void tst_QQuickListView::reuse_reuseIsOffByDefault()
+{
+ // Check that delegate recycling is off by default. The reason is that
+ // ListView needs to be backwards compatible with legacy applications. And
+ // when using delegate recycling, there are certain differences, like that
+ // a delegates Component.onCompleted will just be called the first time the
+ // item is created, and not when it's reused.
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("listviewtest.qml"));
+ window->resize(640, 480);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listView = findItem<QQuickListView>(window->rootObject(), "list");
+ QVERIFY(listView != nullptr);
+ QVERIFY(!listView->reuseItems());
+}
+
+void tst_QQuickListView::reuse_checkThatItemsAreReused()
+{
+ // Flick up and down one page of items. Check that this results in the
+ // delegate items being reused once.
+ // Note that this is slightly different from tableview, which will reuse the items
+ // twice during a similar down-then-up flick. The reason is that listview fills up
+ // free space in the view with items _before_ it release old items that have been
+ // flicked out. But changing this will break other auto tests (and perhaps legacy
+ // apps), so we have chosen to stick with this behavior for now.
+ QScopedPointer<QQuickView> window(createView());
+
+ ReuseModel model(100);
+ QQmlContext *ctxt = window->rootContext();
+ ctxt->setContextProperty("reuseModel", &model);
+
+ window->setSource(testFileUrl("reusedelegateitems.qml"));
+ window->resize(640, 480);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(window->rootObject() != nullptr);
+
+ QQuickListView *listView = findItem<QQuickListView>(window->rootObject(), "list");
+ QTRY_VERIFY(listView != nullptr);
+ const auto itemView_d = QQuickItemViewPrivate::get(listView);
+
+ QVERIFY(listView->reuseItems());
+
+ auto items = findItems<QQuickItem>(listView, "delegate");
+ const int initialItemCount = items.count();
+ QVERIFY(initialItemCount > 0);
+
+ // Sanity check that the size of the initial list of items match the count we tracked from QML
+ QCOMPARE(listView->property("delegatesCreatedCount").toInt(), initialItemCount);
+
+ // Go through all the initial items and check that they have not been reused yet
+ for (const auto item : qAsConst(items))
+ QCOMPARE(item->property("reusedCount").toInt(), 0);
+
+ // Flick one page down and count how many items we have created thus
+ // far. We expect this number to be twice as high as the initial count
+ // since we flicked one whole page.
+ const qreal delegateHeight = items.at(0)->height();
+ const qreal flickDistance = (initialItemCount * delegateHeight) + 1;
+ listView->setContentY(flickDistance);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listView));
+ const int countAfterDownFlick = listView->property("delegatesCreatedCount").toInt();
+ QCOMPARE(countAfterDownFlick, initialItemCount * 2);
+
+ // Check that the reuse pool is now populated. We expect all initial items to be pooled,
+ // except model index 0, which was never reused or released, since it's ListView.currentItem.
+ const int poolSizeAfterDownFlick = itemView_d->model->poolSize();
+ QCOMPARE(poolSizeAfterDownFlick, initialItemCount - 1);
+
+ // Go through all items and check that all model data inside the delegate
+ // have values updated according to their model index. Since model roles
+ // like 'display' are injected into the context in a special way by the
+ // QML model classes, we need to catch it through a binding instead (which is
+ // OK, since then we can also check that bindings are updated when reused).
+ items = findItems<QQuickItem>(listView, "delegate");
+ for (const auto item : qAsConst(items)) {
+ const QString display = item->property("displayBinding").toString();
+ const int modelIndex = item->property("modelIndex").toInt();
+ QVERIFY(modelIndex >= initialItemCount);
+ QCOMPARE(display, model.displayStringForRow(modelIndex));
+ }
+
+ // Flick one page up. This time there shouldn't be any new items created, so
+ // delegatesCreatedCount should remain unchanged. But while we reuse all the items
+ // in the pool during the flick, we also fill it up again with all the items that
+ // were inside the page that was flicked out.
+ listView->setContentY(0);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listView));
+ const int countAfterUpFlick = listView->property("delegatesCreatedCount").toInt();
+ const int poolSizeAfterUpFlick = itemView_d->model->poolSize();
+ QCOMPARE(countAfterUpFlick, countAfterDownFlick);
+ QCOMPARE(poolSizeAfterUpFlick, initialItemCount);
+
+ // Go through all items and check that they have been reused exactly once
+ // (except for ListView.currentItem, which was never released).
+ const auto listViewCurrentItem = listView->currentItem();
+ items = findItems<QQuickItem>(listView, "delegate");
+ for (const auto item : qAsConst(items)) {
+ const int reusedCount = item->property("reusedCount").toInt();
+ if (item == listViewCurrentItem)
+ QCOMPARE(reusedCount, 0);
+ else
+ QCOMPARE(reusedCount, 1);
+ }
+
+ // Go through all items again and check that all model data inside the delegate
+ // have correct values now that they have been reused.
+ items = findItems<QQuickItem>(listView, "delegate");
+ for (const auto item : qAsConst(items)) {
+ const QString display = item->property("displayBinding").toString();
+ const int modelIndex = item->property("modelIndex").toInt();
+ QVERIFY(modelIndex < initialItemCount);
+ QCOMPARE(display, model.displayStringForRow(modelIndex));
+ }
+}
+
+void tst_QQuickListView::dragOverFloatingHeaderOrFooter() // QTBUG-74046
+{
+ QQuickView *window = getView();
+ QQuickViewTestUtil::moveMouseAway(window);
+ window->setSource(testFileUrl("qtbug63974.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = qmlobject_cast<QQuickListView *>(window->rootObject());
+ QVERIFY(listview);
+ QCOMPARE(listview->contentY(), -20);
+
+ // Drag downwards from the header: the list shouldn't move
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
+ for (int i = 0; i < 10; ++i)
+ QTest::mouseMove(window, QPoint(10, 10 + i * 10));
+ QCOMPARE(listview->isMoving(), false);
+ QCOMPARE(listview->contentY(), -20);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier);
+
+ // Drag upwards from the footer: the list shouldn't move
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(10,190));
+ for (int i = 0; i < 10; ++i)
+ QTest::mouseMove(window, QPoint(10, 190 - i * 10));
+ QCOMPARE(listview->isMoving(), false);
+ QCOMPARE(listview->contentY(), -20);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier);
+
+ // Drag upwards from the middle: the list should move
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(10,100));
+ for (int i = 0; i < 10 && listview->contentY() == -20; ++i)
+ QTest::mouseMove(window, QPoint(10, 100 - i * 10));
+ QVERIFY(listview->isMoving());
+ QVERIFY(listview->contentY() > -20);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier);
+
+ releaseView(window);
+}
+
void tst_QQuickListView::moveObjectModelItemToAnotherObjectModel()
{
QScopedPointer<QQuickView> window(createView());
@@ -9775,6 +9988,60 @@ void tst_QQuickListView::changeModelAndDestroyTheOldOne() // QTBUG-80203
// no crash
}
+class DataObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString name READ name CONSTANT)
+ Q_PROPERTY(QString color READ color CONSTANT)
+
+public:
+ DataObject(QObject *parent = nullptr) : QObject(parent) {}
+ DataObject(const QString &name, const QString &color, QObject *parent = nullptr)
+ : QObject(parent), m_name(name), m_color(color) {}
+
+ QString name() const { return m_name; }
+ QString color() const { return m_color; }
+
+private:
+ QString m_name;
+ QString m_color;
+};
+
+void tst_QQuickListView::requiredObjectListModel()
+{
+ QList<QObject *> dataList = {
+ new DataObject("Item 1", "red", this),
+ new DataObject("Item 2", "green", this),
+ new DataObject("Item 3", "blue", this),
+ new DataObject("Item 4", "yellow", this)
+ };
+
+ const auto deleter = qScopeGuard([&](){ qDeleteAll(dataList); });
+ Q_UNUSED(deleter);
+
+ QQuickView view;
+ view.setInitialProperties({{ "model", QVariant::fromValue(dataList) }});
+ view.setSource(testFileUrl("requiredObjectListModel.qml"));
+ view.show();
+
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ const auto *root = qobject_cast<QQuickListView *>(view.rootObject());
+ QVERIFY(root);
+
+ QCOMPARE(root->count(), dataList.count());
+
+ for (int i = 0, end = dataList.count(); i != end; ++i) {
+ const auto *rect = qobject_cast<QQuickRectangle *>(root->itemAtIndex(i));
+ QVERIFY(rect);
+ const auto *data = qobject_cast<DataObject *>(dataList.at(i));
+ QVERIFY(data);
+
+ QCOMPARE(rect->color(), QColor(data->color()));
+ QCOMPARE(rect->property("name").toString(), data->name());
+ }
+}
+
QTEST_MAIN(tst_QQuickListView)
#include "tst_qquicklistview.moc"
diff --git a/tests/auto/quick/qquickloader/data/RequiredPropertyValuesComponent.qml b/tests/auto/quick/qquickloader/data/RequiredPropertyValuesComponent.qml
new file mode 100644
index 0000000000..7bb21e8b93
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/RequiredPropertyValuesComponent.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+Item {
+ id: behaviorCounter
+ required property int i
+ required property string s
+
+}
diff --git a/tests/auto/quick/qquickloader/data/initialPropertyValues.10.qml b/tests/auto/quick/qquickloader/data/initialPropertyValues.10.qml
new file mode 100644
index 0000000000..4728346ca1
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/initialPropertyValues.10.qml
@@ -0,0 +1,20 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+ property int i: 0
+ property string s: ""
+
+ Loader {
+ id: loader
+ objectName: "loader"
+ onLoaded: {
+ root.i = loader.item.i; // should be 42
+ root.s = loader.item.s; // should be 11
+ }
+ }
+
+ Component.onCompleted: {
+ loader.setSource("RequiredPropertyValuesComponent.qml", {"i": 42});
+ }
+}
diff --git a/tests/auto/quick/qquickloader/data/initialPropertyValues.9.qml b/tests/auto/quick/qquickloader/data/initialPropertyValues.9.qml
new file mode 100644
index 0000000000..5d6e3171a0
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/initialPropertyValues.9.qml
@@ -0,0 +1,20 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+ property int i: 0
+ property string s: ""
+
+ Loader {
+ id: loader
+ objectName: "loader"
+ onLoaded: {
+ root.i = loader.item.i; // should be 42
+ root.s = loader.item.s; // should be 11
+ }
+ }
+
+ Component.onCompleted: {
+ loader.setSource("RequiredPropertyValuesComponent.qml", {"i": 42, "s": "hello world"});
+ }
+}
diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index 7bd6f9466a..91d0bcab2e 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -684,6 +684,16 @@ void tst_QQuickLoader::initialPropertyValues_data()
<< (QStringList() << "initialValue")
<< (QVariantList() << 6);
+ QTest::newRow("ensure required properties are set correctly") << testFileUrl("initialPropertyValues.9.qml")
+ << QStringList()
+ << (QStringList() << "i" << "s")
+ << (QVariantList() << 42 << QLatin1String("hello world"));
+
+ QTest::newRow("required properties only partially set =") << testFileUrl("initialPropertyValues.10.qml")
+ << (QStringList() << QString(testFileUrl("RequiredPropertyValuesComponent.qml").toString() + QLatin1String(":6:5: Required property s was not initialized")))
+ << (QStringList() << "i" << "s")
+ << (QVariantList() << 0 << QLatin1String(""));
+
QTest::newRow("source url changed, previously initial properties are discared") << testFileUrl("initialPropertyValues.11.qml")
<< QStringList()
<< (QStringList() << "oldi" << "i")
diff --git a/tests/auto/quick/qquickmousearea/data/dragreset.qml b/tests/auto/quick/qquickmousearea/data/dragreset.qml
index 10039f1fcb..bbe0160080 100644
--- a/tests/auto/quick/qquickmousearea/data/dragreset.qml
+++ b/tests/auto/quick/qquickmousearea/data/dragreset.qml
@@ -1,6 +1,7 @@
import QtQuick 2.0
Rectangle {
id: whiteRect
+ required property bool haveTarget
width: 200
height: 200
color: "white"
diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
index 1a9182de57..5879fc6897 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -308,7 +308,7 @@ void tst_QQuickMouseArea::resetDrag()
{
QQuickView window;
QByteArray errorMessage;
- window.rootContext()->setContextProperty("haveTarget", QVariant(true));
+ window.setInitialProperties({{"haveTarget", true}});
QVERIFY2(QQuickTest::initView(window, testFileUrl("dragreset.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
@@ -327,7 +327,9 @@ void tst_QQuickMouseArea::resetDrag()
QVERIFY(rootItem != nullptr);
QSignalSpy targetSpy(drag, SIGNAL(targetChanged()));
QVERIFY(drag->target() != nullptr);
- window.rootContext()->setContextProperty("haveTarget", QVariant(false));
+ auto root = window.rootObject();
+ QQmlProperty haveTarget {root, "haveTarget"};
+ haveTarget.write(false);
QCOMPARE(targetSpy.count(),1);
QVERIFY(!drag->target());
}
@@ -716,7 +718,7 @@ void tst_QQuickMouseArea::updateMouseAreaPosOnClick()
QCOMPARE(mouseRegion->mouseX(), rect->x());
QCOMPARE(mouseRegion->mouseY(), rect->y());
- QMouseEvent event(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent event(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &event);
QCOMPARE(mouseRegion->mouseX(), 100.0);
@@ -744,7 +746,7 @@ void tst_QQuickMouseArea::updateMouseAreaPosOnResize()
QCOMPARE(mouseRegion->mouseX(), 0.0);
QCOMPARE(mouseRegion->mouseY(), 0.0);
- QMouseEvent event(QEvent::MouseButtonPress, rect->position().toPoint(), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent event(QEvent::MouseButtonPress, rect->position().toPoint(), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &event);
QVERIFY(!mouseRegion->property("emitPositionChanged").toBool());
@@ -773,7 +775,7 @@ void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
QQuickMouseArea *mouseArea = qobject_cast<QQuickMouseArea*>(window.rootObject()->children().first());
QVERIFY(mouseArea);
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &pressEvent);
QCOMPARE(mouseArea->pressedButtons(), Qt::LeftButton);
@@ -787,7 +789,7 @@ void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
QVERIFY(!window.rootObject()->property("clicked").toBool());
QVERIFY(window.rootObject()->property("held").toBool());
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QTRY_VERIFY(window.rootObject()->property("held").toBool());
@@ -803,14 +805,14 @@ void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
QVERIFY(QTest::qWaitForWindowExposed(&window));
QVERIFY(window.rootObject() != nullptr);
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &pressEvent);
QVERIFY(!window.rootObject()->property("clicked").toBool());
QTest::qWait(1000);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QVERIFY(window.rootObject()->property("clicked").toBool());
@@ -834,7 +836,7 @@ void tst_QQuickMouseArea::onMousePressRejected()
QVERIFY(!window.rootObject()->property("mr2_released").toBool());
QVERIFY(!window.rootObject()->property("mr2_canceled").toBool());
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &pressEvent);
QVERIFY(window.rootObject()->property("mr1_pressed").toBool());
@@ -846,7 +848,7 @@ void tst_QQuickMouseArea::onMousePressRejected()
QTest::qWait(200);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QVERIFY(window.rootObject()->property("mr1_released").toBool());
@@ -881,8 +883,8 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
QCOMPARE(window.rootObject()->property("clicked").toInt(), expectedClicks);
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &pressEvent);
@@ -899,7 +901,7 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
QCOMPARE(window.rootObject()->property("clicked").toInt(), ++expectedClicks);
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent pressEvent2(QEvent::MouseButtonDblClick, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent pressEvent2(QEvent::MouseButtonDblClick, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &pressEvent2);
QTRY_VERIFY(window.rootObject()->property("pressed").toBool());
@@ -952,16 +954,16 @@ void tst_QQuickMouseArea::doubleClick()
// The sequence for a double click is:
// press, release, (click), press, double click, release
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("released").toInt(), 1);
QGuiApplication::sendEvent(&window, &pressEvent);
- pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, nullptr);
+ pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
QGuiApplication::sendEvent(&window, &releaseEvent);
@@ -987,10 +989,10 @@ void tst_QQuickMouseArea::clickTwice()
QVERIFY(mouseArea);
mouseArea->setAcceptedButtons(acceptedButtons);
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("pressed").toInt(), 1);
@@ -998,7 +1000,7 @@ void tst_QQuickMouseArea::clickTwice()
QCOMPARE(window.rootObject()->property("clicked").toInt(), 1);
QGuiApplication::sendEvent(&window, &pressEvent);
- pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, nullptr);
+ pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
QGuiApplication::sendEvent(&window, &releaseEvent);
@@ -1025,16 +1027,16 @@ void tst_QQuickMouseArea::invalidClick()
// The sequence for a double click is:
// press, release, (click), press, double click, release
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("released").toInt(), 0);
QGuiApplication::sendEvent(&window, &pressEvent);
- pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, nullptr);
+ pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
QGuiApplication::sendEvent(&window, &releaseEvent);
@@ -1054,12 +1056,12 @@ void tst_QQuickMouseArea::pressedOrdering()
QCOMPARE(window.rootObject()->property("value").toString(), QLatin1String("base"));
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &pressEvent);
QCOMPARE(window.rootObject()->property("value").toString(), QLatin1String("pressed"));
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("value").toString(), QLatin1String("toggled"));
@@ -1318,13 +1320,13 @@ void tst_QQuickMouseArea::hoverPropagation()
QCOMPARE(root->property("point1").toBool(), false);
QCOMPARE(root->property("point2").toBool(), false);
- QMouseEvent moveEvent(QEvent::MouseMove, QPoint(32, 32), Qt::NoButton, Qt::NoButton, nullptr);
+ QMouseEvent moveEvent(QEvent::MouseMove, QPoint(32, 32), Qt::NoButton, Qt::NoButton, {});
QGuiApplication::sendEvent(&window, &moveEvent);
QCOMPARE(root->property("point1").toBool(), true);
QCOMPARE(root->property("point2").toBool(), false);
- QMouseEvent moveEvent2(QEvent::MouseMove, QPoint(232, 32), Qt::NoButton, Qt::NoButton, nullptr);
+ QMouseEvent moveEvent2(QEvent::MouseMove, QPoint(232, 32), Qt::NoButton, Qt::NoButton, {});
QGuiApplication::sendEvent(&window, &moveEvent2);
QCOMPARE(root->property("point1").toBool(), false);
QCOMPARE(root->property("point2").toBool(), true);
@@ -1334,7 +1336,7 @@ void tst_QQuickMouseArea::hoverVisible()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QQuickView window;
QByteArray errorMessage;
diff --git a/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.2.qml b/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.2.qml
new file mode 100644
index 0000000000..ae8ca784bc
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.2.qml
@@ -0,0 +1,59 @@
+import QtQuick 2.14
+
+Item {
+ id: root
+ width: 800
+ height: 600
+ property bool working: false
+
+ ListModel {
+ id: myModel
+ ListElement {
+ name: "Bill Jones"
+ place: "Berlin"
+ }
+ ListElement {
+ name: "Jane Doe"
+ place: "Oslo"
+ }
+ ListElement {
+ name: "John Smith"
+ place: "Oulo"
+ }
+ }
+
+ Component {
+ id: delegateComponent
+ Rectangle {
+ id: myDelegate
+ height: 50
+ width: 50
+ required property string name
+ required property int index
+ onNameChanged: () => {if (myDelegate.name === "You-know-who") root.working = true}
+ Text {
+ text: myDelegate.name
+ font.pointSize: 10
+ anchors.fill: myDelegate
+ }
+ }
+ }
+
+ PathView {
+ anchors.fill: parent
+ model: myModel
+ delegate: delegateComponent
+ path: Path {
+ startX: 80; startY: 100
+ PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
+ PathQuad { x: 140; y: 100; controlX: -20; controlY: 75 }
+ }
+ }
+ Timer {
+ interval: 1
+ running: true
+ repeat: false
+ onTriggered: () => { myModel.setProperty(1, "name", "You-know-who"); }
+ }
+
+}
diff --git a/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.3.qml b/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.3.qml
new file mode 100644
index 0000000000..2996ba18fd
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.3.qml
@@ -0,0 +1,64 @@
+import QtQuick 2.14
+
+Item {
+ id: root
+ width: 800
+ height: 600
+ property bool working: false
+
+ ListModel {
+ id: myModel
+ ListElement {
+ name: "Bill Jones"
+ place: "Berlin"
+ }
+ ListElement {
+ name: "Jane Doe"
+ place: "Oslo"
+ }
+ ListElement {
+ name: "John Smith"
+ place: "Oulo"
+ }
+ }
+
+ Component {
+ id: delegateComponent
+ Rectangle {
+ id: myDelegate
+ height: 50
+ width: 50
+ required property string name
+ required property int index
+ onNameChanged: () => {if (myDelegate.name === "You-know-who") root.working = false}
+ Text {
+ text: myDelegate.name
+ font.pointSize: 10
+ anchors.fill: myDelegate
+ }
+ Component.onCompleted: () => {myDelegate.name = "break binding"}
+ }
+ }
+
+ PathView {
+ anchors.fill: parent
+ model: myModel
+ delegate: delegateComponent
+ path: Path {
+ startX: 80; startY: 100
+ PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
+ PathQuad { x: 140; y: 100; controlX: -20; controlY: 75 }
+ }
+ }
+ Timer {
+ interval: 1
+ running: true
+ repeat: false
+ onTriggered: () => {
+ myModel.setProperty(1, "name", "You-know-who")
+ myModel.setProperty(2, "name", "You-know-who")
+ root.working = true
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.qml b/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.qml
new file mode 100644
index 0000000000..5d721fd0c4
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.qml
@@ -0,0 +1,53 @@
+import QtQuick 2.14
+
+Item {
+ width: 400
+ height: 200
+
+ ListModel {
+ id: myModel
+ ListElement {
+ name: "Bill Jones"
+ place: "Berlin"
+ }
+ ListElement {
+ name: "Jane Doe"
+ place: "Oslo"
+ }
+ ListElement {
+ name: "John Smith"
+ place: "Oulo"
+ }
+ }
+
+ Component {
+ id: delegateComponent
+ Rectangle {
+ id: myDelegate
+ required property int index
+ required property string name
+ required property string place
+ height: 100
+ width: 100
+ Text {
+ text: myDelegate.name + " lives in " + myDelegate.place + myDelegate.index
+ font.pointSize: 16
+ anchors.fill: myDelegate
+
+ Component.onCompleted: () => {console.info(myDelegate.name+myDelegate.place+myDelegate.index)}
+ }
+ }
+ }
+
+ PathView {
+ anchors.fill: parent
+ model: myModel
+ delegate: delegateComponent
+ path: Path {
+ startX: 120; startY: 100
+ PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
+ PathQuad { x: 120; y: 100; controlX: -20; controlY: 75 }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquickpathview/data/delegatewithUnrelatedRequiredPreventsAccessToModel.qml b/tests/auto/quick/qquickpathview/data/delegatewithUnrelatedRequiredPreventsAccessToModel.qml
new file mode 100644
index 0000000000..bf130a2d73
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/delegatewithUnrelatedRequiredPreventsAccessToModel.qml
@@ -0,0 +1,52 @@
+import QtQuick 2.14
+
+Item {
+ width: 400
+ height: 200
+
+ ListModel {
+ id: myModel
+ ListElement {
+ name: "Bill Jones"
+ place: "Berlin"
+ }
+ ListElement {
+ name: "Jane Doe"
+ place: "Oslo"
+ }
+ ListElement {
+ name: "John Smith"
+ place: "Oulo"
+ }
+ }
+
+ Component {
+ id: delegateComponent
+ Rectangle {
+ id: myDelegate
+ required property int set
+ set: 42
+ height: 100
+ width: 100
+ Text {
+ text: "Test"
+ font.pointSize: 16
+ anchors.fill: myDelegate
+
+ Component.onCompleted: () => { try {index; console.log(index); console.log(name)} catch(ex) {console.info(ex.name)} }
+ }
+ }
+ }
+
+ PathView {
+ anchors.fill: parent
+ model: myModel
+ delegate: delegateComponent
+ path: Path {
+ startX: 120; startY: 100
+ PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
+ PathQuad { x: 120; y: 100; controlX: -20; controlY: 75 }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
index f3119dd0f3..8ba09fa509 100644
--- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
+++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
@@ -151,6 +151,8 @@ private slots:
void movementDirection();
void removePath();
void objectModelMove();
+ void requiredPropertiesInDelegate();
+ void requiredPropertiesInDelegatePreventUnrelated();
};
class TestObject : public QObject
@@ -2759,6 +2761,41 @@ void tst_QQuickPathView::objectModelMove()
}
}
+void tst_QQuickPathView::requiredPropertiesInDelegate()
+{
+ {
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "Bill JonesBerlin0");
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "Jane DoeOslo1");
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "John SmithOulo2");
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("delegateWithRequiredProperties.qml"));
+ window->show();
+ }
+ {
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("delegateWithRequiredProperties.2.qml"));
+ window->show();
+ QTRY_VERIFY(window->rootObject()->property("working").toBool());
+ }
+ {
+ QScopedPointer<QQuickView> window(createView());
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression("Writing to \"name\" broke the binding to the underlying model"));
+ window->setSource(testFileUrl("delegateWithRequiredProperties.3.qml"));
+ window->show();
+ QTRY_VERIFY(window->rootObject()->property("working").toBool());
+ }
+}
+
+void tst_QQuickPathView::requiredPropertiesInDelegatePreventUnrelated()
+{
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "ReferenceError");
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "ReferenceError");
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "ReferenceError");
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("delegatewithUnrelatedRequiredPreventsAccessToModel.qml"));
+ window->show();
+}
+
QTEST_MAIN(tst_QQuickPathView)
#include "tst_qquickpathview.moc"
diff --git a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
index 1e2e0a6078..88cf6ece96 100644
--- a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
+++ b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
@@ -433,7 +433,7 @@ void tst_qquickpixmapcache::uncached()
QUrl url("image://mypixmaps/mypix");
{
QQuickPixmap p;
- p.load(&engine, url, nullptr);
+ p.load(&engine, url, QQuickPixmap::Options{});
QImage img = p.image();
QCOMPARE(img.pixel(0,0), qRgb(255, 0, 0));
}
@@ -442,7 +442,7 @@ void tst_qquickpixmapcache::uncached()
MyPixmapProvider::fillColor = qRgb(0, 255, 0);
{
QQuickPixmap p;
- p.load(&engine, url, nullptr);
+ p.load(&engine, url, QQuickPixmap::Options{});
QImage img = p.image();
QCOMPARE(img.pixel(0,0), qRgb(0, 255, 0));
}
@@ -460,7 +460,7 @@ void tst_qquickpixmapcache::uncached()
MyPixmapProvider::fillColor = qRgb(255, 0, 255);
{
QQuickPixmap p;
- p.load(&engine, url, nullptr);
+ p.load(&engine, url, QQuickPixmap::Options{});
QImage img = p.image();
QCOMPARE(img.pixel(0,0), qRgb(255, 0, 255));
}
diff --git a/tests/auto/quick/qquickpositioners/data/transitions-padding.qml b/tests/auto/quick/qquickpositioners/data/transitions-padding.qml
index e3175c480c..eda9ce628e 100644
--- a/tests/auto/quick/qquickpositioners/data/transitions-padding.qml
+++ b/tests/auto/quick/qquickpositioners/data/transitions-padding.qml
@@ -5,6 +5,16 @@ Rectangle {
width: 500
height: 500
+ required property bool usePopulateTransition
+ required property bool enableAddTransition
+ required property bool dynamicallyPopulate
+ required property var testModel
+ required property var model_targetItems_transitionFrom
+ required property var model_displacedItems_transitionVia
+ required property point targetItems_transitionFrom
+ required property point displacedItems_transitionVia
+ required property string testedPositioner
+
property int duration: 50
property real incrementalSize: 5
diff --git a/tests/auto/quick/qquickpositioners/data/transitions.qml b/tests/auto/quick/qquickpositioners/data/transitions.qml
index a1f27bb06e..988a01e373 100644
--- a/tests/auto/quick/qquickpositioners/data/transitions.qml
+++ b/tests/auto/quick/qquickpositioners/data/transitions.qml
@@ -5,6 +5,16 @@ Rectangle {
width: 500
height: 500
+ required property bool usePopulateTransition
+ required property bool enableAddTransition
+ required property bool dynamicallyPopulate
+ required property var testModel
+ required property var model_targetItems_transitionFrom
+ required property var model_displacedItems_transitionVia
+ required property point targetItems_transitionFrom
+ required property point displacedItems_transitionVia
+ required property string testedPositioner
+
property int duration: 50
property real incrementalSize: 5
diff --git a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
index d3c0f345b9..e6bbd8c215 100644
--- a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
+++ b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
@@ -1025,16 +1025,17 @@ void tst_qquickpositioners::populateTransitions(const QString &positionerObjectN
QScopedPointer<QQuickView> window(QQuickViewTestUtil::createView());
- QQmlContext *ctxt = window->rootContext();
- ctxt->setContextProperty("usePopulateTransition", usePopulateTransition);
- ctxt->setContextProperty("enableAddTransition", true);
- ctxt->setContextProperty("dynamicallyPopulate", dynamicallyPopulate);
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
- ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
- ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
- ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
- ctxt->setContextProperty("testedPositioner", positionerObjectName);
+ window->setInitialProperties({
+ {"usePopulateTransition", usePopulateTransition},
+ {"enableAddTransition", true},
+ {"dynamicallyPopulate", dynamicallyPopulate},
+ {"testModel", QVariant::fromValue(&model)},
+ {"model_targetItems_transitionFrom", QVariant::fromValue(&model_targetItems_transitionFrom)},
+ {"model_displacedItems_transitionVia", QVariant::fromValue(&model_displacedItems_transitionVia)},
+ {"targetItems_transitionFrom", targetItems_transitionFrom},
+ {"displacedItems_transitionVia", displacedItems_transitionVia},
+ {"testedPositioner", positionerObjectName}
+ });
window->setSource(testFileUrl(qmlFile));
QQuickItem *positioner = window->rootObject()->findChild<QQuickItem*>(positionerObjectName);
@@ -1111,16 +1112,17 @@ void tst_qquickpositioners::addTransitions(const QString &positionerObjectName)
QaimModel model_displacedItems_transitionVia;
QScopedPointer<QQuickView> window(QQuickViewTestUtil::createView());
- QQmlContext *ctxt = window->rootContext();
- ctxt->setContextProperty("usePopulateTransition", QVariant(false));
- ctxt->setContextProperty("enableAddTransition", QVariant(true));
- ctxt->setContextProperty("dynamicallyPopulate", QVariant(false));
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
- ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
- ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
- ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
- ctxt->setContextProperty("testedPositioner", QString());
+ window->setInitialProperties({
+ {"usePopulateTransition", QVariant(false)},
+ {"enableAddTransition", QVariant(true)},
+ {"dynamicallyPopulate", QVariant(false)},
+ {"testModel", QVariant::fromValue(&model)},
+ {"model_targetItems_transitionFrom", QVariant::fromValue(&model_targetItems_transitionFrom)},
+ {"model_displacedItems_transitionVia", QVariant::fromValue(&model_displacedItems_transitionVia)},
+ {"targetItems_transitionFrom", targetItems_transitionFrom},
+ {"displacedItems_transitionVia", displacedItems_transitionVia},
+ {"testedPositioner", QString()}
+ });
window->setSource(testFileUrl(qmlFile));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
@@ -1234,16 +1236,17 @@ void tst_qquickpositioners::moveTransitions(const QString &positionerObjectName)
QaimModel model_displacedItems_transitionVia;
QScopedPointer<QQuickView> window(QQuickViewTestUtil::createView());
- QQmlContext *ctxt = window->rootContext();
- ctxt->setContextProperty("usePopulateTransition", QVariant(false));
- ctxt->setContextProperty("enableAddTransition", QVariant(false));
- ctxt->setContextProperty("dynamicallyPopulate", QVariant(false));
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
- ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
- ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
- ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
- ctxt->setContextProperty("testedPositioner", QString());
+ window->setInitialProperties({
+ {"usePopulateTransition", QVariant(false)},
+ {"enableAddTransition", QVariant(false)},
+ {"dynamicallyPopulate", QVariant(false)},
+ {"testModel", QVariant::fromValue(&model)},
+ {"model_targetItems_transitionFrom", QVariant::fromValue(&model_targetItems_transitionFrom)},
+ {"model_displacedItems_transitionVia", QVariant::fromValue(&model_displacedItems_transitionVia)},
+ {"targetItems_transitionFrom", targetItems_transitionFrom},
+ {"displacedItems_transitionVia", displacedItems_transitionVia},
+ {"testedPositioner", QString()}
+ });
window->setSource(testFileUrl(qmlFile));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
diff --git a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
index e4d790f466..536280337a 100644
--- a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
+++ b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
@@ -73,7 +73,7 @@ void tst_qquickrectangle::color()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimal platforms", Abort);
QImage image = view.grabWindow();
QVERIFY(image.pixel(0,0) == QColor("#020202").rgba());
diff --git a/tests/auto/quick/qquickrendercontrol/data/rect.qml b/tests/auto/quick/qquickrendercontrol/data/rect.qml
new file mode 100644
index 0000000000..5f58869fb5
--- /dev/null
+++ b/tests/auto/quick/qquickrendercontrol/data/rect.qml
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+
+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 }
+ }
+ Text {
+ text: "Hello World\n\nrotation=" + Math.round(r.rotation)
+ anchors.centerIn: parent
+ }
+}
diff --git a/tests/auto/quick/qquickrendercontrol/qquickrendercontrol.pro b/tests/auto/quick/qquickrendercontrol/qquickrendercontrol.pro
new file mode 100644
index 0000000000..958abe316d
--- /dev/null
+++ b/tests/auto/quick/qquickrendercontrol/qquickrendercontrol.pro
@@ -0,0 +1,12 @@
+CONFIG += testcase
+TARGET = tst_qquickrendercontrol
+SOURCES += tst_qquickrendercontrol.cpp
+
+include (../../shared/util.pri)
+
+macos:CONFIG -= app_bundle
+
+QT += core-private gui-private qml-private quick-private testlib opengl
+
+OTHER_FILES += \
+ data/rect.qml
diff --git a/tests/auto/quick/qquickrendercontrol/tst_qquickrendercontrol.cpp b/tests/auto/quick/qquickrendercontrol/tst_qquickrendercontrol.cpp
new file mode 100644
index 0000000000..4bab4e345a
--- /dev/null
+++ b/tests/auto/quick/qquickrendercontrol/tst_qquickrendercontrol.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+
+#if QT_CONFIG(opengl)
+#include <QOffscreenSurface>
+#include <QOpenGLContext>
+#include <QOpenGLFunctions>
+#include <QOpenGLFramebufferObject>
+#endif
+#include <QAnimationDriver>
+
+#include <QQuickWindow>
+#include <QQuickRenderControl>
+#include <QQuickItem>
+#include <QQmlEngine>
+#include <QQmlComponent>
+
+#include "../../shared/util.h"
+
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpa/qplatformintegration.h>
+
+class tst_RenderControl : public QQmlDataTest
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void renderAndReadBack();
+};
+
+void tst_RenderControl::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+}
+
+class AnimationDriver : public QAnimationDriver
+{
+public:
+ AnimationDriver(int msPerStep) : m_step(msPerStep) { }
+
+ void advance() override
+ {
+ m_elapsed += m_step;
+ advanceAnimation();
+ }
+
+ qint64 elapsed() const override
+ {
+ return m_elapsed;
+ }
+
+private:
+ int m_step;
+ qint64 m_elapsed = 0;
+};
+
+
+void tst_RenderControl::renderAndReadBack()
+{
+ static const int ANIM_ADVANCE_PER_FRAME = 16; // milliseconds
+ QScopedPointer<AnimationDriver> animDriver(new AnimationDriver(ANIM_ADVANCE_PER_FRAME));
+ animDriver->install();
+
+ // ### Qt 6: migrate this to OpenGL-on-RHI
+#if QT_CONFIG(opengl)
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL))
+ QSKIP("Skipping due to platform not supporting OpenGL at run time");
+
+ QScopedPointer<QOpenGLContext> context(new QOpenGLContext);
+ QVERIFY(context->create());
+ QScopedPointer<QOffscreenSurface> offscreenSurface(new QOffscreenSurface);
+ offscreenSurface->setFormat(context->format());
+ offscreenSurface->create();
+ QVERIFY(context->makeCurrent(offscreenSurface.data()));
+
+ QScopedPointer<QQuickRenderControl> renderControl(new QQuickRenderControl);
+ QScopedPointer<QQuickWindow> quickWindow(new QQuickWindow(renderControl.data()));
+ QScopedPointer<QQmlEngine> qmlEngine(new QQmlEngine);
+
+ QScopedPointer<QQmlComponent> qmlComponent(new QQmlComponent(qmlEngine.data(), testFileUrl(QLatin1String("rect.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);
+ QCOMPARE(rootItem->size(), QSize(200, 200));
+
+ quickWindow->contentItem()->setSize(rootItem->size());
+ quickWindow->setGeometry(0, 0, rootItem->width(), rootItem->height());
+
+ rootItem->setParentItem(quickWindow->contentItem());
+
+ renderControl->initialize(context.data());
+
+ // cannot do this test with the 'software' backend of Qt Quick
+ QSGRendererInterface::GraphicsApi api = quickWindow->rendererInterface()->graphicsApi();
+ if (api != QSGRendererInterface::OpenGL)
+ QSKIP("Skipping due to Qt Quick not using the direct OpenGL rendering path");
+
+ QScopedPointer<QOpenGLFramebufferObject> fbo(new QOpenGLFramebufferObject(rootItem->size().toSize(),
+ QOpenGLFramebufferObject::CombinedDepthStencil));
+
+ quickWindow->setRenderTarget(fbo.data());
+
+ for (int frame = 0; frame < 100; ++frame) {
+ // have to process events, e.g. to get queued metacalls delivered
+ QCoreApplication::processEvents();
+
+ if (frame > 0) {
+ // Quick animations will now think that ANIM_ADVANCE_PER_FRAME milliseconds have passed,
+ // even though in reality we have a tight loop that generates frames unthrottled.
+ animDriver->advance();
+ }
+
+ renderControl->polishItems();
+ renderControl->sync();
+ renderControl->render();
+
+ context->functions()->glFlush();
+
+ QImage img = fbo->toImage();
+ QVERIFY(!img.isNull());
+ QCOMPARE(img.size(), rootItem->size());
+
+ const int maxFuzz = 2;
+
+ // The scene is: background, rectangle, text
+ // where rectangle rotates
+
+ QRgb background = img.pixel(5, 5);
+ 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);
+
+ // 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);
+ }
+ }
+
+#else
+ QSKIP("No OpenGL, skipping rendercontrol test");
+#endif
+}
+
+#include "tst_qquickrendercontrol.moc"
+
+QTEST_MAIN(tst_RenderControl)
diff --git a/tests/auto/quick/qquickrepeater/data/contextProperty.qml b/tests/auto/quick/qquickrepeater/data/contextProperty.qml
new file mode 100644
index 0000000000..44e76f474f
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/contextProperty.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.14
+
+Item {
+ Column {
+ Repeater {
+ model: ["apples", "oranges", "pears"]
+ Text {
+ id: txt
+ text: modelData + index
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickrepeater/data/objlist_required.qml b/tests/auto/quick/qquickrepeater/data/objlist_required.qml
new file mode 100644
index 0000000000..cc9dd9566c
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/objlist_required.qml
@@ -0,0 +1,23 @@
+import QtQuick 2.0
+
+Rectangle {
+ id: container
+ objectName: "container"
+ width: 240
+ height: 320
+ color: "white"
+ Repeater {
+ id: repeater
+ objectName: "repeater"
+ model: testData
+ property int errors: 0
+ property int instantiated: 0
+ Component {
+ Item{
+ required property int index
+ required property int idx
+ Component.onCompleted: {if (index != idx) repeater.errors += 1; repeater.instantiated++}
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickrepeater/data/package2.qml b/tests/auto/quick/qquickrepeater/data/package2.qml
new file mode 100644
index 0000000000..0ceb34b362
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/package2.qml
@@ -0,0 +1,36 @@
+import QtQuick 2.0
+import QtQml.Models 2.2
+import QtQuick.Window 2.0
+
+Item {
+ width: 300
+ height: 300
+ visible: true
+ DelegateModel {
+ id: mdl
+
+ model: 1
+ delegate: Package {
+ Item {
+ id: first
+ Package.name: "first"
+ }
+ Item{
+ id: second
+ Package.name: "second"
+ }
+ }
+ }
+
+ Repeater {
+ model: mdl.parts.first
+ }
+ Repeater {
+ model: mdl.parts.second
+ }
+
+ function setup(): bool {
+ mdl.model = 2
+ return true;
+ }
+}
diff --git a/tests/auto/quick/qquickrepeater/data/requiredProperty.qml b/tests/auto/quick/qquickrepeater/data/requiredProperty.qml
new file mode 100644
index 0000000000..80eb3c28ee
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/requiredProperty.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.14
+
+Item {
+ Column {
+ Repeater {
+ model: ["apples", "oranges", "pears"]
+ Text {
+ id: txt
+ required property string modelData
+ required property int index
+ text: modelData + index
+ Component.onCompleted: () => {console.info(txt.text)}
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
index 65e7d29595..35883339d7 100644
--- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
+++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
@@ -55,6 +55,7 @@ public:
private slots:
void numberModel();
+ void objectList_data();
void objectList();
void stringList();
void dataModel_adding();
@@ -79,6 +80,8 @@ private slots:
void QTBUG54859_asynchronousMove();
void package();
void ownership();
+ void requiredProperties();
+ void contextProperties();
};
class TestObject : public QObject
@@ -143,6 +146,14 @@ void tst_QQuickRepeater::numberModel()
delete window;
}
+void tst_QQuickRepeater::objectList_data()
+{
+ QTest::addColumn<QUrl>("filename");
+
+ QTest::newRow("normal") << testFileUrl("objlist.qml");
+ QTest::newRow("required") << testFileUrl("objlist_required.qml");
+}
+
class MyObject : public QObject
{
Q_OBJECT
@@ -157,6 +168,7 @@ public:
void tst_QQuickRepeater::objectList()
{
+ QFETCH(QUrl, filename);
QQuickView *window = createView();
QObjectList data;
for (int i=0; i<100; i++)
@@ -165,7 +177,7 @@ void tst_QQuickRepeater::objectList()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testData", QVariant::fromValue(data));
- window->setSource(testFileUrl("objlist.qml"));
+ window->setSource(filename);
qApp->processEvents();
QQuickRepeater *repeater = findItem<QQuickRepeater>(window->rootObject(), "repeater");
@@ -1044,6 +1056,16 @@ void tst_QQuickRepeater::package()
QCOMPARE(repeater2->count(), 1);
QCOMPARE(repeater2->itemAt(0)->objectName(), "secondItem");
}
+
+ {
+ QQmlComponent component(&engine, testFileUrl("package2.qml"));
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(root != nullptr);
+ bool returnedValue = false;
+ // calling setup should not crash
+ QMetaObject::invokeMethod(root.get(), "setup", Q_RETURN_ARG(bool, returnedValue));
+ QVERIFY(returnedValue);
+ }
}
void tst_QQuickRepeater::ownership()
@@ -1108,6 +1130,41 @@ void tst_QQuickRepeater::ownership()
QVERIFY(!modelGuard);
}
+void tst_QQuickRepeater::requiredProperties()
+{
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "apples0");
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "oranges1");
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "pears2");
+ QQmlEngine engine;
+
+ QQmlComponent component(&engine, testFileUrl("requiredProperty.qml"));
+ QScopedPointer<QObject> o {component.create()};
+ QVERIFY(o);
+}
+
+void tst_QQuickRepeater::contextProperties()
+{
+ QQmlEngine engine;
+
+ QQmlComponent component(&engine, testFileUrl("contextProperty.qml"));
+ QScopedPointer<QObject> o {component.create()};
+ QVERIFY(o);
+
+ auto *root = qobject_cast<QQuickItem *>(o.get());
+ QVERIFY(root);
+
+ QQueue<QQuickItem *> items;
+ items.append(root);
+
+ while (!items.isEmpty()) {
+ QQuickItem *item = items.dequeue();
+ QQmlContextData *data = QQmlContextData::get(qmlContext(item));
+ QVERIFY(!data->hasExtraObject);
+ for (QQuickItem *child : item->childItems())
+ items.enqueue(child);
+ }
+}
+
QTEST_MAIN(tst_QQuickRepeater)
#include "tst_qquickrepeater.moc"
diff --git a/tests/auto/quick/qquickshape/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
index 851475e2cd..578d8d4e3a 100644
--- a/tests/auto/quick/qquickshape/tst_qquickshape.cpp
+++ b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
@@ -283,7 +283,7 @@ void tst_QQuickShape::render()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimal platforms", Abort);
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -307,7 +307,7 @@ void tst_QQuickShape::renderWithMultipleSp()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimal platforms", Abort);
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -331,7 +331,7 @@ void tst_QQuickShape::radialGrad()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimal platforms", Abort);
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -355,7 +355,7 @@ void tst_QQuickShape::conicalGrad()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimal platforms", Abort);
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -379,7 +379,7 @@ void tst_QQuickShape::renderPolyline()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimal platforms", Abort);
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -408,7 +408,7 @@ void tst_QQuickShape::renderMultiline()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimal platforms", Abort);
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -474,7 +474,7 @@ void tst_QQuickShape::polylineDataTypes()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimal platforms", Abort);
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -625,7 +625,7 @@ void tst_QQuickShape::multilineDataTypes()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimal platforms", Abort);
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -673,7 +673,7 @@ void tst_QQuickShape::multilineStronglyTyped()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimal platforms", Abort);
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
diff --git a/tests/auto/quick/qquickstates/data/parentChangeCorrectReversal.qml b/tests/auto/quick/qquickstates/data/parentChangeCorrectReversal.qml
new file mode 100644
index 0000000000..3d38fa4046
--- /dev/null
+++ b/tests/auto/quick/qquickstates/data/parentChangeCorrectReversal.qml
@@ -0,0 +1,72 @@
+import QtQuick 2.10
+import QtQuick.Layouts 1.3
+
+Item {
+ id: root
+
+ visible: true
+
+ width: 400
+ height: 200
+ property bool switchToRight: false
+ property alias stayingRectX: stayingRect.x
+
+ RowLayout {
+ id: topLayout
+
+ anchors.fill: parent
+
+ Item {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ Rectangle {
+ id: leftRect
+
+ width: parent.width*(2/3)
+ height: width
+ anchors.centerIn: parent
+
+ color: "red"
+
+ Rectangle {
+ id: stayingRect
+
+ x: 70; y: 70
+ width: 50; height: 50
+
+ color: "yellow"
+ }
+ }
+ }
+
+ Item {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ Rectangle {
+ id: rightRect
+
+ width: parent.height*(2/3)
+ height: width
+ anchors.centerIn: parent
+
+ color: "green"
+ rotation: 45
+ }
+ }
+ }
+
+ states: State {
+ name: "switchToRight"
+
+ ParentChange {
+ target: stayingRect
+ parent: rightRect
+ width: 70
+ }
+
+ }
+
+ state: root.switchToRight ? "switchToRight" : ""
+}
diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
index 1eb797f54f..d5fea3cb28 100644
--- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
@@ -139,6 +139,7 @@ private slots:
void revertListMemoryLeak();
void duplicateStateName();
void trivialWhen();
+ void parentChangeCorrectReversal();
};
void tst_qquickstates::initTestCase()
@@ -1675,6 +1676,22 @@ void tst_qquickstates::trivialWhen()
QVERIFY(c.create());
}
+void tst_qquickstates::parentChangeCorrectReversal()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("parentChangeCorrectReversal.qml"));
+ QScopedPointer<QObject> root {c.create()};
+ QVERIFY(root);
+ QQmlProperty stayingRectX(root.get(), "stayingRectX");
+ qreal oldX = stayingRectX.read().toDouble();
+ QQmlProperty switchToRight(root.get(), "switchToRight");
+ switchToRight.write(true);
+ qreal newX = stayingRectX.read().toDouble();
+ QVERIFY(newX != oldX);
+ switchToRight.write(false);
+ QCOMPARE(oldX, stayingRectX.read().toDouble());
+}
+
QTEST_MAIN(tst_qquickstates)
diff --git a/tests/auto/quick/qquicktableview/data/delegateWithRequired.qml b/tests/auto/quick/qquicktableview/data/delegateWithRequired.qml
new file mode 100644
index 0000000000..bebfd86931
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/delegateWithRequired.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ delegate: tableViewDelegate
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ id: rect
+ required property string position
+ required property bool hasModelChildren
+ required property QtObject model
+ Text {text: rect.position}
+ implicitWidth: 100
+ implicitHeight: 100
+ Component.onCompleted: () => {if (rect.position === "R1:C1" && rect.model.hasModelChildren == rect.hasModelChildren) console.info("success")}
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/delegatewithRequiredUnset.qml b/tests/auto/quick/qquicktableview/data/delegatewithRequiredUnset.qml
new file mode 100644
index 0000000000..0c685cd49e
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/delegatewithRequiredUnset.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ delegate: tableViewDelegate
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ id: rect
+ required property string position
+ required property bool unset
+ required property bool hasModelChildren
+ required property QtObject model
+ Text {text: rect.position}
+ implicitWidth: 100
+ implicitHeight: 100
+ Component.onCompleted: () => {if (rect.position === "R1:C1" && rect.model.hasModelChildren == rect.hasModelChildren) console.info("success")}
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index 7c4a5ed65b..ef39a91a65 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -175,6 +175,7 @@ private slots:
void checkSyncView_differentSizedModels();
void checkSyncView_connect_late_data();
void checkSyncView_connect_late();
+ void delegateWithRequiredProperties();
void checkThatFetchMoreIsCalledWhenScrolledToTheEndOfTable();
void replaceModel();
};
@@ -2701,6 +2702,50 @@ void tst_QQuickTableView::checkThatFetchMoreIsCalledWhenScrolledToTheEndOfTable(
QCOMPARE(tableView->columns(), 5);
}
+void tst_QQuickTableView::delegateWithRequiredProperties()
+{
+ constexpr static int PositionRole = Qt::UserRole+1;
+ struct MyTable : QAbstractTableModel {
+
+
+ using QAbstractTableModel::QAbstractTableModel;
+
+ int rowCount(const QModelIndex& = QModelIndex()) const override {
+ return 3;
+ }
+
+ int columnCount(const QModelIndex& = QModelIndex()) const override {
+ return 3;
+ }
+
+ QVariant data(const QModelIndex &index, int = Qt::DisplayRole) const override {
+ return QVariant::fromValue(QString::asprintf("R%d:C%d", index.row(), index.column()));
+ }
+
+ QHash<int, QByteArray> roleNames() const override {
+ return QHash<int, QByteArray> { {PositionRole, "position"} };
+ }
+ };
+
+ auto model = QVariant::fromValue(QSharedPointer<MyTable>(new MyTable));
+ {
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "success");
+ LOAD_TABLEVIEW("delegateWithRequired.qml");
+ QVERIFY(tableView);
+ tableView->setModel(model);
+ WAIT_UNTIL_POLISHED;
+ QVERIFY(view->errors().empty());
+ }
+ {
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression(R"|(TableView: failed loading index: \d)|"));
+ LOAD_TABLEVIEW("delegatewithRequiredUnset.qml");
+ QVERIFY(tableView);
+ tableView->setModel(model);
+ WAIT_UNTIL_POLISHED;
+ QTRY_VERIFY(view->errors().empty());
+ }
+}
+
void tst_QQuickTableView::replaceModel()
{
LOAD_TABLEVIEW("replaceModelTableView.qml");
diff --git a/tests/auto/quick/qquicktext/BLACKLIST b/tests/auto/quick/qquicktext/BLACKLIST
index 08a5249e2e..f50276a4f1 100644
--- a/tests/auto/quick/qquicktext/BLACKLIST
+++ b/tests/auto/quick/qquicktext/BLACKLIST
@@ -4,3 +4,5 @@ qemu
macos
[fontSizeMode]
opensuse-42.1
+[hAlignVisual]
+sles
diff --git a/tests/auto/quick/qquicktext/data/displaySuperscriptedTag.qml b/tests/auto/quick/qquicktext/data/displaySuperscriptedTag.qml
new file mode 100644
index 0000000000..b0ed21a0c8
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/displaySuperscriptedTag.qml
@@ -0,0 +1,18 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 200
+ height: 200
+ color: "white"
+ Text {
+ objectName: "text"
+ textFormat: Text.RichText
+ anchors.fill: parent
+ color: "black"
+ // display a black rectangle at the top left of the text
+ text: "<span style=\"background-color:rgba(255,255,255,255);vertical-align:super;\">&#x2588;</span>This is a test"
+ verticalAlignment: Text.AlignTop
+ horizontalAlignment: Text.AlignLeft
+ font.pixelSize: 30
+ }
+}
diff --git a/tests/auto/quick/qquicktext/data/lineLayout.qml b/tests/auto/quick/qquicktext/data/lineLayout.qml
index cb2474791e..5a980de7da 100644
--- a/tests/auto/quick/qquicktext/data/lineLayout.qml
+++ b/tests/auto/quick/qquicktext/data/lineLayout.qml
@@ -14,6 +14,9 @@ Rectangle {
textFormat: Text.StyledText
focus: true
+ property int lastLineNumber: -1
+ property bool receivedMultipleLastLines
+
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."
@@ -30,6 +33,12 @@ Rectangle {
line.x = line.width * 2 + 60
line.height = 20
}
+
+ // Save last line number, it is important to do this after setting the width
+ if (line.isLast) {
+ receivedMultipleLastLines = (lastLineNumber !== -1) && (lastLineNumber !== line.number)
+ lastLineNumber = line.number
+ }
}
}
}
diff --git a/tests/auto/quick/qquicktext/data/lineLayoutImplicitWidth.qml b/tests/auto/quick/qquicktext/data/lineLayoutImplicitWidth.qml
new file mode 100644
index 0000000000..de5ca616b8
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/lineLayoutImplicitWidth.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Jolla Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ id: main
+ width: 800; height: 600
+
+ property real off: 0
+
+ Text {
+ id: myText
+ objectName: "myText"
+ wrapMode: Text.WordWrap
+ font.pixelSize: 14
+ textFormat: Text.PlainText
+ focus: true
+ anchors.fill: parent
+
+ // The autotest will retrieve these so that it can verify them
+ property var lineImplicitWidths: []
+
+ 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: {
+ var n = line.number
+
+ // Save information about the line so the autotest can retrieve it
+ lineImplicitWidths[n] = line.implicitWidth
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index e62db81d27..42fdbea58d 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -30,6 +30,7 @@
#include <QTextDocument>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qjsvalue.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQuick/private/qquickmousearea_p.h>
#include <QtQuickTest/QtQuickTest>
@@ -119,6 +120,7 @@ private slots:
void lineLaidOut();
void lineLaidOutRelayout();
void lineLaidOutHAlign();
+ void lineLaidOutImplicitWidth();
void imgTagsBaseUrl_data();
void imgTagsBaseUrl();
@@ -166,6 +168,8 @@ private slots:
void transparentBackground();
+ void displaySuperscriptedTag();
+
private:
QStringList standard;
QStringList richText;
@@ -1035,7 +1039,7 @@ void tst_qquicktext::hAlignImplicitWidth()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimal platforms", Abort);
// Left Align
QImage image = view.grabWindow();
@@ -2871,6 +2875,13 @@ void tst_qquicktext::lineLaidOut()
QCOMPARE(r.height(), qreal(20));
}
}
+
+ // Ensure that isLast was correctly emitted
+ int lastLineNumber = myText->property("lastLineNumber").toInt();
+ QCOMPARE(lastLineNumber, myText->lineCount() - 1);
+ // Ensure that only one line was considered last (after changing its width)
+ bool receivedMultipleLastLines = myText->property("receivedMultipleLastLines").toBool();
+ QVERIFY(!receivedMultipleLastLines);
}
void tst_qquicktext::lineLaidOutRelayout()
@@ -2975,6 +2986,53 @@ void tst_qquicktext::imgTagsBaseUrl_data()
<< 181.;
}
+void tst_qquicktext::lineLaidOutImplicitWidth()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("lineLayoutImplicitWidth.qml")));
+
+ QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
+ QVERIFY(myText != nullptr);
+
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
+ QVERIFY(textPrivate != nullptr);
+
+ // Retrieve the saved implicitWidth values of each rendered line
+ QVariant widthsProperty = myText->property("lineImplicitWidths");
+ QVERIFY(!widthsProperty.isNull());
+ QVERIFY(widthsProperty.isValid());
+ QVERIFY(widthsProperty.canConvert<QJSValue>());
+ QJSValue widthsValue = widthsProperty.value<QJSValue>();
+ QVERIFY(widthsValue.isArray());
+ int lineCount = widthsValue.property("length").toInt();
+ QVERIFY(lineCount > 0);
+
+ // Create the same text layout by hand
+ // Note that this approach needs additional processing for styled text,
+ // so we only use it for plain text here.
+ QTextLayout layout;
+ layout.setCacheEnabled(true);
+ layout.setText(myText->text());
+ layout.setTextOption(textPrivate->layout.textOption());
+ layout.setFont(myText->font());
+ layout.beginLayout();
+ for (QTextLine line = layout.createLine(); line.isValid(); line = layout.createLine()) {
+ line.setLineWidth(myText->width());
+ }
+ layout.endLayout();
+
+ // Line count of the just created layout should match the rendered text
+ QCOMPARE(lineCount, layout.lineCount());
+
+ // Go through each line and verify that the values emitted by lineLaidOut are correct
+ for (int i = 0; i < layout.lineCount(); ++i) {
+ qreal implicitWidth = widthsValue.property(i).toNumber();
+ QVERIFY(implicitWidth > 0);
+
+ QTextLine line = layout.lineAt(i);
+ QCOMPARE(implicitWidth, line.naturalTextWidth());
+ }
+}
+
static QUrl substituteTestServerUrl(const QUrl &serverUrl, const QUrl &testUrl)
{
QUrl result = testUrl;
@@ -4435,7 +4493,7 @@ void tst_qquicktext::transparentBackground()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabToImage not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabToImage not functional on offscreen/minimal platforms");
QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("transparentBackground.qml"));
@@ -4451,6 +4509,32 @@ void tst_qquicktext::transparentBackground()
QCOMPARE(color.blue(), 255);
QCOMPARE(color.green(), 255);
}
+
+void tst_qquicktext::displaySuperscriptedTag()
+{
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabToImage not functional on offscreen/minimal platforms");
+
+ QScopedPointer<QQuickView> window(new QQuickView);
+ window->setSource(testFileUrl("displaySuperscriptedTag.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickText *text = window->findChild<QQuickText *>("text");
+ QVERIFY(text);
+
+ QImage img = window->grabWindow();
+ QCOMPARE(img.isNull(), false);
+
+ QColor color = img.pixelColor(1, static_cast<int>(text->contentHeight()) / 4 * 3);
+ QCOMPARE(color.red(), 255);
+ QCOMPARE(color.blue(), 255);
+ QCOMPARE(color.green(), 255);
+}
+
QTEST_MAIN(tst_qquicktext)
#include "tst_qquicktext.moc"
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index facd63027e..8ea2ce3bfb 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -131,8 +131,10 @@ private slots:
void mouseSelectionMode_accessors();
void selectByMouse();
void selectByKeyboard();
+#if QT_CONFIG(shortcut)
void keyboardSelection_data();
void keyboardSelection();
+#endif
void renderType();
void inputMethodHints();
@@ -190,16 +192,19 @@ private slots:
void insert();
void remove_data();
void remove();
-
+#if QT_CONFIG(shortcut)
void keySequence_data();
void keySequence();
+#endif
void undo_data();
void undo();
void redo_data();
void redo();
+#if QT_CONFIG(shortcut)
void undo_keypressevents_data();
void undo_keypressevents();
+#endif
void clear();
void baseUrl();
@@ -217,9 +222,11 @@ private slots:
private:
void simulateKeys(QWindow *window, const QList<Key> &keys);
+#if QT_CONFIG(shortcut)
void simulateKeys(QWindow *window, const QKeySequence &sequence);
+#endif
- void simulateKey(QWindow *, int key, Qt::KeyboardModifiers modifiers = nullptr);
+ void simulateKey(QWindow *, int key, Qt::KeyboardModifiers modifiers = {});
QStringList standard;
QStringList richText;
@@ -260,6 +267,8 @@ void tst_qquicktextedit::simulateKeys(QWindow *window, const QList<Key> &keys)
}
}
+#if QT_CONFIG(shortcut)
+
void tst_qquicktextedit::simulateKeys(QWindow *window, const QKeySequence &sequence)
{
for (int i = 0; i < sequence.count(); ++i) {
@@ -277,6 +286,8 @@ QList<Key> &operator <<(QList<Key> &keys, const QKeySequence &sequence)
return keys;
}
+#endif // QT_CONFIG(shortcut)
+
template <int N> QList<Key> &operator <<(QList<Key> &keys, const char (&characters)[N])
{
for (int i = 0; i < N - 1; ++i) {
@@ -916,7 +927,7 @@ void tst_qquicktextedit::hAlignVisual()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimal platforms", Abort);
// Left Align
QImage image = view.grabWindow();
@@ -1378,7 +1389,7 @@ void tst_qquicktextedit::focusOnPress()
QCOMPARE(textEditObject->hasActiveFocus(), false);
QPoint centerPoint(window.width()/2, window.height()/2);
- Qt::KeyboardModifiers noModifiers = nullptr;
+ Qt::KeyboardModifiers noModifiers;
QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QCOMPARE(textEditObject->hasFocus(), true);
@@ -2307,6 +2318,8 @@ void tst_qquicktextedit::selectByKeyboard()
QCOMPARE(spy.at(2).at(0).toBool(), false);
}
+#if QT_CONFIG(shortcut)
+
Q_DECLARE_METATYPE(QKeySequence::StandardKey)
void tst_qquicktextedit::keyboardSelection_data()
@@ -2391,6 +2404,8 @@ void tst_qquicktextedit::keyboardSelection()
QCOMPARE(edit->selectedText(), selectedText);
}
+#endif // QT_CONFIG(shortcut)
+
void tst_qquicktextedit::renderType()
{
QQmlComponent component(&engine);
@@ -4820,6 +4835,7 @@ void tst_qquicktextedit::remove()
QVERIFY(cursorPositionSpy.count() > 0);
}
+#if QT_CONFIG(shortcut)
void tst_qquicktextedit::keySequence_data()
{
@@ -4984,6 +5000,8 @@ void tst_qquicktextedit::keySequence()
QCOMPARE(textEdit->selectedText(), selectedText);
}
+#endif // QT_CONFIG(shortcut)
+
#define NORMAL 0
#define REPLACE_UNTIL_END 1
@@ -5257,6 +5275,8 @@ void tst_qquicktextedit::redo()
QCOMPARE(spy.count(), 2);
}
+#if QT_CONFIG(shortcut)
+
void tst_qquicktextedit::undo_keypressevents_data()
{
QTest::addColumn<KeyList>("keys");
@@ -5450,6 +5470,8 @@ void tst_qquicktextedit::undo_keypressevents()
QVERIFY(textEdit->text().isEmpty());
}
+#endif // QT_CONFIG(shortcut)
+
void tst_qquicktextedit::clear()
{
QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true }";
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index 6f24ca8ded..2e64c80b85 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -146,7 +146,7 @@ private slots:
void cursorRectangle();
void navigation();
void navigation_RTL();
-#if QT_CONFIG(clipboard)
+#if QT_CONFIG(clipboard) && QT_CONFIG(shortcut)
void copyAndPaste();
void copyAndPasteKeySequence();
void canPasteEmpty();
@@ -181,15 +181,19 @@ private slots:
void remove_data();
void remove();
+#if QT_CONFIG(shortcut)
void keySequence_data();
void keySequence();
+#endif
void undo_data();
void undo();
void redo_data();
void redo();
+#if QT_CONFIG(shortcut)
void undo_keypressevents_data();
void undo_keypressevents();
+#endif
void clear();
void backspaceSurrogatePairs();
@@ -236,7 +240,9 @@ private:
void simulateKey(QWindow *, int key);
void simulateKeys(QWindow *window, const QList<Key> &keys);
+#if QT_CONFIG(shortcut)
void simulateKeys(QWindow *window, const QKeySequence &sequence);
+#endif
QQmlEngine engine;
QStringList standard;
@@ -264,6 +270,8 @@ void tst_qquicktextinput::simulateKeys(QWindow *window, const QList<Key> &keys)
}
}
+#if QT_CONFIG(shortcut)
+
void tst_qquicktextinput::simulateKeys(QWindow *window, const QKeySequence &sequence)
{
for (int i = 0; i < sequence.count(); ++i) {
@@ -281,6 +289,8 @@ QList<Key> &operator <<(QList<Key> &keys, const QKeySequence &sequence)
return keys;
}
+#endif // QT_CONFIG(shortcut)
+
template <int N> QList<Key> &operator <<(QList<Key> &keys, const char (&characters)[N])
{
for (int i = 0; i < N - 1; ++i) {
@@ -2063,11 +2073,15 @@ void tst_qquicktextinput::validators()
QTest::keyPress(&window, Qt::Key_Comma);
QTest::keyRelease(&window, Qt::Key_Comma, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12,"));
- QCOMPARE(dblInput->hasAcceptableInput(), true);
- QTest::keyPress(&window, Qt::Key_1);
- QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier);
- QTRY_COMPARE(dblInput->text(), QLatin1String("12,"));
- QCOMPARE(dblInput->hasAcceptableInput(), true);
+ int extraSignals = 2;
+ if (dblInput->hasAcceptableInput()) {
+ // TODO: old behavior of QDoubleValidator - remove when merged from qtbase
+ QTest::keyPress(&window, Qt::Key_1);
+ QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier);
+ QTRY_COMPARE(dblInput->text(), QLatin1String("12,"));
+ QCOMPARE(dblInput->hasAcceptableInput(), true);
+ extraSignals = 0;
+ }
dblValidator->setLocaleName(deLocale.name());
QCOMPARE(dblInput->hasAcceptableInput(), true);
QTest::keyPress(&window, Qt::Key_1);
@@ -2096,84 +2110,84 @@ void tst_qquicktextinput::validators()
QTRY_COMPARE(dblInput->text(), QLatin1String("12."));
QCOMPARE(dblInput->hasAcceptableInput(), true);
QCOMPARE(dblInput->property("acceptable").toBool(), true);
- QCOMPARE(dblSpy.count(), 1);
+ QCOMPARE(dblSpy.count(), 1 + extraSignals);
QTest::keyPress(&window, Qt::Key_1);
QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12.1"));
QCOMPARE(dblInput->hasAcceptableInput(), true);
QCOMPARE(dblInput->property("acceptable").toBool(), true);
- QCOMPARE(dblSpy.count(), 1);
+ QCOMPARE(dblSpy.count(), 1 + extraSignals);
QTest::keyPress(&window, Qt::Key_1);
QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12.11"));
QCOMPARE(dblInput->hasAcceptableInput(), true);
QCOMPARE(dblInput->property("acceptable").toBool(), true);
- QCOMPARE(dblSpy.count(), 1);
+ QCOMPARE(dblSpy.count(), 1 + extraSignals);
QTest::keyPress(&window, Qt::Key_1);
QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12.11"));
QCOMPARE(dblInput->hasAcceptableInput(), true);
QCOMPARE(dblInput->property("acceptable").toBool(), true);
- QCOMPARE(dblSpy.count(), 1);
+ QCOMPARE(dblSpy.count(), 1 + extraSignals);
// Ensure the validator doesn't prevent characters being removed.
dblInput->setValidator(intInput->validator());
QCOMPARE(dblInput->text(), QLatin1String("12.11"));
QCOMPARE(dblInput->hasAcceptableInput(), false);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
- QCOMPARE(dblSpy.count(), 2);
+ QCOMPARE(dblSpy.count(), 2 + extraSignals);
QTest::keyPress(&window, Qt::Key_Backspace);
QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12.1"));
QCOMPARE(dblInput->hasAcceptableInput(), false);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
- QCOMPARE(dblSpy.count(), 2);
+ QCOMPARE(dblSpy.count(), 2 + extraSignals);
// Once unacceptable input is in anything goes until it reaches an acceptable state again.
QTest::keyPress(&window, Qt::Key_1);
QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12.11"));
QCOMPARE(dblInput->hasAcceptableInput(), false);
- QCOMPARE(dblSpy.count(), 2);
+ QCOMPARE(dblSpy.count(), 2 + extraSignals);
QTest::keyPress(&window, Qt::Key_Backspace);
QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12.1"));
QCOMPARE(dblInput->hasAcceptableInput(), false);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
- QCOMPARE(dblSpy.count(), 2);
+ QCOMPARE(dblSpy.count(), 2 + extraSignals);
QTest::keyPress(&window, Qt::Key_Backspace);
QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12."));
QCOMPARE(dblInput->hasAcceptableInput(), false);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
- QCOMPARE(dblSpy.count(), 2);
+ QCOMPARE(dblSpy.count(), 2 + extraSignals);
QTest::keyPress(&window, Qt::Key_Backspace);
QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12"));
QCOMPARE(dblInput->hasAcceptableInput(), false);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
- QCOMPARE(dblSpy.count(), 2);
+ QCOMPARE(dblSpy.count(), 2 + extraSignals);
QTest::keyPress(&window, Qt::Key_Backspace);
QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("1"));
QCOMPARE(dblInput->hasAcceptableInput(), false);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
- QCOMPARE(dblSpy.count(), 2);
+ QCOMPARE(dblSpy.count(), 2 + extraSignals);
QTest::keyPress(&window, Qt::Key_1);
QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier);
QCOMPARE(dblInput->text(), QLatin1String("11"));
QCOMPARE(dblInput->property("acceptable").toBool(), true);
QCOMPARE(dblInput->hasAcceptableInput(), true);
- QCOMPARE(dblSpy.count(), 3);
+ QCOMPARE(dblSpy.count(), 3 + extraSignals);
// Changing the validator properties will re-evaluate whether the input is acceptable.
intValidator->setTop(10);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
QCOMPARE(dblInput->hasAcceptableInput(), false);
- QCOMPARE(dblSpy.count(), 4);
+ QCOMPARE(dblSpy.count(), 4 + extraSignals);
intValidator->setTop(12);
QCOMPARE(dblInput->property("acceptable").toBool(), true);
QCOMPARE(dblInput->hasAcceptableInput(), true);
- QCOMPARE(dblSpy.count(), 5);
+ QCOMPARE(dblSpy.count(), 5 + extraSignals);
QQuickTextInput *strInput = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(window.rootObject()->property("strInput")));
QVERIFY(strInput);
@@ -2586,7 +2600,7 @@ void tst_qquicktextinput::navigation_RTL()
QVERIFY(input->hasActiveFocus());
}
-#if QT_CONFIG(clipboard)
+#if QT_CONFIG(clipboard) && QT_CONFIG(shortcut)
void tst_qquicktextinput::copyAndPaste()
{
if (!PlatformQuirks::isClipboardAvailable())
@@ -2684,7 +2698,7 @@ void tst_qquicktextinput::copyAndPaste()
}
#endif
-#if QT_CONFIG(clipboard)
+#if QT_CONFIG(clipboard) && QT_CONFIG(shortcut)
void tst_qquicktextinput::copyAndPasteKeySequence()
{
if (!PlatformQuirks::isClipboardAvailable())
@@ -2752,7 +2766,7 @@ void tst_qquicktextinput::copyAndPasteKeySequence()
}
#endif
-#if QT_CONFIG(clipboard)
+#if QT_CONFIG(clipboard) && QT_CONFIG(shortcut)
void tst_qquicktextinput::canPasteEmpty()
{
QGuiApplication::clipboard()->clear();
@@ -2768,7 +2782,7 @@ void tst_qquicktextinput::canPasteEmpty()
}
#endif
-#if QT_CONFIG(clipboard)
+#if QT_CONFIG(clipboard) && QT_CONFIG(shortcut)
void tst_qquicktextinput::canPaste()
{
QGuiApplication::clipboard()->setText("Some text");
@@ -2784,7 +2798,7 @@ void tst_qquicktextinput::canPaste()
}
#endif
-#if QT_CONFIG(clipboard)
+#if QT_CONFIG(clipboard) && QT_CONFIG(shortcut)
void tst_qquicktextinput::middleClickPaste()
{
if (!PlatformQuirks::isClipboardAvailable())
@@ -5098,6 +5112,7 @@ void tst_qquicktextinput::remove()
QVERIFY(cursorPositionSpy.count() > 0);
}
+#if QT_CONFIG(shortcut)
void tst_qquicktextinput::keySequence_data()
{
QTest::addColumn<QString>("text");
@@ -5283,6 +5298,8 @@ void tst_qquicktextinput::keySequence()
QCOMPARE(textInput->selectedText(), selectedText);
}
+#endif // QT_CONFIG(shortcut)
+
#define NORMAL 0
#define REPLACE_UNTIL_END 1
@@ -5556,6 +5573,8 @@ void tst_qquicktextinput::redo()
QCOMPARE(spy.count(), 2);
}
+#if QT_CONFIG(shortcut)
+
void tst_qquicktextinput::undo_keypressevents_data()
{
QTest::addColumn<KeyList>("keys");
@@ -5860,6 +5879,8 @@ void tst_qquicktextinput::undo_keypressevents()
QVERIFY(textInput->text().isEmpty());
}
+#endif // QT_CONFIG(shortcut)
+
void tst_qquicktextinput::clear()
{
QString componentStr = "import QtQuick 2.0\nTextInput { focus: true }";
@@ -6391,8 +6412,20 @@ void tst_qquicktextinput::setInputMask_data()
QTest::newRow(QString(insert_mode + "blank=input").toLatin1())
<< QString("9999;0")
<< QString("2004")
+ << QString("24")
<< QString("2004")
- << QString("2004")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "any_opt").toLatin1())
+ << QString("@xxx@")
+ << QString("@A C@")
+ << QString("@AC@")
+ << QString("@A C@")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "any_req").toLatin1())
+ << QString("@XXX@")
+ << QString("@A C@")
+ << QString("@AC@@")
+ << QString("@AC@@")
<< bool(insert_text);
}
}
@@ -6435,9 +6468,6 @@ void tst_qquicktextinput::setInputMask()
QTest::keyClick(&window, input.at(i).toLatin1());
}
- QEXPECT_FAIL( "keys blank=input", "To eat blanks or not? Known issue. Task 43172", Abort);
- QEXPECT_FAIL( "insert blank=input", "To eat blanks or not? Known issue. Task 43172", Abort);
-
QCOMPARE(textInput->text(), expectedText);
QCOMPARE(textInput->displayText(), expectedDisplay);
}
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/readFromProxyObject.qml b/tests/auto/quick/qquickvisualdatamodel/data/readFromProxyObject.qml
new file mode 100644
index 0000000000..3983c707a1
--- /dev/null
+++ b/tests/auto/quick/qquickvisualdatamodel/data/readFromProxyObject.qml
@@ -0,0 +1,23 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ id: window
+ width: 200
+ height: 200
+ color: "red"
+ visible: true
+ Repeater {
+ model: Qt.application.screens
+ Text {
+ required property string name
+ required property int virtualX
+ required property int virtualY
+
+ text: name + virtualX + ", " + virtualY
+ Component.onCompleted: window.name = name
+ }
+ }
+
+ property string name: "wrong"
+}
diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
index c5a3bceee0..66069c48cb 100644
--- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
+++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
@@ -434,6 +434,7 @@ private slots:
void externalManagedModel();
void delegateModelChangeDelegate();
void checkFilterGroupForDelegate();
+ void readFromProxyObject();
private:
template <int N> void groups_verify(
@@ -4356,6 +4357,21 @@ void tst_qquickvisualdatamodel::checkFilterGroupForDelegate()
QVERIFY(obj->property("ok").toBool());
}
+void tst_qquickvisualdatamodel::readFromProxyObject()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("readFromProxyObject.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj);
+
+ auto *window = qobject_cast<QQuickWindow *>(obj.get());
+ QVERIFY(window);
+
+ QCOMPARE(window->property("name").type(), QMetaType::QString);
+ QTRY_VERIFY(window->property("name").toString() != QLatin1String("wrong"));
+}
+
QTEST_MAIN(tst_qquickvisualdatamodel)
#include "tst_qquickvisualdatamodel.moc"
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index 7faa621e86..22b04eabd8 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -73,7 +73,7 @@ static QTouchEvent::TouchPoint makeTouchPoint(QQuickItem *item, const QPointF &p
return tp;
}
-static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states = nullptr,
+static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states = {},
const QList<QTouchEvent::TouchPoint>& touchPoints = QList<QTouchEvent::TouchPoint>())
{
TouchEventData d = { type, nullptr, w, states, touchPoints };
@@ -157,7 +157,7 @@ public:
setEnabled(true);
setVisible(true);
- lastEvent = makeTouchData(QEvent::None, window(), nullptr, QList<QTouchEvent::TouchPoint>());//CHECK_VALID
+ lastEvent = makeTouchData(QEvent::None, window(), {}, QList<QTouchEvent::TouchPoint>());//CHECK_VALID
lastVelocity = lastVelocityFromMouseMove = QVector2D();
lastMousePos = QPointF();
@@ -1481,7 +1481,7 @@ void tst_qquickwindow::grab()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QFETCH(bool, visible);
QFETCH(bool, alpha);
@@ -1797,22 +1797,26 @@ void tst_qquickwindow::cursor()
window.resize(320, 290);
QQuickItem parentItem;
+ parentItem.setObjectName("parentItem");
parentItem.setPosition(QPointF(0, 0));
parentItem.setSize(QSizeF(180, 180));
parentItem.setParentItem(window.contentItem());
QQuickItem childItem;
+ childItem.setObjectName("childItem");
childItem.setPosition(QPointF(60, 90));
childItem.setSize(QSizeF(120, 120));
childItem.setParentItem(&parentItem);
QQuickItem clippingItem;
+ clippingItem.setObjectName("clippingItem");
clippingItem.setPosition(QPointF(120, 120));
clippingItem.setSize(QSizeF(180, 180));
clippingItem.setClip(true);
clippingItem.setParentItem(window.contentItem());
QQuickItem clippedItem;
+ clippedItem.setObjectName("clippedItem");
clippedItem.setPosition(QPointF(-30, -30));
clippedItem.setSize(QSizeF(120, 120));
clippedItem.setParentItem(&clippingItem);
@@ -2082,7 +2086,7 @@ void tst_qquickwindow::requestActivate()
QString warning = QString::fromLatin1("Mouse event MousePress not accepted by receiving window");
QWARN(warning.toLatin1().data());
}
- me = QMouseEvent(QEvent::MouseButtonPress, pos, window1->mapToGlobal(pos), Qt::LeftButton, nullptr, Qt::NoModifier);
+ me = QMouseEvent(QEvent::MouseButtonPress, pos, window1->mapToGlobal(pos), Qt::LeftButton, {}, Qt::NoModifier);
QSpontaneKeyEvent::setSpontaneous(&me);
if (!qApp->notify(window1.data(), &me)) {
QString warning = QString::fromLatin1("Mouse event MouseRelease not accepted by receiving window");
@@ -2535,7 +2539,7 @@ void tst_qquickwindow::testRenderJob()
QTRY_COMPARE(RenderJob::deleted, 1);
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QEXPECT_FAIL("", "NoStage job fails on offscreen/minimimal platforms", Continue);
+ QEXPECT_FAIL("", "NoStage job fails on offscreen/minimal platforms", Continue);
QCOMPARE(completedJobs.size(), 1);
#if QT_CONFIG(opengl)
@@ -2856,7 +2860,7 @@ void tst_qquickwindow::pointerEventTypeAndPointCount()
QList<QTouchEvent::TouchPoint>() << QTouchEvent::TouchPoint(1));
- QQuickPointerMouseEvent pme;
+ QQuickPointerMouseEvent pme(nullptr, QQuickPointerDevice::genericMouseDevice());
pme.reset(&me);
QCOMPARE(pme.asMouseEvent(localPosition), &me);
QVERIFY(pme.asPointerMouseEvent());
@@ -2868,7 +2872,7 @@ void tst_qquickwindow::pointerEventTypeAndPointCount()
QCOMPARE(pme.asMouseEvent(localPosition)->localPos(), localPosition);
QCOMPARE(pme.asMouseEvent(localPosition)->screenPos(), screenPosition);
- QQuickPointerTouchEvent pte;
+ QQuickPointerTouchEvent pte(nullptr, QQuickPointerDevice::touchDevice(touchDevice));
pte.reset(&te);
QCOMPARE(pte.asTouchEvent(), &te);
QVERIFY(!pte.asPointerMouseEvent());
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index b6ffdc0f7e..0db8abd951 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -15,7 +15,8 @@ qtConfig(opengl(es1|es2)?) {
qquickframebufferobject \
qquickopenglinfo \
qquickspritesequence \
- qquickshadereffect
+ qquickshadereffect \
+ qquickrendercontrol
}
!cross_compile: PRIVATETESTS += examples
@@ -96,6 +97,8 @@ boot2qt: QUICKTESTS -= qquickgridview qquicklistview qquicktableview qquickposit
!qtConfig(accessibility):QUICKTESTS -= qquickaccessible
+!qtConfig(shortcut):QUICKTESTS -= qquickshortcut
+
qtConfig(private_tests) {
SUBDIRS += $$PRIVATETESTS
SUBDIRS += $$QUICKTESTS
diff --git a/tests/auto/quick/rendernode/tst_rendernode.cpp b/tests/auto/quick/rendernode/tst_rendernode.cpp
index 6ca5231343..ec248e8210 100644
--- a/tests/auto/quick/rendernode/tst_rendernode.cpp
+++ b/tests/auto/quick/rendernode/tst_rendernode.cpp
@@ -218,7 +218,7 @@ void tst_rendernode::renderOrder()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
if (isRunningOnRhi())
QSKIP("Render nodes not yet supported with QRhi");
@@ -251,7 +251,7 @@ void tst_rendernode::messUpState()
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
if (isRunningOnRhi())
QSKIP("Render nodes not yet supported with QRhi");
@@ -312,7 +312,7 @@ void tst_rendernode::matrix()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
if (isRunningOnRhi())
QSKIP("Render nodes not yet supported with QRhi");
diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
index 3f605348c3..12f7efb7d5 100644
--- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp
+++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
@@ -241,7 +241,7 @@ void tst_SceneGraph::manyWindows()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QFETCH(QString, file);
QFETCH(bool, toplevel);
diff --git a/tests/auto/quick/shared/viewtestutil.cpp b/tests/auto/quick/shared/viewtestutil.cpp
index 1680e850f7..67b73f047c 100644
--- a/tests/auto/quick/shared/viewtestutil.cpp
+++ b/tests/auto/quick/shared/viewtestutil.cpp
@@ -73,13 +73,13 @@ void QQuickViewTestUtil::moveMouseAway(QQuickView *window)
void QQuickViewTestUtil::moveAndRelease(QQuickView *window, const QPoint &position)
{
QTest::mouseMove(window, position);
- QTest::mouseRelease(window, Qt::LeftButton, 0, position);
+ QTest::mouseRelease(window, Qt::LeftButton, {}, position);
}
void QQuickViewTestUtil::moveAndPress(QQuickView *window, const QPoint &position)
{
QTest::mouseMove(window, position);
- QTest::mousePress(window, Qt::LeftButton, 0, position);
+ QTest::mousePress(window, Qt::LeftButton, {}, position);
}
void QQuickViewTestUtil::flick(QQuickView *window, const QPoint &from, const QPoint &to, int duration)
@@ -282,14 +282,28 @@ void QQuickViewTestUtil::QaimModel::resetItems(const QList<QPair<QString, QStrin
endResetModel();
}
+class ScopedPrintable
+{
+ Q_DISABLE_COPY_MOVE(ScopedPrintable)
+
+public:
+ ScopedPrintable(const QString &string) : data(QTest::toString(string)) {}
+ ~ScopedPrintable() { delete[] data; }
+
+ operator const char*() const { return data; }
+
+private:
+ const char *data;
+};
+
void QQuickViewTestUtil::QaimModel::matchAgainst(const QList<QPair<QString, QString> > &other, const QString &error1, const QString &error2) {
for (int i=0; i<other.count(); i++) {
QVERIFY2(list.contains(other[i]),
- QTest::toString(other[i].first + QLatin1Char(' ') + other[i].second + QLatin1Char(' ') + error1));
+ ScopedPrintable(other[i].first + QLatin1Char(' ') + other[i].second + QLatin1Char(' ') + error1));
}
for (int i=0; i<list.count(); i++) {
QVERIFY2(other.contains(list[i]),
- QTest::toString(list[i].first + QLatin1Char(' ') + list[i].second + QLatin1Char(' ') + error2));
+ ScopedPrintable(list[i].first + QLatin1Char(' ') + list[i].second + QLatin1Char(' ') + error2));
}
}
diff --git a/tests/auto/quickwidgets/qquickwidget/data/resizeOverlay.qml b/tests/auto/quickwidgets/qquickwidget/data/resizeOverlay.qml
new file mode 100644
index 0000000000..5547856941
--- /dev/null
+++ b/tests/auto/quickwidgets/qquickwidget/data/resizeOverlay.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.15
+
+import Test 1.0
+
+Item {
+ id: root
+
+ property alias overlay: overlay
+
+ Overlay {
+ id: overlay
+ // Parent it to the contentItem of the underlying QQuickWindow.
+ parent: root.parent
+ }
+}
diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
index 691dfd1bc6..12c51caa75 100644
--- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
+++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
@@ -33,6 +33,7 @@
#include <QtQml/qqmlcontext.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
+#include <QtQuick/private/qquickitem_p.h>
#include "../../shared/util.h"
#include <QtGui/QWindow>
#include <QtGui/QScreen>
@@ -142,6 +143,7 @@ private slots:
void synthMouseFromTouch_data();
void synthMouseFromTouch();
void tabKey();
+ void resizeOverlay();
private:
QTouchDevice *device = QTest::createTouchDevice();
@@ -662,6 +664,74 @@ void tst_qquickwidget::tabKey()
QVERIFY(middleItem->property("activeFocus").toBool());
}
+class Overlay : public QQuickItem, public QQuickItemChangeListener
+{
+ Q_OBJECT
+
+public:
+ Overlay() = default;
+
+ ~Overlay()
+ {
+ QQuickItemPrivate::get(parentItem())->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
+ }
+
+ // componentCompleted() is too early to add the listener, as parentItem()
+ // is still null by that stage, so we use this function instead.
+ void startListening()
+ {
+ QQuickItemPrivate::get(parentItem())->addItemChangeListener(this, QQuickItemPrivate::Geometry);
+ }
+
+private:
+ virtual void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &/*oldGeometry*/) override
+ {
+ auto window = QQuickItemPrivate::get(this)->window;
+ if (!window)
+ return;
+
+ setSize(window->size());
+ }
+};
+
+// Test that an item that resizes itself based on the window size can use a
+// Geometry item change listener to respond to changes in size. This is a
+// simplified test to mimic a use case involving Overlay from Qt Quick Controls 2.
+void tst_qquickwidget::resizeOverlay()
+{
+ QWidget widget;
+ auto contentVerticalLayout = new QVBoxLayout(&widget);
+ contentVerticalLayout->setMargin(0);
+
+ qmlRegisterType<Overlay>("Test", 1, 0, "Overlay");
+
+ auto quickWidget = new QQuickWidget(testFileUrl("resizeOverlay.qml"), &widget);
+ QCOMPARE(quickWidget->status(), QQuickWidget::Ready);
+ quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
+ contentVerticalLayout->addWidget(quickWidget);
+
+ auto rootItem = qobject_cast<QQuickItem*>(quickWidget->rootObject());
+ QVERIFY(rootItem);
+
+ auto overlay = rootItem->property("overlay").value<Overlay*>();
+ QVERIFY(overlay);
+ QVERIFY(overlay->parentItem());
+ overlay->startListening();
+
+ widget.resize(200, 200);
+ widget.show();
+ QCOMPARE(rootItem->width(), 200);
+ QCOMPARE(rootItem->height(), 200);
+ QCOMPARE(overlay->width(), rootItem->width());
+ QCOMPARE(overlay->height(), rootItem->height());
+
+ widget.resize(300, 300);
+ QCOMPARE(rootItem->width(), 300);
+ QCOMPARE(rootItem->height(), 300);
+ QCOMPARE(overlay->width(), rootItem->width());
+ QCOMPARE(overlay->height(), rootItem->height());
+}
+
QTEST_MAIN(tst_qquickwidget)
#include "tst_qquickwidget.moc"
diff --git a/tests/auto/shared/astdump.pri b/tests/auto/shared/astdump.pri
new file mode 100644
index 0000000000..365b12fc51
--- /dev/null
+++ b/tests/auto/shared/astdump.pri
@@ -0,0 +1,7 @@
+
+INCLUDEPATH += $$PWD
+HEADERS += \
+ $$PWD/qqmljsastdumper.h
+
+SOURCES += \
+ $$PWD/qqmljsastdumper.cpp
diff --git a/tests/auto/shared/qqmljsastdumper.cpp b/tests/auto/shared/qqmljsastdumper.cpp
new file mode 100644
index 0000000000..5da6be6bd0
--- /dev/null
+++ b/tests/auto/shared/qqmljsastdumper.cpp
@@ -0,0 +1,1079 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**/
+#include "qqmljsastdumper.h"
+#include <private/qqmljsast_p.h>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+#include <QtCore/QTextStream>
+
+QT_BEGIN_NAMESPACE
+
+namespace QQmlJS {
+using namespace AST;
+/*!
+\internal
+\enum QQmlJS::DumperOptions
+
+This enum type specifies the options for the AstDumper.
+The values can be combined with the '|' operator, and checked using the '&' operator.
+
+\value None
+ Default dumping options
+\value NoLocations
+ Does not dump SourceLocations, allowing one to compare equivalent AST
+ generated by code formatted differently
+\value NoAnnotations
+ Does not dump annotations
+\value DumpNode
+ Does dump a <Node></Node> in preVisit/postVisit
+*/
+
+/*!
+\internal
+\class QQmlJS::AstDumper
+\brief Dumps or compares AST in an xml like format, mostly for testing/debugging
+
+Initialize it with a lambda that dumps a string, and configure it with .setX methods.
+If \l{indent} is set to a non zero value the xml is indented by that amount, and
+\l{baseIndent} is the initial indent.
+If \l{emitNode} is true the node tag is emitted in the preVisit/postVisit.
+If \l{emitLocation} is true the SourceLocations are emitted.
+If \l{emitAnnotations} is true annotations are emitted
+
+The implementation has unnecessary roundtrips to QString, but it is supposed to be used
+for debugging purposes...
+
+Probably you will not use the visitor at all but rather the static method diff or
+the qDebug() and ostream operator << that use the visitor...
+
+\fn AstDumper::diff(AST::Node *n1, AST::Node *n2, int nContext, DumperOptions opt, int indent)
+
+\brief compares the two AST::Node n1 and n2 and returns a string describing their first difference
+
+If there are no differences the empty string is returned, so .isEmpty() can be use to check
+for no differences.
+\l{nContext} decides how much context is printed out.
+
+*/
+
+
+QDebug operator<<(QDebug d, AST::Node *n) {
+ QDebug noQuote = d.noquote().nospace();
+ AstDumper visitor([&noQuote](const QString &s){ noQuote << s; });
+ Node::accept(n, &visitor);
+ return d;
+}
+
+
+std::ostream &operator<<(std::ostream &stream, AST::Node *n) {
+ AstDumper visitor([&stream](const QString &s){ stream << s.toStdString(); });
+ Node::accept(n, &visitor);
+ return stream;
+}
+
+bool operator & (DumperOptions lhs, DumperOptions rhs) {
+ return bool(static_cast<int>(lhs) & static_cast<int>(rhs));
+}
+
+DumperOptions operator | (DumperOptions lhs, DumperOptions rhs) {
+ return DumperOptions(static_cast<int>(lhs) | static_cast<int>(rhs));
+}
+
+QString AstDumper::diff(AST::Node *n1, AST::Node *n2, int nContext, DumperOptions opt, int indent) {
+ QString s1, s2;
+ QTextStream d1(&s1), d2(&s2);
+ AstDumper visitor1=AstDumper([&d1](const QString &s){ d1 << s; }, opt, indent);
+ AstDumper visitor2=AstDumper([&d2](const QString &s){ d2 << s; }, opt, indent);
+ Node::accept(n1, &visitor1);
+ Node::accept(n2, &visitor2);
+ d1.seek(0);
+ d2.seek(0);
+ std::vector<QString> preLines(nContext);
+ int nLine = 0;
+ bool same = true;
+ QString l1, l2;
+ while (same && !d1.atEnd() && !d2.atEnd()) {
+ l1=d1.readLine();
+ l2=d2.readLine();
+ if (l1 == l2)
+ preLines[nLine++ % nContext] = l1;
+ else
+ same = false;
+ }
+ QString res;
+ QTextStream ss(&res);
+ if (!same || !d1.atEnd() || !d2.atEnd()) {
+ for (int iline = qMin(nLine, nContext); iline > 0; --iline) {
+ ss << QLatin1String(" ") << preLines[(nLine - iline) % nContext] << QLatin1String("\n");
+ }
+ int iline = 0;
+ if (!same) {
+ ss << QLatin1String("-") << l1 << QLatin1String("\n");
+ ++iline;
+ }
+ if (same && nContext == 0)
+ nContext = 1;
+ for (;iline < nContext && !d1.atEnd(); iline ++) {
+ l1 = d1.readLine();
+ ss << QLatin1String("-") << l1 << QLatin1String("\n");
+ }
+ iline = 0;
+ if (!same) {
+ ss << QLatin1String("+") << l2 << QLatin1String("\n");
+ ++iline;
+ }
+ for (;iline < nContext && !d2.atEnd(); iline ++) {
+ l2 = d2.readLine();
+ ss << QLatin1String("+") << l2 << QLatin1String("\n");
+ }
+ }
+ return res;
+}
+
+QString AstDumper::printNode(Node *n, DumperOptions opt, int indent, int baseIndent)
+{
+ QString res;
+ QTextStream d(&res);
+ AstDumper visitor=AstDumper([&d](const QString &s){ d << s; }, opt, indent, baseIndent);
+ Node::accept(n, &visitor);
+ return res;
+}
+
+AstDumper::AstDumper(const std::function<void(const QString &)> &dumper, DumperOptions options, int indent, int baseIndent):
+ dumper(dumper), options(options), indent(indent), baseIndent(baseIndent) {}
+
+void AstDumper::start(const QString &str) {
+ dumper(QString::fromLatin1(" ").repeated(baseIndent));
+ dumper(QLatin1String("<"));
+ dumper(str);
+ dumper(QLatin1String(">\n"));
+ baseIndent += indent;
+}
+
+void AstDumper::start(const char *str) {
+ start(QLatin1String(str));
+}
+
+void AstDumper::stop(const QString &str) {
+ baseIndent -= indent;
+ dumper(QString::fromLatin1(" ").repeated(baseIndent));
+ dumper(QLatin1String("</"));
+ dumper(str);
+ dumper(QLatin1String(">\n"));
+}
+
+void AstDumper::stop(const char *str) {
+ stop(QLatin1String(str));
+}
+
+QString AstDumper::qs(const QString &s) {
+ QString res(s);
+ return QLatin1String("\"") + res
+ .replace(QLatin1String("\\"), QLatin1String("\\\\"))
+ .replace(QLatin1String("\""), QLatin1String("\\\"")) + QLatin1String("\"");
+}
+
+QString AstDumper::qs(const char *s) {
+ return qs(QLatin1String(s));
+}
+
+QString AstDumper::qs(const QStringRef &s) {
+ return qs(s.toString());
+}
+
+QString AstDumper::loc(const SourceLocation &s) {
+ if (noLocations() || !s.isValid())
+ return QLatin1String("\"\"");
+ else {
+ return QLatin1String("\"off:%1 len:%2 l:%3 c:%4\"").arg(QString::number(s.offset), QString::number(s.length), QString::number(s.startLine), QString::number(s.startColumn));
+ }
+}
+
+QString AstDumper::boolStr(bool v) { return (v ? qs("true"): qs("false")); }
+
+bool AstDumper::preVisit(Node *) { if (dumpNode()) start("Node"); return true; }
+
+void AstDumper::postVisit(Node *) { if (dumpNode()) stop("Node"); }
+
+bool AstDumper::visit(UiProgram *) { start("UiProgram"); return true; }
+
+bool AstDumper::visit(UiHeaderItemList *) { start("UiHeaderItemList"); return true; }
+
+bool AstDumper::visit(UiPragma *el) {
+ start(QLatin1String("UiPragma name=%1 pragmaToken=%2 semicolonToken=%3")
+ .arg(qs(el->name), loc(el->pragmaToken), loc(el->semicolonToken)));
+ return true;
+}
+
+bool AstDumper::visit(UiImport *el)
+{
+ start(QLatin1String("UiImport fileName=%1 importId=%2 importToken=%3 fileNameToken=%4 asToken=%5 importIdToken=%6 semicolonToken=%7")
+ .arg(qs(el->fileName), qs(el->importId), loc(el->importToken), loc(el->fileNameToken), loc(el->asToken), loc(el->importIdToken), loc(el->semicolonToken)));
+ return true;
+}
+
+bool AstDumper::visit(UiPublicMember *el) {
+ QString typeStr = ((el->type == UiPublicMember::Signal) ? QLatin1String("Signal") :
+ (el->type == UiPublicMember::Property) ? QLatin1String("Property") : QLatin1String("Unexpected(%1)").arg(el->type));
+ start(QLatin1String("UiPublicMember type=%1 typeModifier=%2 name=%3 isDefaultMember=%4 isReadonlyMember=%5 isRequired=%6 "
+ "defaultToken=%7 readonlyToken=%8 propertyToken=%9 requiredToken=%10 typeModifierToken=%11 typeToken=%12 "
+ "identifierToken=%13 colonToken=%14 semicolonToken=%15")
+ .arg(qs(typeStr), qs(el->typeModifier), qs(el->name),
+ el->isDefaultMember, el->isReadonlyMember, el->isRequired,
+ loc(el->defaultToken), loc(el->readonlyToken), loc(el->propertyToken),
+ loc(el->requiredToken), loc(el->typeModifierToken), loc(el->typeToken),
+ loc(el->identifierToken), loc(el->colonToken), loc(el->semicolonToken)
+ ));
+ if (!noAnnotations()) // put annotations inside the node they refer to
+ Node::accept(el->annotations, this);
+ Node::accept(el->memberType, this);
+ return true;
+}
+
+bool AstDumper::visit(AST::UiSourceElement *el) {
+ start(QLatin1String("UiSourceElement"));
+ if (!noAnnotations()) // put annotations inside the node they refer to
+ Node::accept(el->annotations, this);
+ return true;
+}
+
+bool AstDumper::visit(AST::UiObjectDefinition *el) {
+ start("UiObjectDefinition");
+ if (!noAnnotations()) // put annotations inside the node they refer to
+ Node::accept(el->annotations, this);
+ return true;
+}
+
+bool AstDumper::visit(AST::UiObjectInitializer *el) {
+ start(QLatin1String("UiObjectInitializer lbraceToken=%1 rbraceToken=%2")
+ .arg(loc(el->lbraceToken), loc(el->rbraceToken)));
+ return true;
+}
+
+bool AstDumper::visit(AST::UiObjectBinding *el) {
+ start(QLatin1String("UiObjectBinding colonToken=%1 hasOnToken=%2")
+ .arg(loc(el->colonToken), boolStr(el->hasOnToken)));
+ if (!noAnnotations()) // put annotations inside the node they refer to
+ Node::accept(el->annotations, this);
+ return true;
+}
+
+bool AstDumper::visit(AST::UiScriptBinding *el) {
+ start(QLatin1String("UiScriptBinding colonToken=%1")
+ .arg(loc(el->colonToken)));
+ if (!noAnnotations()) // put annotations inside the node they refer to
+ Node::accept(el->annotations, this);
+ return true;
+}
+
+bool AstDumper::visit(AST::UiArrayBinding *el) {
+ start(QLatin1String("UiArrayBinding colonToken=%1 lbracketToken=%2 rbracketToken=%3")
+ .arg(loc(el->colonToken), loc(el->lbracketToken), loc(el->rbracketToken)));
+ if (!noAnnotations()) // put annotations inside the node they refer to
+ Node::accept(el->annotations, this);
+ return true;
+}
+
+bool AstDumper::visit(AST::UiParameterList *el) {
+ start(QLatin1String("UiArrayBinding name=%1 commaToken=%2 propertyTypeToken=%3 identifierToken=%4 colonToken=%5")
+ .arg(qs(el->name), loc(el->commaToken), loc(el->propertyTypeToken), loc(el->identifierToken), loc(el->colonToken)));
+ Node::accept(el->type, this);
+ return true;
+}
+
+bool AstDumper::visit(AST::UiObjectMemberList *) { start("UiObjectMemberList"); return true; }
+
+bool AstDumper::visit(AST::UiArrayMemberList *el) {
+ start(QLatin1String("UiArrayMemberList commaToken=%1")
+ .arg(loc(el->commaToken)));
+ return true;
+}
+
+bool AstDumper::visit(AST::UiQualifiedId *el) {
+ start(QLatin1String("UiQualifiedId name=%1 identifierToken=%2")
+ .arg(qs(el->name), loc(el->identifierToken)));
+ Node::accept(el->next, this);
+ return true;
+}
+
+bool AstDumper::visit(AST::UiEnumDeclaration *el) {
+ start(QLatin1String("UiEnumDeclaration enumToken=%1 rbraceToken=%2 name=%3")
+ .arg(loc(el->enumToken), loc(el->rbraceToken), qs(el->name)));
+ if (!noAnnotations()) // put annotations inside the node they refer to
+ Node::accept(el->annotations, this);
+ return true;
+}
+
+bool AstDumper::visit(AST::UiEnumMemberList *el) {
+ start(QLatin1String("UiEnumMemberList member=%1 value=%2 memberToken=%3 valueToken=%4")
+ .arg(qs(el->member), qs(QString::number(el->value)), loc(el->memberToken), loc(el->valueToken)));
+ return true;
+}
+
+bool AstDumper::visit(AST::UiVersionSpecifier *el) {
+ start(QLatin1String("UiVersionSpecifier majorVersion=%1 minorVersion=%2 majorToken=%3 minorToken=%4")
+ .arg(qs(QString::number(el->majorVersion)), qs(QString::number(el->minorVersion)), loc(el->majorToken), loc(el->minorToken)));
+ return true;
+}
+
+bool AstDumper::visit(AST::UiInlineComponent *el) {
+ start(QLatin1String("UiInlineComponent name=%1 componentToken=%2")
+ .arg(qs(el->name), loc(el->componentToken)));
+ if (!noAnnotations()) // put annotations inside the node they refer to
+ Node::accept(el->annotations, this);
+ return true;
+}
+
+bool AstDumper::visit(UiRequired *el)
+{
+ start(QLatin1String("UiRequired name=%1 requiredToken=%2 semicolonToken=%3")
+ .arg(qs(el->name), loc(el->requiredToken), loc(el->semicolonToken)));
+ return true;
+}
+
+bool AstDumper::visit(UiAnnotation *)
+{
+ start(QLatin1String("UiAnnotation"));
+ return true;
+}
+
+bool AstDumper::visit(UiAnnotationList *)
+{
+ start(QLatin1String("UiAnnotationList"));
+ return true;
+}
+
+void AstDumper::endVisit(AST::UiProgram *) { stop("UiProgram"); }
+
+void AstDumper::endVisit(AST::UiImport *el) {
+ Node::accept(el->version, this);
+ stop("UiImport");
+}
+
+void AstDumper::endVisit(AST::UiHeaderItemList *) { stop("UiHeaderItemList"); }
+
+void AstDumper::endVisit(AST::UiPragma *) { stop("UiPragma"); }
+
+void AstDumper::endVisit(AST::UiPublicMember *el) {
+ Node::accept(el->parameters, this);
+ stop("UiPublicMember");
+}
+
+void AstDumper::endVisit(AST::UiSourceElement *) { stop("UiSourceElement"); }
+void AstDumper::endVisit(AST::UiObjectDefinition *) { stop("UiObjectDefinition"); }
+void AstDumper::endVisit(AST::UiObjectInitializer *) { stop("UiObjectInitializer"); }
+void AstDumper::endVisit(AST::UiObjectBinding *) { stop("UiObjectBinding"); }
+void AstDumper::endVisit(AST::UiScriptBinding *) { stop("UiScriptBinding"); }
+void AstDumper::endVisit(AST::UiArrayBinding *) { stop("UiArrayBinding"); }
+void AstDumper::endVisit(AST::UiParameterList *el) {
+ stop("UiParameterList");
+ Node::accept(el->next, this); // put other args at the same level as this one...
+}
+void AstDumper::endVisit(AST::UiObjectMemberList *) { stop("UiObjectMemberList"); }
+void AstDumper::endVisit(AST::UiArrayMemberList *) { stop("UiArrayMemberList"); }
+void AstDumper::endVisit(AST::UiQualifiedId *) { stop("UiQualifiedId"); }
+void AstDumper::endVisit(AST::UiEnumDeclaration *) { stop("UiEnumDeclaration"); }
+void AstDumper::endVisit(AST::UiEnumMemberList *el) {
+ stop("UiEnumMemberList");
+ Node::accept(el->next, this); // put other enum members at the same level as this one...
+}
+void AstDumper::endVisit(AST::UiVersionSpecifier *) { stop("UiVersionSpecifier"); }
+void AstDumper::endVisit(AST::UiInlineComponent *) { stop("UiInlineComponent"); }
+void AstDumper::endVisit(UiRequired *) { stop("UiRequired"); }
+void AstDumper::endVisit(UiAnnotation *) { stop("UiAnnotation"); }
+void AstDumper::endVisit(UiAnnotationList *) { stop("UiAnnotationList"); }
+
+// QQmlJS
+bool AstDumper::visit(AST::ThisExpression *el) {
+ start(QLatin1String("ThisExpression thisToken=%1")
+ .arg(loc(el->thisToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::ThisExpression *) { stop("ThisExpression"); }
+
+bool AstDumper::visit(AST::IdentifierExpression *el) {
+ start(QLatin1String("IdentifierExpression name=%1 identiferToken=%2")
+ .arg(qs(el->name), loc(el->identifierToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::IdentifierExpression *) { stop("IdentifierExpression"); }
+
+bool AstDumper::visit(AST::NullExpression *el) {
+ start(QLatin1String("NullExpression nullToken=%1")
+ .arg(loc(el->nullToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::NullExpression *) { stop("NullExpression"); }
+
+bool AstDumper::visit(AST::TrueLiteral *el) {
+ start(QLatin1String("TrueLiteral trueToken=%1")
+ .arg(loc(el->trueToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::TrueLiteral *) { stop("TrueLiteral"); }
+
+bool AstDumper::visit(AST::FalseLiteral *el) {
+ start(QLatin1String("FalseLiteral falseToken=%1")
+ .arg(loc(el->falseToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::FalseLiteral *) { stop("FalseLiteral"); }
+
+bool AstDumper::visit(AST::SuperLiteral *el) {
+ start(QLatin1String("SuperLiteral superToken=%1")
+ .arg(loc(el->superToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::SuperLiteral *) { stop("SuperLiteral"); }
+
+bool AstDumper::visit(AST::StringLiteral *el) {
+ start(QLatin1String("StringLiteral value=%1 literalToken=%2")
+ .arg(qs(el->value), loc(el->literalToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::StringLiteral *) { stop("StringLiteral"); }
+
+bool AstDumper::visit(AST::TemplateLiteral *el) {
+ start(QLatin1String("TemplateLiteral value=%1 rawValue=%2 literalToken=%3")
+ .arg(qs(el->value), qs(el->rawValue), loc(el->literalToken)));
+ Node::accept(el->expression, this);
+ return true;
+}
+void AstDumper::endVisit(AST::TemplateLiteral *) { stop("TemplateLiteral"); }
+
+bool AstDumper::visit(AST::NumericLiteral *el) {
+ start(QLatin1String("NumericLiteral value=%1 literalToken=%2")
+ .arg(qs(QString::number(el->value)), loc(el->literalToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::NumericLiteral *) { stop("NumericLiteral"); }
+
+bool AstDumper::visit(AST::RegExpLiteral *el) {
+ start(QLatin1String("RegExpLiteral pattern=%1 flags=%2 literalToken=%3")
+ .arg(qs(el->pattern), qs(QString::number(el->flags, 16)), loc(el->literalToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::RegExpLiteral *) { stop("RegExpLiteral"); }
+
+bool AstDumper::visit(AST::ArrayPattern *el) {
+ start(QLatin1String("ArrayPattern lbracketToken=%1, commaToken=%2, rbracketToken=%3 parseMode=%4")
+ .arg(loc(el->lbracketToken),loc(el->commaToken),loc(el->rbracketToken), qs(QString::number(el->parseMode, 16))));
+ return true;
+}
+void AstDumper::endVisit(AST::ArrayPattern *) { stop("ArrayPattern"); }
+
+bool AstDumper::visit(AST::ObjectPattern *el) {
+ start(QLatin1String("ObjectPattern lbraceToken=%1 rbraceToken=%2 parseMode=%3")
+ .arg(loc(el->lbraceToken), loc(el->rbraceToken), qs(QString::number(el->parseMode, 16))));
+ return true;
+}
+void AstDumper::endVisit(AST::ObjectPattern *) { stop("ObjectPattern"); }
+
+bool AstDumper::visit(AST::PatternElementList *) { start("PatternElementList"); return true; }
+void AstDumper::endVisit(AST::PatternElementList *) { stop("PatternElementList"); }
+
+bool AstDumper::visit(AST::PatternPropertyList *) { start("PatternPropertyList"); return true; }
+void AstDumper::endVisit(AST::PatternPropertyList *) { stop("PatternPropertyList"); }
+
+bool AstDumper::visit(AST::PatternElement *el) {
+ start(QLatin1String("PatternElement identifierToken=%1 bindingIdentifier=%2 type=%3 scope=%4 isForDeclaration=%5")
+ .arg(loc(el->identifierToken), qs(el->bindingIdentifier), qs(QString::number(el->type, 16)),
+ qs(QString::number(static_cast<int>(el->scope), 16)), boolStr(el->isForDeclaration)));
+ return true;
+}
+void AstDumper::endVisit(AST::PatternElement *) { stop("PatternElement"); }
+
+bool AstDumper::visit(AST::PatternProperty *el) {
+ start(QLatin1String("PatternProperty identifierToken=%1 bindingIdentifier=%2 type=%3 scope=%4 isForDeclaration=%5 colonToken=%6")
+ .arg(loc(el->identifierToken), qs(el->bindingIdentifier), qs(QString::number(el->type, 16)),
+ qs(QString::number(static_cast<int>(el->scope), 16)), boolStr(el->isForDeclaration), loc(el->colonToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::PatternProperty *) { stop("PatternProperty"); }
+
+bool AstDumper::visit(AST::Elision *el) {
+ start(QLatin1String("Elision commaToken=%1")
+ .arg(loc(el->commaToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::Elision *el) {
+ stop("Elision");
+ Node::accept(el->next, this); // emit other elisions at the same level
+}
+
+bool AstDumper::visit(AST::NestedExpression *el) {
+ start(QLatin1String("NestedExpression lparenToken=%1 rparenToken=%2")
+ .arg(loc(el->lparenToken), loc(el->rparenToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::NestedExpression *) { stop("NestedExpression"); }
+
+bool AstDumper::visit(AST::IdentifierPropertyName *el) {
+ start(QLatin1String("IdentifierPropertyName id=%1 propertyNameToken=%2")
+ .arg(qs(el->id), loc(el->propertyNameToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::IdentifierPropertyName *) { stop("IdentifierPropertyName"); }
+
+bool AstDumper::visit(AST::StringLiteralPropertyName *el) {
+ start(QLatin1String("StringLiteralPropertyName id=%1 propertyNameToken=%2")
+ .arg(qs(el->id), loc(el->propertyNameToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::StringLiteralPropertyName *) { stop("StringLiteralPropertyName"); }
+
+bool AstDumper::visit(AST::NumericLiteralPropertyName *el) {
+ start(QLatin1String("NumericLiteralPropertyName id=%1 propertyNameToken=%2")
+ .arg(qs(QString::number(el->id)),loc(el->propertyNameToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::NumericLiteralPropertyName *) { stop("NumericLiteralPropertyName"); }
+
+bool AstDumper::visit(AST::ComputedPropertyName *) {
+ start(QLatin1String("ComputedPropertyName"));
+ return true;
+}
+void AstDumper::endVisit(AST::ComputedPropertyName *) { stop("ComputedPropertyName"); }
+
+bool AstDumper::visit(AST::ArrayMemberExpression *el) {
+ start(QLatin1String("ArrayMemberExpression lbraketToken=%1 rbraketToken=%2")
+ .arg(loc(el->lbracketToken), loc(el->rbracketToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::ArrayMemberExpression *) { stop("ArrayMemberExpression"); }
+
+bool AstDumper::visit(AST::FieldMemberExpression *el) {
+ start(QLatin1String("FieldMemberExpression name=%1 dotToken=%2 identifierToken=%3")
+ .arg(qs(el->name), loc(el->dotToken), loc(el->identifierToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::FieldMemberExpression *) { stop("FieldMemberExpression"); }
+
+bool AstDumper::visit(AST::TaggedTemplate *) {
+ start(QLatin1String("TaggedTemplate"));
+ return true;
+}
+void AstDumper::endVisit(AST::TaggedTemplate *) { stop("TaggedTemplate"); }
+
+bool AstDumper::visit(AST::NewMemberExpression *el) {
+ start(QLatin1String("NewMemberExpression newToken=%1 lparenToken=%2 rparenToken=%3")
+ .arg(loc(el->newToken), loc(el->lparenToken), loc(el->rparenToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::NewMemberExpression *) { stop("NewMemberExpression"); }
+
+bool AstDumper::visit(AST::NewExpression *el) {
+ start(QLatin1String("NewExpression newToken=%1")
+ .arg(loc(el->newToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::NewExpression *) { stop("NewExpression"); }
+
+bool AstDumper::visit(AST::CallExpression *el) {
+ start(QLatin1String("CallExpression lparenToken=%1 rparenToken=%2")
+ .arg(loc(el->lparenToken), loc(el->rparenToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::CallExpression *) { stop("CallExpression"); }
+
+bool AstDumper::visit(AST::ArgumentList *el) {
+ start(QLatin1String("ArgumentList commaToken=%1 isSpreadElement=%2")
+ .arg(loc(el->commaToken), boolStr(el->isSpreadElement)));
+ return true;
+}
+void AstDumper::endVisit(AST::ArgumentList *) { stop("ArgumentList"); }
+
+bool AstDumper::visit(AST::PostIncrementExpression *el) {
+ start(QLatin1String("PostIncrementExpression incrementToken=%1")
+ .arg(loc(el->incrementToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::PostIncrementExpression *) { stop("PostIncrementExpression"); }
+
+bool AstDumper::visit(AST::PostDecrementExpression *el) {
+ start(QLatin1String("PostDecrementExpression decrementToken=%1")
+ .arg(loc(el->decrementToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::PostDecrementExpression *) { stop("PostDecrementExpression"); }
+
+bool AstDumper::visit(AST::DeleteExpression *el) {
+ start(QLatin1String("DeleteExpression deleteToken=%1")
+ .arg(loc(el->deleteToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::DeleteExpression *) { stop("DeleteExpression"); }
+
+bool AstDumper::visit(AST::VoidExpression *el) {
+ start(QLatin1String("VoidExpression voidToken=%1")
+ .arg(loc(el->voidToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::VoidExpression *) { stop("VoidExpression"); }
+
+bool AstDumper::visit(AST::TypeOfExpression *el) {
+ start(QLatin1String("TypeOfExpression typeofToken=%1")
+ .arg(loc(el->typeofToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::TypeOfExpression *) { stop("TypeOfExpression"); }
+
+bool AstDumper::visit(AST::PreIncrementExpression *el) {
+ start(QLatin1String("PreIncrementExpression incrementToken=%1")
+ .arg(loc(el->incrementToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::PreIncrementExpression *) { stop("PreIncrementExpression"); }
+
+bool AstDumper::visit(AST::PreDecrementExpression *el) {
+ start(QLatin1String("PreDecrementExpression decrementToken=%1")
+ .arg(loc(el->decrementToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::PreDecrementExpression *) { stop("PreDecrementExpression"); }
+
+bool AstDumper::visit(AST::UnaryPlusExpression *el) {
+ start(QLatin1String("UnaryPlusExpression plusToken=%1")
+ .arg(loc(el->plusToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::UnaryPlusExpression *) { stop("UnaryPlusExpression"); }
+
+bool AstDumper::visit(AST::UnaryMinusExpression *el) {
+ start(QLatin1String("UnaryMinusExpression minusToken=%1")
+ .arg(loc(el->minusToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::UnaryMinusExpression *) { stop("UnaryMinusExpression"); }
+
+bool AstDumper::visit(AST::TildeExpression *el) {
+ start(QLatin1String("TildeExpression tildeToken=%1")
+ .arg(loc(el->tildeToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::TildeExpression *) { stop("TildeExpression"); }
+
+bool AstDumper::visit(AST::NotExpression *el) {
+ start(QLatin1String("NotExpression notToken=%1")
+ .arg(loc(el->notToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::NotExpression *) { stop("NotExpression"); }
+
+bool AstDumper::visit(AST::BinaryExpression *el) {
+ start(QLatin1String("BinaryExpression op=%1 operatorToken=%2")
+ .arg(qs(QString::number(el->op,16)), loc(el->operatorToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::BinaryExpression *) { stop("BinaryExpression"); }
+
+bool AstDumper::visit(AST::ConditionalExpression *el) {
+ start(QLatin1String("ConditionalExpression questionToken=%1 colonToken=%2")
+ .arg(loc(el->questionToken), loc(el->colonToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::ConditionalExpression *) { stop("ConditionalExpression"); }
+
+bool AstDumper::visit(AST::Expression *el) {
+ start(QLatin1String("Expression commaToken=%1")
+ .arg(loc(el->commaToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::Expression *) { stop("Expression"); }
+
+bool AstDumper::visit(AST::Block *el) {
+ start(QLatin1String("Block lbraceToken=%1 rbraceToken=%2")
+ .arg(loc(el->lbraceToken), loc(el->rbraceToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::Block *) { stop("Block"); }
+
+bool AstDumper::visit(AST::StatementList *) {
+ start(QLatin1String("StatementList"));
+ return true;
+}
+void AstDumper::endVisit(AST::StatementList *) { stop("StatementList"); }
+
+bool AstDumper::visit(AST::VariableStatement *el) {
+ start(QLatin1String("VariableStatement declarationKindToken=%1")
+ .arg(loc(el->declarationKindToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::VariableStatement *) { stop("VariableStatement"); }
+
+bool AstDumper::visit(AST::VariableDeclarationList *el) {
+ start(QLatin1String("VariableDeclarationList commaToken=%1")
+ .arg(loc(el->commaToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::VariableDeclarationList *) { stop("VariableDeclarationList"); }
+
+bool AstDumper::visit(AST::EmptyStatement *el) {
+ start(QLatin1String("EmptyStatement semicolonToken=%1")
+ .arg(loc(el->semicolonToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::EmptyStatement *) { stop("EmptyStatement"); }
+
+bool AstDumper::visit(AST::ExpressionStatement *el) {
+ start(QLatin1String("ExpressionStatement semicolonToken=%1")
+ .arg(loc(el->semicolonToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::ExpressionStatement *) { stop("ExpressionStatement"); }
+
+bool AstDumper::visit(AST::IfStatement *el) {
+ start(QLatin1String("IfStatement ifToken=%1 lparenToken=%2 rparenToken=%3 elseToken=%4")
+ .arg(loc(el->ifToken), loc(el->lparenToken), loc(el->rparenToken), loc(el->elseToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::IfStatement *) { stop("IfStatement"); }
+
+bool AstDumper::visit(AST::DoWhileStatement *el) {
+ start(QLatin1String("DoWhileStatement doToken=%1 whileToken=%2 lparenToken=%3 rparenToken=%4 semicolonToken=%5")
+ .arg(loc(el->doToken), loc(el->whileToken), loc(el->lparenToken), loc(el->rparenToken), loc(el->semicolonToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::DoWhileStatement *) { stop("DoWhileStatement"); }
+
+bool AstDumper::visit(AST::WhileStatement *el) {
+ start(QLatin1String("WhileStatement whileToken=%1 lparenToken=%2 rparenToken=%3")
+ .arg(loc(el->whileToken), loc(el->lparenToken), loc(el->rparenToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::WhileStatement *) { stop("WhileStatement"); }
+
+bool AstDumper::visit(AST::ForStatement *el) {
+ start(QLatin1String("ForStatement forToken=%1 lparenToken=%2 firstSemicolonToken=%3 secondSemicolonToken=%4 rparenToken=%5")
+ .arg(loc(el->forToken), loc(el->lparenToken), loc(el->firstSemicolonToken), loc(el->secondSemicolonToken), loc(el->rparenToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::ForStatement *) { stop("ForStatement"); }
+
+bool AstDumper::visit(AST::ForEachStatement *el) {
+ start(QLatin1String("ForEachStatement forToken=%1 lparenToken=%2 inOfToken=%3 rparenToken=%4 type=%5")
+ .arg(loc(el->forToken), loc(el->lparenToken), loc(el->inOfToken), loc(el->rparenToken), qs(QString::number(static_cast<int>(el->type), 16))));
+ return true;
+}
+void AstDumper::endVisit(AST::ForEachStatement *) { stop("ForEachStatement"); }
+
+bool AstDumper::visit(AST::ContinueStatement *el) {
+ start(QLatin1String("ContinueStatement label=%1 continueToken=%2 identifierToken=%3 semicolonToken=%4")
+ .arg(qs(el->label), loc(el->continueToken), loc(el->identifierToken), loc(el->semicolonToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::ContinueStatement *) { stop("ContinueStatement"); }
+
+bool AstDumper::visit(AST::BreakStatement *el) {
+ start(QLatin1String("BreakStatement label=%1 breakToken=%2 identifierToken=%3 semicolonToken=%4")
+ .arg(qs(el->label), loc(el->breakToken), loc(el->identifierToken), loc(el->semicolonToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::BreakStatement *) { stop("BreakStatement"); }
+
+bool AstDumper::visit(AST::ReturnStatement *el) {
+ start(QLatin1String("ReturnStatement returnToken=%1 semicolonToken=%2")
+ .arg(loc(el->returnToken), loc(el->semicolonToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::ReturnStatement *) { stop("ReturnStatement"); }
+
+bool AstDumper::visit(AST::YieldExpression *el) {
+ start(QLatin1String("YieldExpression isYieldStar=%1 yieldToken=%2")
+ .arg(boolStr(el->isYieldStar), loc(el->yieldToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::YieldExpression *) { stop("YieldExpression"); }
+
+bool AstDumper::visit(AST::WithStatement *el) {
+ start(QLatin1String("WithStatement withToken=%1 lparenToken=%2 rparenToken=%3")
+ .arg(loc(el->withToken), loc(el->lparenToken), loc(el->rparenToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::WithStatement *) { stop("WithStatement"); }
+
+bool AstDumper::visit(AST::SwitchStatement *el) {
+ start(QLatin1String("SwitchStatement switchToken=%1 lparenToken=%2 rparenToken=%3")
+ .arg(loc(el->switchToken), loc(el->lparenToken), loc(el->rparenToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::SwitchStatement *) { stop("SwitchStatement"); }
+
+bool AstDumper::visit(AST::CaseBlock *el) {
+ start(QLatin1String("CaseBlock lbraceToken=%1 rbraceToken=%2")
+ .arg(loc(el->lbraceToken), loc(el->rbraceToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::CaseBlock *) { stop("CaseBlock"); }
+
+bool AstDumper::visit(AST::CaseClauses *) {
+ start(QLatin1String("CaseClauses"));
+ return true;
+}
+void AstDumper::endVisit(AST::CaseClauses *) { stop("CaseClauses"); }
+
+bool AstDumper::visit(AST::CaseClause *el) {
+ start(QLatin1String("CaseClause caseToken=%1 colonToken=%2")
+ .arg(loc(el->caseToken), loc(el->colonToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::CaseClause *) { stop("CaseClause"); }
+
+bool AstDumper::visit(AST::DefaultClause *el) {
+ start(QLatin1String("DefaultClause defaultToken=%1 colonToken=%2")
+ .arg(loc(el->defaultToken), loc(el->colonToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::DefaultClause *) { stop("DefaultClause"); }
+
+bool AstDumper::visit(AST::LabelledStatement *el) {
+ start(QLatin1String("LabelledStatement label=%1 identifierToken=%2 colonToken=%3")
+ .arg(qs(el->label), loc(el->identifierToken), loc(el->colonToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::LabelledStatement *) { stop("LabelledStatement"); }
+
+bool AstDumper::visit(AST::ThrowStatement *el) {
+ start(QLatin1String("ThrowStatement throwToken=%1 semicolonToken=%2")
+ .arg(loc(el->throwToken), loc(el->semicolonToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::ThrowStatement *) { stop("ThrowStatement"); }
+
+bool AstDumper::visit(AST::TryStatement *el) {
+ start(QLatin1String("TryStatement tryToken=%1")
+ .arg(loc(el->tryToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::TryStatement *) { stop("TryStatement"); }
+
+bool AstDumper::visit(AST::Catch *el) {
+ start(QLatin1String("Catch catchToken=%1 lparenToken=%2 identifierToken=%3 rparenToken=%4")
+ .arg(loc(el->catchToken), loc(el->lparenToken), loc(el->identifierToken), loc(el->rparenToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::Catch *) { stop("Catch"); }
+
+bool AstDumper::visit(AST::Finally *el) {
+ start(QLatin1String("Finally finallyToken=%1")
+ .arg(loc(el->finallyToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::Finally *) { stop("Finally"); }
+
+bool AstDumper::visit(AST::FunctionDeclaration *el) {
+ start(QLatin1String("FunctionDeclaration name=%1 isArrowFunction=%2 isGenerator=%3 functionToken=%4 "
+ "identifierToken=%5 lparenToken=%6 rparenToken=%7 lbraceToken=%8 rbraceToken=%9")
+ .arg(qs(el->name), boolStr(el->isArrowFunction), boolStr(el->isGenerator), loc(el->functionToken),
+ loc(el->identifierToken), loc(el->lparenToken), loc(el->rparenToken), loc(el->lbraceToken),
+ loc(el->rbraceToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::FunctionDeclaration *) { stop("FunctionDeclaration"); }
+
+bool AstDumper::visit(AST::FunctionExpression *el) {
+ start(QLatin1String("FunctionExpression name=%1 isArrowFunction=%2 isGenerator=%3 functionToken=%4 "
+ "identifierToken=%5 lparenToken=%6 rparenToken=%7 lbraceToken=%8 rbraceToken=%9")
+ .arg(qs(el->name), boolStr(el->isArrowFunction), boolStr(el->isGenerator), loc(el->functionToken),
+ loc(el->identifierToken), loc(el->lparenToken), loc(el->rparenToken), loc(el->lbraceToken),
+ loc(el->rbraceToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::FunctionExpression *) { stop("FunctionExpression"); }
+
+bool AstDumper::visit(AST::FormalParameterList *) {
+ start(QLatin1String("FormalParameterList"));
+ return true;
+}
+void AstDumper::endVisit(AST::FormalParameterList *) { stop("FormalParameterList"); }
+
+bool AstDumper::visit(AST::ClassExpression *el) {
+ start(QLatin1String("ClassExpression name=%1 classToken=%2 identifierToken=%3 lbraceToken=%4 rbraceToken=%5")
+ .arg(qs(el->name), loc(el->classToken), loc(el->identifierToken), loc(el->lbraceToken), loc(el->rbraceToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::ClassExpression *) { stop("ClassExpression"); }
+
+bool AstDumper::visit(AST::ClassDeclaration *el) {
+ start(QLatin1String("ClassDeclaration name=%1 classToken=%2 identifierToken=%3 lbraceToken=%4 rbraceToken=%5")
+ .arg(qs(el->name), loc(el->classToken), loc(el->identifierToken), loc(el->lbraceToken), loc(el->rbraceToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::ClassDeclaration *) { stop("ClassDeclaration"); }
+
+bool AstDumper::visit(AST::ClassElementList *el) {
+ start(QLatin1String("ClassElementList isStatic=%1")
+ .arg(boolStr(el->isStatic)));
+ return true;
+}
+void AstDumper::endVisit(AST::ClassElementList *) { stop("ClassElementList"); }
+
+bool AstDumper::visit(AST::Program *) {
+ start(QLatin1String("Program"));
+ return true;
+}
+void AstDumper::endVisit(AST::Program *) { stop("Program"); }
+
+bool AstDumper::visit(AST::NameSpaceImport *el) {
+ start(QLatin1String("NameSpaceImport starToken=%1 importedBindingToken=%2 importedBinding=%3")
+ .arg(loc(el->starToken), loc(el->importedBindingToken), qs(el->importedBinding)));
+ return true;
+}
+void AstDumper::endVisit(AST::NameSpaceImport *) { stop("NameSpaceImport"); }
+
+bool AstDumper::visit(AST::ImportSpecifier *el) {
+ start(QLatin1String("ImportSpecifier identifierToken=%1 importedBindingToken=%2 identifier=%3 importedBinding=%4")
+ .arg(loc(el->identifierToken), loc(el->importedBindingToken), qs(el->identifier), qs(el->importedBinding)));
+ return true;
+}
+void AstDumper::endVisit(AST::ImportSpecifier *) { stop("ImportSpecifier"); }
+
+bool AstDumper::visit(AST::ImportsList *el) {
+ start(QLatin1String("ImportsList importSpecifierToken=%1")
+ .arg(loc(el->importSpecifierToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::ImportsList *) { stop("ImportsList"); }
+
+bool AstDumper::visit(AST::NamedImports *el) {
+ start(QLatin1String("NamedImports leftBraceToken=%1 rightBraceToken=%2")
+ .arg(loc(el->leftBraceToken), loc(el->rightBraceToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::NamedImports *) { stop("NamedImports"); }
+
+bool AstDumper::visit(AST::FromClause *el) {
+ start(QLatin1String("FromClause fromToken=%1 moduleSpecifierToken=%2 moduleSpecifier=%3")
+ .arg(loc(el->fromToken), loc(el->moduleSpecifierToken), qs(el->moduleSpecifier)));
+ return true;
+}
+void AstDumper::endVisit(AST::FromClause *) { stop("FromClause"); }
+
+bool AstDumper::visit(AST::ImportClause *el) {
+ start(QLatin1String("ImportClause importedDefaultBindingToken=%1 importedDefaultBinding=%2")
+ .arg(loc(el->importedDefaultBindingToken), qs(el->importedDefaultBinding)));
+ return true;
+}
+void AstDumper::endVisit(AST::ImportClause *) { stop("ImportClause"); }
+
+bool AstDumper::visit(AST::ImportDeclaration *el) {
+ start(QLatin1String("ImportDeclaration importToken=%1 moduleSpecifierToken=%2 moduleSpecifier=%3")
+ .arg(loc(el->importToken), loc(el->moduleSpecifierToken), qs(el->moduleSpecifier)));
+ return true;
+}
+void AstDumper::endVisit(AST::ImportDeclaration *) { stop("ImportDeclaration"); }
+
+bool AstDumper::visit(AST::ExportSpecifier *el) {
+ start(QLatin1String("ExportSpecifier identifierToken=%1 exportedIdentifierToken=%2 identifier=%3 exportedIdentifier=%4")
+ .arg(loc(el->identifierToken), loc(el->exportedIdentifierToken), qs(el->identifier), qs(el->exportedIdentifier)));
+ return true;
+}
+void AstDumper::endVisit(AST::ExportSpecifier *) { stop("ExportSpecifier"); }
+
+bool AstDumper::visit(AST::ExportsList *) {
+ start(QLatin1String("ExportsList"));
+ return true;
+}
+void AstDumper::endVisit(AST::ExportsList *) { stop("ExportsList"); }
+
+bool AstDumper::visit(AST::ExportClause *el) {
+ start(QLatin1String("ExportClause leftBraceToken=%1 rightBraceToken=%2")
+ .arg(loc(el->leftBraceToken), loc(el->rightBraceToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::ExportClause *) { stop("ExportClause"); }
+
+bool AstDumper::visit(AST::ExportDeclaration *el) {
+ start(QLatin1String("ExportDeclaration exportToken=%1 exportAll=%2 exportDefault=%3")
+ .arg(loc(el->exportToken), boolStr(el->exportAll), boolStr(el->exportDefault)));
+ return true;
+}
+void AstDumper::endVisit(AST::ExportDeclaration *) { stop("ExportDeclaration"); }
+
+bool AstDumper::visit(AST::ESModule *) {
+ start(QLatin1String("ESModule"));
+ return true;
+}
+void AstDumper::endVisit(AST::ESModule *) { stop("ESModule"); }
+
+bool AstDumper::visit(AST::DebuggerStatement *el) {
+ start(QLatin1String("DebuggerStatement debuggerToken=%1 semicolonToken=%2")
+ .arg(loc(el->debuggerToken), loc(el->semicolonToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::DebuggerStatement *) { stop("DebuggerStatement"); }
+
+bool AstDumper::visit(AST::Type *) {
+ start(QLatin1String("Type"));
+ return true;
+}
+void AstDumper::endVisit(AST::Type *) { stop("Type"); }
+
+bool AstDumper::visit(AST::TypeArgumentList *) {
+ start(QLatin1String("TypeArgumentList"));
+ return true;
+}
+void AstDumper::endVisit(AST::TypeArgumentList *) { stop("TypeArgumentList"); }
+
+bool AstDumper::visit(AST::TypeAnnotation *el) {
+ start(QLatin1String("TypeAnnotation colonToken=%1")
+ .arg(loc(el->colonToken)));
+ return true;
+}
+void AstDumper::endVisit(AST::TypeAnnotation *) { stop("TypeAnnotation"); }
+
+void AstDumper::throwRecursionDepthError()
+{
+ qDebug() << "Maximum statement or expression depth exceeded in AstDumper";
+}
+
+bool AstDumper::dumpNode() {
+ return options & DumperOptions::DumpNode;
+}
+
+bool AstDumper::noLocations() {
+ return options & DumperOptions::NoLocations;
+}
+
+bool AstDumper::noAnnotations() {
+ return options & DumperOptions::NoAnnotations;
+}
+
+} // end namespace QQmlJS
+
+QT_END_NAMESPACE
diff --git a/tests/auto/shared/qqmljsastdumper.h b/tests/auto/shared/qqmljsastdumper.h
new file mode 100644
index 0000000000..5e46e516f0
--- /dev/null
+++ b/tests/auto/shared/qqmljsastdumper.h
@@ -0,0 +1,446 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**/
+#ifndef ASTDUMPER_H
+#define ASTDUMPER_H
+
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qqmljsglobal_p.h>
+#include <private/qqmljsastvisitor_p.h>
+#include <QtCore/QString>
+#include <functional>
+#include <ostream>
+
+QT_BEGIN_NAMESPACE
+class QDebug;
+
+namespace QQmlJS {
+
+enum class DumperOptions {
+ None=0,
+ NoLocations=0x1,
+ NoAnnotations=0x2,
+ DumpNode=0x4
+};
+bool operator & (DumperOptions lhs, DumperOptions rhs);
+DumperOptions operator | (DumperOptions lhs, DumperOptions rhs);
+
+// no export, currently just a supporting file...
+class AstDumper: public AST::BaseVisitor
+{
+public:
+ static QString printNode2(AST::Node *);
+
+ static QString diff(AST::Node *n1, AST::Node *n2, int nContext=3, DumperOptions opt=DumperOptions::None, int indent=0);
+ static QString printNode(AST::Node *n, DumperOptions opt=DumperOptions::None, int indent=1, int baseIndent=0);
+
+ AstDumper(const std::function <void (const QString &)> &dumper, DumperOptions options=DumperOptions::None,
+ int indent=1, int baseIndent=0);
+
+ void start(const QString &str);
+ void start(const char *str);
+ void stop(const QString &str);
+ void stop(const char *str);
+
+ QString qs(const QString &s);
+ QString qs(const char *s);
+ QString qs(const QStringRef &s);
+
+ QString loc(const SourceLocation &s);
+
+ QString boolStr(bool v);
+
+ bool preVisit(AST::Node *el) override;
+ void postVisit(AST::Node *el) override;
+
+ // Ui
+ bool visit(AST::UiProgram *el) override;
+ bool visit(AST::UiHeaderItemList *) override;
+ bool visit(AST::UiPragma *el) override;
+ bool visit(AST::UiImport *el) override;
+ bool visit(AST::UiPublicMember *el) override;
+ bool visit(AST::UiSourceElement *) override;
+ bool visit(AST::UiObjectDefinition *) override;
+ bool visit(AST::UiObjectInitializer *) override;
+ bool visit(AST::UiObjectBinding *) override;
+ bool visit(AST::UiScriptBinding *) override;
+ bool visit(AST::UiArrayBinding *) override;
+ bool visit(AST::UiParameterList *) override;
+ bool visit(AST::UiObjectMemberList *) override;
+ bool visit(AST::UiArrayMemberList *) override;
+ bool visit(AST::UiQualifiedId *) override;
+ bool visit(AST::UiEnumDeclaration *) override;
+ bool visit(AST::UiEnumMemberList *) override;
+ bool visit(AST::UiVersionSpecifier *) override;
+ bool visit(AST::UiInlineComponent *) override;
+ bool visit(AST::UiRequired *) override;
+ bool visit(AST::UiAnnotation *) override;
+ bool visit(AST::UiAnnotationList *) override;
+
+ void endVisit(AST::UiProgram *) override;
+ void endVisit(AST::UiImport *) override;
+ void endVisit(AST::UiHeaderItemList *) override;
+ void endVisit(AST::UiPragma *) override;
+ void endVisit(AST::UiPublicMember *) override;
+ void endVisit(AST::UiSourceElement *) override;
+ void endVisit(AST::UiObjectDefinition *) override;
+ void endVisit(AST::UiObjectInitializer *) override;
+ void endVisit(AST::UiObjectBinding *) override;
+ void endVisit(AST::UiScriptBinding *) override;
+ void endVisit(AST::UiArrayBinding *) override;
+ void endVisit(AST::UiParameterList *) override;
+ void endVisit(AST::UiObjectMemberList *) override;
+ void endVisit(AST::UiArrayMemberList *) override;
+ void endVisit(AST::UiQualifiedId *) override;
+ void endVisit(AST::UiEnumDeclaration *) override;
+ void endVisit(AST::UiEnumMemberList *) override;
+ void endVisit(AST::UiVersionSpecifier *) override;
+ void endVisit(AST::UiInlineComponent *) override;
+ void endVisit(AST::UiRequired *) override;
+ void endVisit(AST::UiAnnotation *) override;
+ void endVisit(AST::UiAnnotationList *) override;
+
+ // QQmlJS
+ bool visit(AST::ThisExpression *) override;
+ void endVisit(AST::ThisExpression *) override;
+
+ bool visit(AST::IdentifierExpression *) override;
+ void endVisit(AST::IdentifierExpression *) override;
+
+ bool visit(AST::NullExpression *) override;
+ void endVisit(AST::NullExpression *) override;
+
+ bool visit(AST::TrueLiteral *) override;
+ void endVisit(AST::TrueLiteral *) override;
+
+ bool visit(AST::FalseLiteral *) override;
+ void endVisit(AST::FalseLiteral *) override;
+
+ bool visit(AST::SuperLiteral *) override;
+ void endVisit(AST::SuperLiteral *) override;
+
+ bool visit(AST::StringLiteral *) override;
+ void endVisit(AST::StringLiteral *) override;
+
+ bool visit(AST::TemplateLiteral *) override;
+ void endVisit(AST::TemplateLiteral *) override;
+
+ bool visit(AST::NumericLiteral *) override;
+ void endVisit(AST::NumericLiteral *) override;
+
+ bool visit(AST::RegExpLiteral *) override;
+ void endVisit(AST::RegExpLiteral *) override;
+
+ bool visit(AST::ArrayPattern *) override;
+ void endVisit(AST::ArrayPattern *) override;
+
+ bool visit(AST::ObjectPattern *) override;
+ void endVisit(AST::ObjectPattern *) override;
+
+ bool visit(AST::PatternElementList *) override;
+ void endVisit(AST::PatternElementList *) override;
+
+ bool visit(AST::PatternPropertyList *) override;
+ void endVisit(AST::PatternPropertyList *) override;
+
+ bool visit(AST::PatternElement *) override;
+ void endVisit(AST::PatternElement *) override;
+
+ bool visit(AST::PatternProperty *) override;
+ void endVisit(AST::PatternProperty *) override;
+
+ bool visit(AST::Elision *) override;
+ void endVisit(AST::Elision *) override;
+
+ bool visit(AST::NestedExpression *) override;
+ void endVisit(AST::NestedExpression *) override;
+
+ bool visit(AST::IdentifierPropertyName *) override;
+ void endVisit(AST::IdentifierPropertyName *) override;
+
+ bool visit(AST::StringLiteralPropertyName *) override;
+ void endVisit(AST::StringLiteralPropertyName *) override;
+
+ bool visit(AST::NumericLiteralPropertyName *) override;
+ void endVisit(AST::NumericLiteralPropertyName *) override;
+
+ bool visit(AST::ComputedPropertyName *) override;
+ void endVisit(AST::ComputedPropertyName *) override;
+
+ bool visit(AST::ArrayMemberExpression *) override;
+ void endVisit(AST::ArrayMemberExpression *) override;
+
+ bool visit(AST::FieldMemberExpression *) override;
+ void endVisit(AST::FieldMemberExpression *) override;
+
+ bool visit(AST::TaggedTemplate *) override;
+ void endVisit(AST::TaggedTemplate *) override;
+
+ bool visit(AST::NewMemberExpression *) override;
+ void endVisit(AST::NewMemberExpression *) override;
+
+ bool visit(AST::NewExpression *) override;
+ void endVisit(AST::NewExpression *) override;
+
+ bool visit(AST::CallExpression *) override;
+ void endVisit(AST::CallExpression *) override;
+
+ bool visit(AST::ArgumentList *) override;
+ void endVisit(AST::ArgumentList *) override;
+
+ bool visit(AST::PostIncrementExpression *) override;
+ void endVisit(AST::PostIncrementExpression *) override;
+
+ bool visit(AST::PostDecrementExpression *) override;
+ void endVisit(AST::PostDecrementExpression *) override;
+
+ bool visit(AST::DeleteExpression *) override;
+ void endVisit(AST::DeleteExpression *) override;
+
+ bool visit(AST::VoidExpression *) override;
+ void endVisit(AST::VoidExpression *) override;
+
+ bool visit(AST::TypeOfExpression *) override;
+ void endVisit(AST::TypeOfExpression *) override;
+
+ bool visit(AST::PreIncrementExpression *) override;
+ void endVisit(AST::PreIncrementExpression *) override;
+
+ bool visit(AST::PreDecrementExpression *) override;
+ void endVisit(AST::PreDecrementExpression *) override;
+
+ bool visit(AST::UnaryPlusExpression *) override;
+ void endVisit(AST::UnaryPlusExpression *) override;
+
+ bool visit(AST::UnaryMinusExpression *) override;
+ void endVisit(AST::UnaryMinusExpression *) override;
+
+ bool visit(AST::TildeExpression *) override;
+ void endVisit(AST::TildeExpression *) override;
+
+ bool visit(AST::NotExpression *) override;
+ void endVisit(AST::NotExpression *) override;
+
+ bool visit(AST::BinaryExpression *) override;
+ void endVisit(AST::BinaryExpression *) override;
+
+ bool visit(AST::ConditionalExpression *) override;
+ void endVisit(AST::ConditionalExpression *) override;
+
+ bool visit(AST::Expression *) override;
+ void endVisit(AST::Expression *) override;
+
+ bool visit(AST::Block *) override;
+ void endVisit(AST::Block *) override;
+
+ bool visit(AST::StatementList *) override;
+ void endVisit(AST::StatementList *) override;
+
+ bool visit(AST::VariableStatement *) override;
+ void endVisit(AST::VariableStatement *) override;
+
+ bool visit(AST::VariableDeclarationList *) override;
+ void endVisit(AST::VariableDeclarationList *) override;
+
+ bool visit(AST::EmptyStatement *) override;
+ void endVisit(AST::EmptyStatement *) override;
+
+ bool visit(AST::ExpressionStatement *) override;
+ void endVisit(AST::ExpressionStatement *) override;
+
+ bool visit(AST::IfStatement *) override;
+ void endVisit(AST::IfStatement *) override;
+
+ bool visit(AST::DoWhileStatement *) override;
+ void endVisit(AST::DoWhileStatement *) override;
+
+ bool visit(AST::WhileStatement *) override;
+ void endVisit(AST::WhileStatement *) override;
+
+ bool visit(AST::ForStatement *) override;
+ void endVisit(AST::ForStatement *) override;
+
+ bool visit(AST::ForEachStatement *) override;
+ void endVisit(AST::ForEachStatement *) override;
+
+ bool visit(AST::ContinueStatement *) override;
+ void endVisit(AST::ContinueStatement *) override;
+
+ bool visit(AST::BreakStatement *) override;
+ void endVisit(AST::BreakStatement *) override;
+
+ bool visit(AST::ReturnStatement *) override;
+ void endVisit(AST::ReturnStatement *) override;
+
+ bool visit(AST::YieldExpression *) override;
+ void endVisit(AST::YieldExpression *) override;
+
+ bool visit(AST::WithStatement *) override;
+ void endVisit(AST::WithStatement *) override;
+
+ bool visit(AST::SwitchStatement *) override;
+ void endVisit(AST::SwitchStatement *) override;
+
+ bool visit(AST::CaseBlock *) override;
+ void endVisit(AST::CaseBlock *) override;
+
+ bool visit(AST::CaseClauses *) override;
+ void endVisit(AST::CaseClauses *) override;
+
+ bool visit(AST::CaseClause *) override;
+ void endVisit(AST::CaseClause *) override;
+
+ bool visit(AST::DefaultClause *) override;
+ void endVisit(AST::DefaultClause *) override;
+
+ bool visit(AST::LabelledStatement *) override;
+ void endVisit(AST::LabelledStatement *) override;
+
+ bool visit(AST::ThrowStatement *) override;
+ void endVisit(AST::ThrowStatement *) override;
+
+ bool visit(AST::TryStatement *) override;
+ void endVisit(AST::TryStatement *) override;
+
+ bool visit(AST::Catch *) override;
+ void endVisit(AST::Catch *) override;
+
+ bool visit(AST::Finally *) override;
+ void endVisit(AST::Finally *) override;
+
+ bool visit(AST::FunctionDeclaration *) override;
+ void endVisit(AST::FunctionDeclaration *) override;
+
+ bool visit(AST::FunctionExpression *) override;
+ void endVisit(AST::FunctionExpression *) override;
+
+ bool visit(AST::FormalParameterList *) override;
+ void endVisit(AST::FormalParameterList *) override;
+
+ bool visit(AST::ClassExpression *) override;
+ void endVisit(AST::ClassExpression *) override;
+
+ bool visit(AST::ClassDeclaration *) override;
+ void endVisit(AST::ClassDeclaration *) override;
+
+ bool visit(AST::ClassElementList *) override;
+ void endVisit(AST::ClassElementList *) override;
+
+ bool visit(AST::Program *) override;
+ void endVisit(AST::Program *) override;
+
+ bool visit(AST::NameSpaceImport *) override;
+ void endVisit(AST::NameSpaceImport *) override;
+
+ bool visit(AST::ImportSpecifier *) override;
+ void endVisit(AST::ImportSpecifier *) override;
+
+ bool visit(AST::ImportsList *) override;
+ void endVisit(AST::ImportsList *) override;
+
+ bool visit(AST::NamedImports *) override;
+ void endVisit(AST::NamedImports *) override;
+
+ bool visit(AST::FromClause *) override;
+ void endVisit(AST::FromClause *) override;
+
+ bool visit(AST::ImportClause *) override;
+ void endVisit(AST::ImportClause *) override;
+
+ bool visit(AST::ImportDeclaration *) override;
+ void endVisit(AST::ImportDeclaration *) override;
+
+ bool visit(AST::ExportSpecifier *) override;
+ void endVisit(AST::ExportSpecifier *) override;
+
+ bool visit(AST::ExportsList *) override;
+ void endVisit(AST::ExportsList *) override;
+
+ bool visit(AST::ExportClause *) override;
+ void endVisit(AST::ExportClause *) override;
+
+ bool visit(AST::ExportDeclaration *) override;
+ void endVisit(AST::ExportDeclaration *) override;
+
+ bool visit(AST::ESModule *) override;
+ void endVisit(AST::ESModule *) override;
+
+ bool visit(AST::DebuggerStatement *) override;
+ void endVisit(AST::DebuggerStatement *) override;
+
+ bool visit(AST::Type *) override;
+ void endVisit(AST::Type *) override;
+
+ bool visit(AST::TypeArgumentList *) override;
+ void endVisit(AST::TypeArgumentList *) override;
+
+ bool visit(AST::TypeAnnotation *) override;
+ void endVisit(AST::TypeAnnotation *) override;
+
+ void throwRecursionDepthError() override;
+
+private:
+ // attributes
+ std::function <void (const QString &)> dumper;
+ DumperOptions options = DumperOptions::None;
+ int indent = 0;
+ int baseIndent = 0;
+ bool dumpNode();
+ bool noLocations();
+ bool noAnnotations();
+};
+
+QDebug operator<<(QDebug d, AST::Node *n);
+
+std::ostream &operator<<(std::ostream &stream, AST::Node *n);
+
+} // namespace AST
+
+QT_END_NAMESPACE
+
+#endif // ASTDUMPER_H
diff --git a/tests/benchmarks/qml/holistic/testtypes.h b/tests/benchmarks/qml/holistic/testtypes.h
index 6ff64c645d..55f094ae7e 100644
--- a/tests/benchmarks/qml/holistic/testtypes.h
+++ b/tests/benchmarks/qml/holistic/testtypes.h
@@ -36,7 +36,6 @@
#include <QtQml/qqmllist.h>
#include <QtCore/qrandom.h>
#include <QtCore/qrect.h>
-#include <QtGui/qmatrix.h>
#include <QtGui/qcolor.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qvector3d.h>
diff --git a/tests/libfuzzer/qml/jsapi/evaluate/evaluate.pro b/tests/libfuzzer/qml/jsapi/evaluate/evaluate.pro
index 301b4f606a..1b042c94d3 100644
--- a/tests/libfuzzer/qml/jsapi/evaluate/evaluate.pro
+++ b/tests/libfuzzer/qml/jsapi/evaluate/evaluate.pro
@@ -3,4 +3,9 @@ QT += qml
CONFIG += console
CONFIG -= app_bundle
SOURCES += main.cpp
-LIBS += -fsanitize=fuzzer
+FUZZ_ENGINE = $$(LIB_FUZZING_ENGINE)
+isEmpty(FUZZ_ENGINE) {
+ QMAKE_LFLAGS += -fsanitize=fuzzer
+} else {
+ LIBS += $$FUZZ_ENGINE
+}
diff --git a/tests/manual/listview/listview.pro b/tests/manual/listview/listview.pro
new file mode 100644
index 0000000000..a517b75079
--- /dev/null
+++ b/tests/manual/listview/listview.pro
@@ -0,0 +1,29 @@
+QT += quick
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Refer to the documentation for the
+# deprecated API to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += \
+ main.cpp
+
+RESOURCES += qml.qrc
+
+# Additional import path used to resolve QML modules in Qt Creator's code model
+QML_IMPORT_PATH =
+
+# Additional import path used to resolve QML modules just for Qt Quick Designer
+QML_DESIGNER_IMPORT_PATH =
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
diff --git a/tests/manual/listview/main.cpp b/tests/manual/listview/main.cpp
new file mode 100644
index 0000000000..8b28b91ee8
--- /dev/null
+++ b/tests/manual/listview/main.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QAbstractTableModel>
+
+typedef QPair<QString, bool> CellData;
+
+class TestModel : public QAbstractListModel
+{
+ Q_OBJECT
+ Q_PROPERTY(int rowCount READ rowCount WRITE setRowCount NOTIFY rowCountChanged)
+
+public:
+ TestModel(QObject *parent = nullptr) : QAbstractListModel(parent) { }
+
+ int rowCount(const QModelIndex & = QModelIndex()) const override { return m_rows; }
+ void setRowCount(int count) {
+ m_rows = count;
+ emit rowCountChanged();
+ }
+
+ QVariant data(const QModelIndex &index, int role) const override
+ {
+ if (!index.isValid())
+ return QVariant();
+
+ switch (role) {
+ case Qt::DisplayRole:
+ return index.row() % 2 ? QStringLiteral("type2") : QStringLiteral("type1");
+ default:
+ break;
+ }
+
+ return QVariant();
+ }
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return {
+ {Qt::DisplayRole, "delegateType"},
+ };
+ }
+
+signals:
+ void rowCountChanged();
+
+private:
+ int m_rows = 0;
+};
+
+#include "main.moc"
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+
+ QGuiApplication app(argc, argv);
+
+ qmlRegisterType<TestModel>("TestModel", 0, 1, "TestModel");
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
+
+ return app.exec();
+}
diff --git a/tests/manual/listview/main.qml b/tests/manual/listview/main.qml
new file mode 100644
index 0000000000..723e10ac05
--- /dev/null
+++ b/tests/manual/listview/main.qml
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Window 2.2
+import QtQuick.Controls 2.5
+import Qt.labs.qmlmodels 1.0
+import TestModel 0.1
+
+Window {
+ id: root
+ visible: true
+ width: 640
+ height: 480
+
+ property int rows: 500
+ property int columns: 20
+ property real delegateHeight: 10
+ property real delegateWidth: 50
+
+ CheckBox {
+ id: reuseItemsBox
+ text: "Reuse items"
+ checked: true
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 10
+ anchors.topMargin: reuseItemsBox.height + 10
+ color: "lightgray"
+
+ ListView {
+ id: listView
+ anchors.fill: parent
+
+ reuseItems: reuseItemsBox.checked
+
+ cacheBuffer: 0
+ contentWidth: columns * delegateWidth
+ contentHeight: rows * delegateHeight
+ flickableDirection: Flickable.HorizontalAndVerticalFlick
+ clip: true
+
+ model: TestModel {
+ rowCount: root.rows
+ }
+
+ ScrollBar.vertical: ScrollBar { policy: ScrollBar.AlwaysOn }
+ ScrollBar.horizontal: ScrollBar { policy: ScrollBar.AlwaysOn }
+
+ delegate: DelegateChooser {
+ role: "delegateType"
+
+ DelegateChoice {
+ roleValue: "type1"
+
+ Item {
+ width: listView.contentWidth
+ height: delegateHeight
+ property int reusedCount: 0
+
+ ListView.onReused: reusedCount++
+
+ Text {
+ id: text1
+ text: "Reused count:" + reusedCount
+ font.pixelSize: 9
+ }
+
+ Row {
+ id: choice1
+ width: listView.contentWidth
+ height: delegateHeight
+ anchors.left: text1.right
+ anchors.leftMargin: 5
+ property color color: Qt.rgba(0.6, 0.6, 0.8, 1)
+
+ Component.onCompleted: {
+ for (var i = 0; i < columns; ++i)
+ cellComponent.createObject(choice1, {column: i, color: color})
+ }
+ }
+ }
+ }
+
+ DelegateChoice {
+ roleValue: "type2"
+
+ Item {
+ width: listView.contentWidth
+ height: delegateHeight
+ property int reusedCount: 0
+
+ ListView.onReused: reusedCount++
+
+ Text {
+ id: text2
+ text: "Reused count:" + reusedCount
+ font.pixelSize: 9
+ }
+
+ Row {
+ id: choice2
+ width: listView.contentWidth
+ height: delegateHeight
+ anchors.left: text2.right
+ anchors.leftMargin: 5
+ property color color: Qt.rgba(0.3, 0.3, 0.8, 1)
+
+ Component.onCompleted: {
+ for (var i = 0; i < columns; ++i)
+ cellComponent.createObject(choice2, {column: i, color: color})
+ }
+ }
+ }
+ }
+ }
+
+ }
+ }
+
+ Component {
+ id: cellComponent
+ Rectangle {
+ height: delegateHeight
+ width: delegateWidth
+ property int column
+ Text {
+ text: "Lorem ipsum dolor sit amet"
+ font.pixelSize: 9
+ }
+ }
+ }
+}
diff --git a/tests/manual/listview/qml.qrc b/tests/manual/listview/qml.qrc
new file mode 100644
index 0000000000..5f6483ac33
--- /dev/null
+++ b/tests/manual/listview/qml.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/nodetypes_ng/buildshaders.bat b/tests/manual/nodetypes_ng/compile.bat
index 328b216c07..328b216c07 100755
--- a/tests/manual/nodetypes_ng/buildshaders.bat
+++ b/tests/manual/nodetypes_ng/compile.bat
diff --git a/tests/manual/nodetypes_ng/shadow_pass1.frag.qsb b/tests/manual/nodetypes_ng/shadow_pass1.frag.qsb
index f3370caee2..4c913fee08 100644
--- a/tests/manual/nodetypes_ng/shadow_pass1.frag.qsb
+++ b/tests/manual/nodetypes_ng/shadow_pass1.frag.qsb
Binary files differ
diff --git a/tests/manual/nodetypes_ng/shadow_pass2.frag.qsb b/tests/manual/nodetypes_ng/shadow_pass2.frag.qsb
index cbf9569373..4f6e6634e7 100644
--- a/tests/manual/nodetypes_ng/shadow_pass2.frag.qsb
+++ b/tests/manual/nodetypes_ng/shadow_pass2.frag.qsb
Binary files differ
diff --git a/tests/manual/nodetypes_ng/wobble.frag.qsb b/tests/manual/nodetypes_ng/wobble.frag.qsb
index 9d3b80fad8..f1766f4363 100644
--- a/tests/manual/nodetypes_ng/wobble.frag.qsb
+++ b/tests/manual/nodetypes_ng/wobble.frag.qsb
Binary files differ
diff --git a/tests/manual/nodetypes_ng/wobble.vert.qsb b/tests/manual/nodetypes_ng/wobble.vert.qsb
index 0f44e87feb..2715c84616 100644
--- a/tests/manual/nodetypes_ng/wobble.vert.qsb
+++ b/tests/manual/nodetypes_ng/wobble.vert.qsb
Binary files differ
diff --git a/tests/manual/pointer/main.qml b/tests/manual/pointer/main.qml
index d382d8b23d..83e1d3b2ba 100644
--- a/tests/manual/pointer/main.qml
+++ b/tests/manual/pointer/main.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the manual tests of the Qt Toolkit.
@@ -57,6 +57,7 @@ Window {
addExample("multibuttons", "TapHandler: gesturePolicy (99 red balloons)", Qt.resolvedUrl("multibuttons.qml"))
addExample("flickable with Handlers", "Flickable with buttons, sliders etc. implemented in various ways", Qt.resolvedUrl("flickableWithHandlers.qml"))
addExample("tap and drag", "Flickable with all possible combinations of TapHandler and DragHandler children", Qt.resolvedUrl("pointerDrag.qml"))
+ addExample("tablet canvas", "PointHandler and HoverHandler with a tablet: detect the stylus, and draw", Qt.resolvedUrl("tabletCanvasDrawing.qml"))
}
}
Item {
diff --git a/tests/manual/pointer/pointerDrag.qml b/tests/manual/pointer/pointerDrag.qml
index 79044eb0b4..2063d8fae2 100644
--- a/tests/manual/pointer/pointerDrag.qml
+++ b/tests/manual/pointer/pointerDrag.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the manual tests of the Qt Toolkit.
@@ -26,7 +26,7 @@
**
****************************************************************************/
-import QtQuick 2.12
+import QtQuick 2.15
import "content"
Rectangle {
@@ -74,7 +74,14 @@ Rectangle {
label: "DragHandler"
objectName: "dragSquircle1"
DragHandler {
-
+ dragThreshold: ckZeroDragThreshold1.checked ? 0 : undefined
+ }
+ CheckBox {
+ id: ckZeroDragThreshold1
+ label: " Zero threshold"
+ anchors.horizontalCenter: parent.horizontalCenter
+ y: 20
+ checked: false
}
}
@@ -99,7 +106,16 @@ Rectangle {
id: tap2
gesturePolicy: root.globalGesturePolicy
}
- DragHandler { }
+ DragHandler {
+ dragThreshold: ckZeroDragThreshold2.checked ? 0 : undefined
+ }
+ CheckBox {
+ id: ckZeroDragThreshold2
+ label: " Zero threshold"
+ anchors.horizontalCenter: parent.horizontalCenter
+ y: 32
+ checked: false
+ }
}
TextBox {
@@ -107,7 +123,16 @@ Rectangle {
width: 100; height: 100
label: "DragHandler\nTapHandler"
color: queryColor(tap3.pressed)
- DragHandler { }
+ DragHandler {
+ dragThreshold: ckZeroDragThreshold3.checked ? 0 : undefined
+ }
+ CheckBox {
+ id: ckZeroDragThreshold3
+ label: " Zero threshold"
+ anchors.horizontalCenter: parent.horizontalCenter
+ y: 32
+ checked: false
+ }
TapHandler {
id: tap3
gesturePolicy: root.globalGesturePolicy
@@ -118,7 +143,16 @@ Rectangle {
x: 400; y: 0
width: 100; height: 100
label: "DragHandler"
- DragHandler { }
+ DragHandler {
+ dragThreshold: ckZeroDragThreshold4.checked ? 0 : undefined
+ }
+ CheckBox {
+ id: ckZeroDragThreshold4
+ label: " Zero threshold"
+ anchors.horizontalCenter: parent.horizontalCenter
+ y: 20
+ checked: false
+ }
TextBox {
label: "TapHandler"
@@ -145,6 +179,13 @@ Rectangle {
label: " Greedy ↓"
checked: true
}
+ CheckBox {
+ id: ckZeroDragThreshold5
+ label: " Zero threshold"
+ x: 10
+ anchors.bottom: ckGreedyDrag.top
+ checked: false
+ }
TapHandler {
id: tap5
gesturePolicy: root.globalGesturePolicy
@@ -159,6 +200,7 @@ Rectangle {
DragHandler {
grabPermissions: ckGreedyDrag ? DragHandler.CanTakeOverFromAnything :
DragHandler.CanTakeOverFromItems | DragHandler.CanTakeOverFromHandlersOfDifferentType | DragHandler.ApprovesTakeOverByAnything
+ dragThreshold: ckZeroDragThreshold5.checked ? 0 : undefined
}
}
}
@@ -174,7 +216,16 @@ Rectangle {
label: "DragHandler"
x: (parent.width - width)/2
y: 60
- DragHandler { }
+ DragHandler {
+ dragThreshold: ckZeroDragThreshold6.checked ? 0 : undefined
+ }
+ }
+ CheckBox {
+ id: ckZeroDragThreshold6
+ label: " Zero threshold"
+ anchors.horizontalCenter: parent.horizontalCenter
+ y: 20
+ checked: false
}
}
diff --git a/tests/manual/pointer/qml.qrc b/tests/manual/pointer/qml.qrc
index 95bece180a..20956fcbac 100644
--- a/tests/manual/pointer/qml.qrc
+++ b/tests/manual/pointer/qml.qrc
@@ -13,6 +13,7 @@
<file>pointerDrag.qml</file>
<file>singlePointHandlerProperties.qml</file>
<file>sidebar.qml</file>
+ <file>tabletCanvasDrawing.qml</file>
<file>tapHandler.qml</file>
<file>content/CheckBox.qml</file>
<file>content/FakeFlickable.qml</file>
@@ -30,6 +31,10 @@
<file>content/TouchpointFeedbackSprite.qml</file>
<file>resources/arrowhead.png</file>
<file>resources/balloon.png</file>
+ <file>resources/cursor-airbrush.png</file>
+ <file>resources/cursor-eraser.png</file>
+ <file>resources/cursor-felt-marker.png</file>
+ <file>resources/cursor-pencil.png</file>
<file>resources/fighter.png</file>
<file>resources/fingersprite.png</file>
<file>resources/grabbing-location.svg</file>
diff --git a/tests/manual/pointer/resources/cursor-airbrush.png b/tests/manual/pointer/resources/cursor-airbrush.png
new file mode 100644
index 0000000000..bea756ed6f
--- /dev/null
+++ b/tests/manual/pointer/resources/cursor-airbrush.png
Binary files differ
diff --git a/tests/manual/pointer/resources/cursor-eraser.png b/tests/manual/pointer/resources/cursor-eraser.png
new file mode 100644
index 0000000000..e5488a89f2
--- /dev/null
+++ b/tests/manual/pointer/resources/cursor-eraser.png
Binary files differ
diff --git a/tests/manual/pointer/resources/cursor-felt-marker.png b/tests/manual/pointer/resources/cursor-felt-marker.png
new file mode 100644
index 0000000000..132f09aa39
--- /dev/null
+++ b/tests/manual/pointer/resources/cursor-felt-marker.png
Binary files differ
diff --git a/tests/manual/pointer/resources/cursor-pencil.png b/tests/manual/pointer/resources/cursor-pencil.png
new file mode 100644
index 0000000000..cc2f447d02
--- /dev/null
+++ b/tests/manual/pointer/resources/cursor-pencil.png
Binary files differ
diff --git a/tests/manual/pointer/sidebar.qml b/tests/manual/pointer/sidebar.qml
index 827dbd1980..b7370a4fb7 100644
--- a/tests/manual/pointer/sidebar.qml
+++ b/tests/manual/pointer/sidebar.qml
@@ -26,7 +26,7 @@
**
****************************************************************************/
-import QtQuick 2.12
+import QtQuick 2.15
import "content"
Rectangle {
@@ -53,6 +53,7 @@ Rectangle {
id: buttonMA
objectName: "buttonMA"
hoverEnabled: true
+ cursorShape: Qt.UpArrowCursor
anchors.fill: parent
onClicked: console.log("clicked MA")
}
@@ -75,9 +76,11 @@ Rectangle {
id: buttonHH
objectName: "buttonHH"
acceptedDevices: PointerDevice.AllDevices
+ cursorShape: tapHandler.pressed ? Qt.BusyCursor : Qt.PointingHandCursor
}
TapHandler {
+ id: tapHandler
onTapped: tapFlash.start()
}
@@ -148,6 +151,7 @@ Rectangle {
HoverHandler {
id: topSidebarHH
objectName: "topSidebarHH"
+ cursorShape: Qt.OpenHandCursor
}
Loader {
@@ -173,6 +177,7 @@ Rectangle {
id: bottomSidebarMA
objectName: "bottomSidebarMA"
hoverEnabled: true
+ cursorShape: Qt.ClosedHandCursor
anchors.fill: parent
}
diff --git a/tests/manual/pointer/tabletCanvasDrawing.qml b/tests/manual/pointer/tabletCanvasDrawing.qml
new file mode 100644
index 0000000000..c340dee5f4
--- /dev/null
+++ b/tests/manual/pointer/tabletCanvasDrawing.qml
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the manual tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import "content"
+
+Rectangle {
+ width: 1024
+ height: 1024
+ color: "#444"
+
+ ColumnLayout {
+ x: -15; width: 80
+ height: parent.height
+ Slider {
+ id: hueSlider
+ width: 80; height: 200
+ Layout.fillHeight: true
+ label: "hue"
+ Rectangle {
+ color: "beige"
+ width: 30
+ height: 25
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 2
+ anchors.horizontalCenter: parent.horizontalCenter
+ Rectangle {
+ border.color: "white"
+ color: canvas.drawingColor
+ anchors.fill: parent
+ }
+ }
+ }
+ Slider {
+ id: saturationSlider
+ width: 80; height: 200
+ Layout.fillHeight: true
+ label: "sat"
+ }
+ Slider {
+ id: lightnessSlider
+ width: 80; height: 200
+ Layout.fillHeight: true
+ label: "light"
+ }
+ }
+
+ ColumnLayout {
+ x: parent.width - 65; width: 80
+ height: parent.height
+ Slider {
+ id: widthSlider
+ width: 80; height: 200
+ Layout.fillHeight: true
+ label: "width"
+ }
+ Slider {
+ id: alphaSlider
+ width: 80; height: 200
+ Layout.fillHeight: true
+ label: "alpha"
+ }
+ }
+
+ Rectangle {
+ id: rect
+ width: 640
+ height: 480
+ color: "beige"
+ anchors {
+ fill: parent
+ margins: 10
+ leftMargin: 50
+ rightMargin: 50
+ }
+
+ Canvas {
+ id: canvas
+ anchors.fill: parent
+ antialiasing: true
+ renderTarget: Canvas.FramebufferObject
+ property color drawingColor: Qt.hsla(hueSlider.value / 100.0,
+ saturationSlider.value / 100.0,
+ lightnessSlider.value / 100.0,
+ alphaSlider.value / 100.0)
+ property var points: []
+ property var pressures: []
+ property var pointerType: PointerDevice.Pen
+ onPaint: {
+ if (points.length < 2)
+ return
+ var ctx = canvas.getContext('2d');
+ ctx.save()
+ ctx.strokeStyle = pointerType === PointerDevice.Pen ? drawingColor : "beige"
+ ctx.lineCap = "round"
+ if (pressures.length === points.length) {
+ for (var i = 1; i < points.length; i++) {
+ ctx.lineWidth = pressures[i] * widthSlider.value
+ ctx.beginPath()
+ ctx.moveTo(points[i - 1].x, points[i - 1].y)
+ ctx.lineTo(points[i].x, points[i].y)
+ ctx.stroke()
+ }
+ points = points.slice(points.length - 2, 1)
+ pressures = pressures.slice(pressures.length - 2, 1)
+ } else {
+ ctx.beginPath()
+ ctx.moveTo(points[0].x, points[0].y)
+ for (var i = 1; i < points.length; i++)
+ ctx.lineTo(points[i].x, points[i].y)
+ ctx.lineWidth = widthSlider
+ ctx.stroke()
+ points = points.slice(points.length - 2, 1)
+ pressures = []
+ }
+ ctx.restore()
+ }
+ }
+
+ PointHandler {
+ acceptedPointerTypes: PointerDevice.Pen
+ onActiveChanged:
+ if (active) {
+ canvas.pointerType = PointerDevice.Pen
+ } else {
+ canvas.points = []
+ canvas.pressures = []
+ }
+ onPointChanged:
+ if (active) {
+ canvas.points.push(point.position)
+ canvas.pressures.push(point.pressure)
+ canvas.requestPaint()
+ }
+ }
+
+ PointHandler {
+ acceptedPointerTypes: PointerDevice.Eraser
+ onActiveChanged:
+ if (active) {
+ canvas.pointerType = PointerDevice.Eraser
+ } else {
+ canvas.points = []
+ canvas.pressures = []
+ }
+ onPointChanged:
+ if (active) {
+ canvas.points.push(point.position)
+ canvas.pressures.push(point.pressure)
+ canvas.requestPaint()
+ }
+ }
+
+ HoverHandler {
+ id: stylusHandler
+ acceptedDevices: PointerDevice.Stylus
+ acceptedPointerTypes: PointerDevice.Pen
+ target: Image {
+ parent: rect
+ source: stylusHandler.point.rotation === 0 ?
+ "resources/cursor-pencil.png" : "resources/cursor-felt-marker.png"
+ visible: stylusHandler.hovered
+ rotation: stylusHandler.point.rotation
+ x: stylusHandler.point.position.x
+ y: stylusHandler.point.position.y
+ }
+ }
+
+ HoverHandler {
+ id: airbrushHandler
+ acceptedDevices: PointerDevice.Airbrush
+ acceptedPointerTypes: PointerDevice.Pen
+ target: Image {
+ parent: rect
+ source: "resources/cursor-airbrush.png"
+ visible: airbrushHandler.hovered
+ x: airbrushHandler.point.position.x
+ y: airbrushHandler.point.position.y
+ }
+ }
+
+ HoverHandler {
+ id: eraserHandler
+ acceptedPointerTypes: PointerDevice.Eraser
+ target: Image {
+ parent: rect
+ source: "resources/cursor-eraser.png"
+ visible: eraserHandler.hovered
+ x: eraserHandler.point.position.x
+ y: eraserHandler.point.position.y - 32
+ }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/activity/activity.qml b/tests/manual/scenegraph_lancelot/data/shaders/activity/activity.qml
index d4ae526b5d..956b3d7d91 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/activity/activity.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/activity/activity.qml
@@ -23,13 +23,6 @@ Item {
property variant source: source
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
+ fragmentShader: "qrc:shaders/gradient.frag"
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/basic/basic.qml b/tests/manual/scenegraph_lancelot/data/shaders/basic/basic.qml
index f1bb03a4a9..24aa5db5e8 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/basic/basic.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/basic/basic.qml
@@ -6,12 +6,6 @@ Item {
ShaderEffect {
anchors.fill: parent;
- fragmentShader: "
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 1, 1);
- }
- "
+ fragmentShader: "qrc:shaders/basic.frag"
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/culling/culling_1.qml b/tests/manual/scenegraph_lancelot/data/shaders/culling/culling_1.qml
index 76ce60fd7d..118de56098 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/culling/culling_1.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/culling/culling_1.qml
@@ -72,16 +72,7 @@ Rectangle {
cullMode: model.bar
property variant frontSource: front
property variant backSource: back
- fragmentShader: "
- varying highp vec2 qt_TexCoord0;
- uniform sampler2D frontSource;
- uniform sampler2D backSource;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = gl_FrontFacing
- ? texture2D(frontSource, qt_TexCoord0)
- : texture2D(backSource, qt_TexCoord0);
- }"
+ fragmentShader: "qrc:shaders/culling.frag"
transform: Rotation {
origin.x: 200
origin.y: 180 - 120 * index
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/culling/culling_2.qml b/tests/manual/scenegraph_lancelot/data/shaders/culling/culling_2.qml
index 45f20dd5a4..7614451e05 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/culling/culling_2.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/culling/culling_2.qml
@@ -72,16 +72,7 @@ Rectangle {
cullMode: model.bar
property variant frontSource: front
property variant backSource: back
- fragmentShader: "
- varying highp vec2 qt_TexCoord0;
- uniform sampler2D frontSource;
- uniform sampler2D backSource;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = gl_FrontFacing
- ? texture2D(frontSource, qt_TexCoord0)
- : texture2D(backSource, qt_TexCoord0);
- }"
+ fragmentShader: "qrc:shaders/culling.frag"
transform: Rotation {
origin.x: 100
origin.y: 180 - 120 * index
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/attributes.qml b/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/attributes.qml
deleted file mode 100644
index 17d9aadf95..0000000000
--- a/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/attributes.qml
+++ /dev/null
@@ -1,65 +0,0 @@
-import QtQuick 2.0
-
-Rectangle {
- width: 320
- height: 480
-
- Text {
- id: text
- font.pixelSize: 80
- text: "Shaderz!"
- }
-
- ShaderEffectSource {
- id: source
- sourceItem: text
- hideSource: true
- smooth: true
- }
- Column {
- ShaderEffect {
- width: 320
- height: 160
- property variant source: source
- vertexShader: "
- uniform highp mat4 qt_Matrix;
- attribute highp vec4 qt_Vertex;
- attribute highp vec2 qt_MultiTexCoord0;
- varying highp vec2 qt_TexCoord0;
- void main() {
- gl_Position = qt_Matrix * qt_Vertex;
- qt_TexCoord0 = qt_MultiTexCoord0;
- }"
- }
- ShaderEffect {
- width: 320
- height: 160
- property variant source: source
- vertexShader: "
- attribute highp vec2 qt_MultiTexCoord0;
- uniform highp mat4 qt_Matrix;
- attribute highp vec4 qt_Vertex;
- varying highp vec2 qt_TexCoord0;
- void main() {
- gl_Position = qt_Matrix * qt_Vertex;
- qt_TexCoord0 = qt_MultiTexCoord0;
- }"
- }
- ShaderEffect {
- width: 320
- height: 160
- property variant source: source
- vertexShader: "
- attribute highp vec2 qt_MultiTexCoord0;
- uniform highp mat4 qt_Matrix;
- attribute highp vec4 qt_Vertex;
- varying highp vec2 qt_TexCoord0;
- uniform highp float width;
- uniform highp float height;
- void main() {
- gl_Position = qt_Matrix * qt_Vertex;
- qt_TexCoord0 = qt_Vertex.xy / vec2(width, height);
- }"
- }
- }
-}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_1.qml b/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_1.qml
index ddea979124..7a743453ab 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_1.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_1.qml
@@ -6,8 +6,8 @@ Rectangle {
color: "skyblue"
ShaderEffect {
anchors.centerIn: parent
- width: 16 * 16
- height: 24 * 16
+ width: 22 * 12
+ height: 16 * 12
property variant source: ShaderEffectSource {
sourceItem: Rectangle {
width: 22 * 20
@@ -40,18 +40,7 @@ Rectangle {
}
smooth: true
}
- vertexShader: "
- uniform highp mat4 qt_Matrix;
- attribute highp vec4 qt_Vertex;
- attribute highp vec2 qt_MultiTexCoord0;
- varying highp vec2 qt_TexCoord0;
- void main() {
- highp vec4 pos = qt_Vertex;
- pos.x += sin(qt_Vertex.y * 0.02) * 20.;
- pos.y += sin(qt_Vertex.x * 0.02) * 20.;
- gl_Position = qt_Matrix * pos;
- qt_TexCoord0 = qt_MultiTexCoord0;
- }"
+ vertexShader: "qrc:shaders/wave.vert"
mesh: GridMesh {
property int r: 1
resolution: Qt.size(r, r)
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_16.qml b/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_16.qml
index 971cda4f55..9e221d0887 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_16.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_16.qml
@@ -6,8 +6,8 @@ Rectangle {
color: "skyblue"
ShaderEffect {
anchors.centerIn: parent
- width: 16 * 16
- height: 24 * 16
+ width: 22 * 12
+ height: 16 * 12
property variant source: ShaderEffectSource {
sourceItem: Rectangle {
width: 22 * 20
@@ -40,18 +40,7 @@ Rectangle {
}
smooth: true
}
- vertexShader: "
- uniform highp mat4 qt_Matrix;
- attribute highp vec4 qt_Vertex;
- attribute highp vec2 qt_MultiTexCoord0;
- varying highp vec2 qt_TexCoord0;
- void main() {
- highp vec4 pos = qt_Vertex;
- pos.x += sin(qt_Vertex.y * 0.02) * 20.;
- pos.y += sin(qt_Vertex.x * 0.02) * 20.;
- gl_Position = qt_Matrix * pos;
- qt_TexCoord0 = qt_MultiTexCoord0;
- }"
+ vertexShader: "qrc:shaders/wave.vert"
mesh: GridMesh {
property int r: 16
resolution: Qt.size(r, r)
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_2.qml b/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_2.qml
index d301ef089c..4dad42d182 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_2.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_2.qml
@@ -4,10 +4,10 @@ Rectangle {
width: 320
height: 480
color: "skyblue"
- ShaderEffect{
+ ShaderEffect {
anchors.centerIn: parent
- width: 16 * 16
- height: 24 * 16
+ width: 22 * 12
+ height: 16 * 12
property variant source: ShaderEffectSource {
sourceItem: Rectangle {
width: 22 * 20
@@ -40,18 +40,7 @@ Rectangle {
}
smooth: true
}
- vertexShader: "
- uniform highp mat4 qt_Matrix;
- attribute highp vec4 qt_Vertex;
- attribute highp vec2 qt_MultiTexCoord0;
- varying highp vec2 qt_TexCoord0;
- void main() {
- highp vec4 pos = qt_Vertex;
- pos.x += sin(qt_Vertex.y * 0.02) * 20.;
- pos.y += sin(qt_Vertex.x * 0.02) * 20.;
- gl_Position = qt_Matrix * pos;
- qt_TexCoord0 = qt_MultiTexCoord0;
- }"
+ vertexShader: "qrc:shaders/wave.vert"
mesh: GridMesh {
property int r: 2
resolution: Qt.size(r, r)
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_4.qml b/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_4.qml
index 0043282efd..9d91da0bb2 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_4.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_4.qml
@@ -6,8 +6,8 @@ Rectangle {
color: "skyblue"
ShaderEffect {
anchors.centerIn: parent
- width: 16 * 16
- height: 24 * 16
+ width: 22 * 12
+ height: 16 * 12
property variant source: ShaderEffectSource {
sourceItem: Rectangle {
width: 22 * 20
@@ -40,18 +40,7 @@ Rectangle {
}
smooth: true
}
- vertexShader: "
- uniform highp mat4 qt_Matrix;
- attribute highp vec4 qt_Vertex;
- attribute highp vec2 qt_MultiTexCoord0;
- varying highp vec2 qt_TexCoord0;
- void main() {
- highp vec4 pos = qt_Vertex;
- pos.x += sin(qt_Vertex.y * 0.02) * 20.;
- pos.y += sin(qt_Vertex.x * 0.02) * 20.;
- gl_Position = qt_Matrix * pos;
- qt_TexCoord0 = qt_MultiTexCoord0;
- }"
+ vertexShader: "qrc:shaders/wave.vert"
mesh: GridMesh {
property int r: 4
resolution: Qt.size(r, r)
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_8.qml b/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_8.qml
index f9427a1f16..c436c0f8e4 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_8.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/resolution_8.qml
@@ -6,8 +6,8 @@ Rectangle {
color: "skyblue"
ShaderEffect {
anchors.centerIn: parent
- width: 16 * 16
- height: 24 * 16
+ width: 22 * 12
+ height: 16 * 12
property variant source: ShaderEffectSource {
sourceItem: Rectangle {
width: 22 * 20
@@ -40,18 +40,7 @@ Rectangle {
}
smooth: true
}
- vertexShader: "
- uniform highp mat4 qt_Matrix;
- attribute highp vec4 qt_Vertex;
- attribute highp vec2 qt_MultiTexCoord0;
- varying highp vec2 qt_TexCoord0;
- void main() {
- highp vec4 pos = qt_Vertex;
- pos.x += sin(qt_Vertex.y * 0.02) * 20.;
- pos.y += sin(qt_Vertex.x * 0.02) * 20.;
- gl_Position = qt_Matrix * pos;
- qt_TexCoord0 = qt_MultiTexCoord0;
- }"
+ vertexShader: "qrc:shaders/wave.vert"
mesh: GridMesh {
property int r: 8
resolution: Qt.size(r, r)
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/hiddensource_1.qml b/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/hiddensource_1.qml
index 83469531b1..7c5b5efac5 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/hiddensource_1.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/hiddensource_1.qml
@@ -43,22 +43,6 @@ Item {
property variant offset: Qt.size(4 / width, 4 / height)
property variant delta: Qt.size(0.5 / width, 0.5 / height)
- fragmentShader: "
- uniform lowp sampler2D source;
- uniform highp vec2 offset;
- uniform highp vec2 delta;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- highp vec2 delta2 = vec2(delta.x, -delta.y);
- lowp float shadow = 0.25 * (texture2D(source, qt_TexCoord0 - offset + delta).a
- + texture2D(source, qt_TexCoord0 - offset - delta).a
- + texture2D(source, qt_TexCoord0 - offset + delta2).a
- + texture2D(source, qt_TexCoord0 - offset - delta2).a);
- lowp vec4 color = texture2D(source, qt_TexCoord0);
- gl_FragColor = mix(vec4(vec3(0.), 0.5 * shadow), color, color.a);
- }
- "
+ fragmentShader: "qrc:shaders/shadow.frag"
}
}
-
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/hiddensource_2.qml b/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/hiddensource_2.qml
index 160b89168e..64b950ace4 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/hiddensource_2.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/hiddensource_2.qml
@@ -43,23 +43,6 @@ Item {
property variant offset: Qt.size(4 / width, 4 / height)
property variant delta: Qt.size(0.5 / width, 0.5 / height)
- fragmentShader: "
- uniform lowp sampler2D source;
- uniform highp vec2 offset;
- uniform highp vec2 delta;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- highp vec2 delta2 = vec2(delta.x, -delta.y);
- lowp float shadow = 0.25 * (texture2D(source, qt_TexCoord0 - offset + delta).a
- + texture2D(source, qt_TexCoord0 - offset - delta).a
- + texture2D(source, qt_TexCoord0 - offset + delta2).a
- + texture2D(source, qt_TexCoord0 - offset - delta2).a);
- lowp vec4 color = texture2D(source, qt_TexCoord0);
- gl_FragColor = mix(vec4(vec3(0.), 0.5 * shadow), color, color.a);
- }
- "
+ fragmentShader: "qrc:shaders/shadow.frag"
}
}
-
-
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/unhidden_1.qml b/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/unhidden_1.qml
index 566edddedb..b071715cf2 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/unhidden_1.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/unhidden_1.qml
@@ -43,22 +43,6 @@ Item {
property variant offset: Qt.size(4 / width, 4 / height)
property variant delta: Qt.size(0.5 / width, 0.5 / height)
- fragmentShader: "
- uniform lowp sampler2D source;
- uniform highp vec2 offset;
- uniform highp vec2 delta;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- highp vec2 delta2 = vec2(delta.x, -delta.y);
- lowp float shadow = 0.25 * (texture2D(source, qt_TexCoord0 - offset + delta).a
- + texture2D(source, qt_TexCoord0 - offset - delta).a
- + texture2D(source, qt_TexCoord0 - offset + delta2).a
- + texture2D(source, qt_TexCoord0 - offset - delta2).a);
- lowp vec4 color = texture2D(source, qt_TexCoord0);
- gl_FragColor = mix(vec4(vec3(0.), 0.5 * shadow), color, color.a);
- }
- "
+ fragmentShader: "qrc:shaders/shadow.frag"
}
}
-
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/unhidden_2.qml b/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/unhidden_2.qml
index 0b8038e9ee..02ac70e69c 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/unhidden_2.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/hiddensource/unhidden_2.qml
@@ -43,24 +43,6 @@ Item {
property variant offset: Qt.size(4 / width, 4 / height)
property variant delta: Qt.size(0.5 / width, 0.5 / height)
- fragmentShader: "
- uniform lowp sampler2D source;
- uniform highp vec2 offset;
- uniform highp vec2 delta;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- highp vec2 delta2 = vec2(delta.x, -delta.y);
- lowp float shadow = 0.25 * (texture2D(source, qt_TexCoord0 - offset + delta).a
- + texture2D(source, qt_TexCoord0 - offset - delta).a
- + texture2D(source, qt_TexCoord0 - offset + delta2).a
- + texture2D(source, qt_TexCoord0 - offset - delta2).a);
- lowp vec4 color = texture2D(source, qt_TexCoord0);
- gl_FragColor = mix(vec4(vec3(0.), 0.5 * shadow), color, color.a);
- }
- "
+ fragmentShader: "qrc:shaders/shadow.frag"
}
}
-
-
-
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/image/async.qml b/tests/manual/scenegraph_lancelot/data/shaders/image/async.qml
index 132f160a26..c4cf4cc1e4 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/image/async.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/image/async.qml
@@ -6,7 +6,7 @@ Item {
Image {
id: image;
- source: "./face-smile.png"
+ source: "face-smile.png"
visible: false
asynchronous: true
}
@@ -14,15 +14,7 @@ Item {
ShaderEffect {
anchors.fill: image
property variant source: image
-
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 0, 1) + texture2D(source, qt_TexCoord0);
- }
- "
+ fragmentShader: "qrc:shaders/gradient2.frag"
visible: image.status == Image.Ready
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/image/source.qml b/tests/manual/scenegraph_lancelot/data/shaders/image/source.qml
index 878eddeda5..04406829b3 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/image/source.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/image/source.qml
@@ -13,14 +13,6 @@ Item {
ShaderEffect {
anchors.fill: image
property variant source: image
-
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 0, 1) + texture2D(source, qt_TexCoord0);
- }
- "
+ fragmentShader: "qrc:shaders/gradient2.frag"
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/live/liveonce_1.qml b/tests/manual/scenegraph_lancelot/data/shaders/live/liveonce_1.qml
index 0383feaf91..97b5760854 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/live/liveonce_1.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/live/liveonce_1.qml
@@ -32,13 +32,6 @@ Item {
property variant source: source
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(0, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
+ fragmentShader: "qrc:shaders/gradient3.frag"
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/live/liveonce_2.qml b/tests/manual/scenegraph_lancelot/data/shaders/live/liveonce_2.qml
index 2e7074c65d..ea3456838c 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/live/liveonce_2.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/live/liveonce_2.qml
@@ -32,13 +32,6 @@ Item {
property variant source: source
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(0, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
+ fragmentShader: "qrc:shaders/gradient3.frag"
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/live/livetwice_1.qml b/tests/manual/scenegraph_lancelot/data/shaders/live/livetwice_1.qml
index 3793e655c7..9f0162ccd3 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/live/livetwice_1.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/live/livetwice_1.qml
@@ -16,7 +16,7 @@ Item {
height: 50
color: "red"
anchors.centerIn: parent
- transform: Rotation{ angle: 45}
+ transform: Rotation{ angle: 45 }
}
}
@@ -38,14 +38,7 @@ Item {
property variant source: source1
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(1, qt_TexCoord0.y, 0, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
+ fragmentShader: "qrc:shaders/gradient4.frag"
}
ShaderEffect {
@@ -55,14 +48,7 @@ Item {
property variant source: source2
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(0, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
+ fragmentShader: "qrc:shaders/gradient3.frag"
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/live/livetwice_2.qml b/tests/manual/scenegraph_lancelot/data/shaders/live/livetwice_2.qml
index 2d8a4b6c09..e0c218ca69 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/live/livetwice_2.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/live/livetwice_2.qml
@@ -16,7 +16,7 @@ Item {
height: 50
color: "red"
anchors.centerIn: parent
- transform: Rotation{ angle: 90}
+ transform: Rotation{ angle: 90 }
}
}
@@ -38,14 +38,7 @@ Item {
property variant source: source1
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(1, qt_TexCoord0.y, 0, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
+ fragmentShader: "qrc:shaders/gradient4.frag"
}
ShaderEffect {
@@ -55,14 +48,7 @@ Item {
property variant source: source2
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(0, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
+ fragmentShader: "qrc:shaders/gradient3.frag"
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/live/samesource.qml b/tests/manual/scenegraph_lancelot/data/shaders/live/samesource.qml
index 67e0cc36ad..5b1f15c01c 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/live/samesource.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/live/samesource.qml
@@ -24,14 +24,7 @@ Item {
property variant source: source
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(0, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
+ fragmentShader: "qrc:shaders/gradient3.frag"
}
ShaderEffect {
@@ -41,13 +34,6 @@ Item {
property variant source: source
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(qt_TexCoord0.x, 1, 0, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
+ fragmentShader: "qrc:shaders/gradient5.frag"
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/source/one-source.qml b/tests/manual/scenegraph_lancelot/data/shaders/source/one-source.qml
index d57f7c5dfb..309db50ba2 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/source/one-source.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/source/one-source.qml
@@ -23,13 +23,6 @@ Item {
property variant source: source
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
+ fragmentShader: "qrc:shaders/gradient.frag"
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/source/rect.qml b/tests/manual/scenegraph_lancelot/data/shaders/source/rect.qml
index e2a3ca7a0c..f473207235 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/source/rect.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/source/rect.qml
@@ -22,14 +22,7 @@ Item {
property variant source: source
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
+ fragmentShader: "qrc:shaders/gradient.frag"
}
Rectangle {
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/source/switch_1.qml b/tests/manual/scenegraph_lancelot/data/shaders/source/switch_1.qml
index 9df6b13c1e..2b04b76482 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/source/switch_1.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/source/switch_1.qml
@@ -47,14 +47,7 @@ Item {
property variant source: source
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
+ fragmentShader: "qrc:shaders/gradient.frag"
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/source/switch_2.qml b/tests/manual/scenegraph_lancelot/data/shaders/source/switch_2.qml
index f997630d30..0ce09cda18 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/source/switch_2.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/source/switch_2.qml
@@ -47,14 +47,7 @@ Item {
property variant source: source
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
+ fragmentShader: "qrc:shaders/gradient.frag"
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/source/switch_3.qml b/tests/manual/scenegraph_lancelot/data/shaders/source/switch_3.qml
index 0d3c1fc4ee..c02dfba9e2 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/source/switch_3.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/source/switch_3.qml
@@ -47,14 +47,7 @@ Item {
property variant source: source
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
+ fragmentShader: "qrc:shaders/gradient.frag"
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/source/two-sources.qml b/tests/manual/scenegraph_lancelot/data/shaders/source/two-sources.qml
index 1fadabe5b6..dbb82a278e 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/source/two-sources.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/source/two-sources.qml
@@ -44,14 +44,6 @@ Item {
property variant colorSource: colorSource
property variant maskSource: maskSource;
- fragmentShader: "
- uniform lowp sampler2D maskSource;
- uniform lowp sampler2D colorSource;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = texture2D(maskSource, qt_TexCoord0).a * texture2D(colorSource, qt_TexCoord0.yx);
- }
- "
+ fragmentShader: "qrc:shaders/stencil.frag"
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/source/visible_1.qml b/tests/manual/scenegraph_lancelot/data/shaders/source/visible_1.qml
index 7a3bf9fd36..309028807f 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/source/visible_1.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/source/visible_1.qml
@@ -27,14 +27,6 @@ Item {
property variant source: source
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
-
+ fragmentShader: "qrc:shaders/gradient.frag"
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/source/visible_2.qml b/tests/manual/scenegraph_lancelot/data/shaders/source/visible_2.qml
index d60dbaee3d..df05c8f087 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/source/visible_2.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/source/visible_2.qml
@@ -27,14 +27,6 @@ Item {
property variant source: source
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
- }
- "
-
+ fragmentShader: "qrc:shaders/gradient.frag"
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/texture/size.qml b/tests/manual/scenegraph_lancelot/data/shaders/texture/size.qml
index ab8db47009..5738da5e8d 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/texture/size.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/texture/size.qml
@@ -18,22 +18,7 @@ Item {
property variant textureSize: source.textureSize
property color color: "black"
- fragmentShader: "
- uniform lowp sampler2D source;
- varying highp vec2 qt_TexCoord0;
- uniform highp vec2 textureSize;
- uniform lowp vec4 color;
- uniform lowp float qt_Opacity;
- void main() {
- highp vec2 dx = vec2(0.5 / textureSize.x, 0.);
- highp vec2 dy = vec2(0., 0.5 / textureSize.y);
- gl_FragColor = color * 0.25
- * (texture2D(source, qt_TexCoord0 + dx + dy).a
- + texture2D(source, qt_TexCoord0 + dx - dy).a
- + texture2D(source, qt_TexCoord0 - dx + dy).a
- + texture2D(source, qt_TexCoord0 - dx - dy).a);
- }
- "
+ fragmentShader: "qrc:shaders/edge.frag"
}
Text {
diff --git a/tests/manual/scenegraph_lancelot/data/shaders/wrap/modes.qml b/tests/manual/scenegraph_lancelot/data/shaders/wrap/modes.qml
index c008114810..baa002dc50 100644
--- a/tests/manual/scenegraph_lancelot/data/shaders/wrap/modes.qml
+++ b/tests/manual/scenegraph_lancelot/data/shaders/wrap/modes.qml
@@ -48,21 +48,6 @@ Item {
property variant yellow: repeat
property variant black: clamp
- fragmentShader: "
- uniform lowp sampler2D cyan;
- uniform lowp sampler2D magenta;
- uniform lowp sampler2D yellow;
- uniform lowp sampler2D black;
- varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
- void main() {
- highp vec2 t = qt_TexCoord0 * 3. - 1.;
- lowp float c = texture2D(cyan, t + vec2(.05, .09)).a;
- lowp float m = texture2D(magenta, t + vec2(.04, -.10)).a;
- lowp float y = texture2D(yellow, t + vec2(-.10, .01)).a;
- lowp float k = texture2D(black, t).a;
- gl_FragColor = 1. - vec4(c + k, m + k, y + k, 0.);
- }
- "
+ fragmentShader: "qrc:shaders/cmyk.frag"
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_text.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_text.qml
new file mode 100644
index 0000000000..37367054b5
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_text.qml
@@ -0,0 +1,91 @@
+import QtQuick 2.15
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Column {
+ Item {
+ width: 200
+ height: 160
+
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ PathText {
+ x: 96
+ y: 10
+ font.pixelSize: 120
+ text: "Qt"
+ }
+ }
+ }
+ }
+
+ Item {
+ width: 200
+ height: 160
+
+ Rectangle {
+ anchors.fill: parent
+ color: "blue"
+ }
+
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "red"
+ strokeColor: "blue"
+ strokeStyle: ShapePath.DashLine
+ capStyle: ShapePath.RoundCap
+ strokeWidth: 8
+
+ PathText {
+ x: 96; y: 10
+ font.pixelSize: 150
+ text: "Qt"
+ }
+ }
+ }
+ }
+
+ Item {
+ width: 200
+ height: 160
+
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillGradient: LinearGradient {
+ x1: 0; x2: 200; y1: 0; y2: 160
+ spread: ShapeGradient.PadSpread
+ GradientStop { position: 0.0; color: "red"; }
+ GradientStop { position: 1.0; color: "green"; }
+ }
+ strokeColor: "blue"
+ strokeStyle: ShapePath.DashLine
+ joinStyle: ShapePath.RoundJoin
+ strokeWidth: 4
+
+ PathText {
+ x: 96; y: 10
+ font.pixelSize: 150
+ text: "Qt"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/basic.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/basic.frag
new file mode 100644
index 0000000000..15459ffdb9
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/basic.frag
Binary files differ
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/cmyk.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/cmyk.frag
new file mode 100644
index 0000000000..5ef0333b6b
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/cmyk.frag
Binary files differ
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/culling.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/culling.frag
new file mode 100644
index 0000000000..edf2d11a93
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/culling.frag
Binary files differ
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/edge.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/edge.frag
new file mode 100644
index 0000000000..aecaa621ef
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/edge.frag
Binary files differ
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient.frag
new file mode 100644
index 0000000000..ef7a9c10ca
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient.frag
Binary files differ
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient2.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient2.frag
new file mode 100644
index 0000000000..ca58580786
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient2.frag
Binary files differ
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient3.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient3.frag
new file mode 100644
index 0000000000..e1fc8b0ce8
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient3.frag
Binary files differ
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient4.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient4.frag
new file mode 100644
index 0000000000..2e0b809d7d
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient4.frag
Binary files differ
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient5.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient5.frag
new file mode 100644
index 0000000000..106c2c5515
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/gradient5.frag
Binary files differ
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/shadow.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/shadow.frag
new file mode 100644
index 0000000000..788a047ab0
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/shadow.frag
Binary files differ
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/stencil.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/stencil.frag
new file mode 100644
index 0000000000..e3907a90d2
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/stencil.frag
Binary files differ
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/wave.vert b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/wave.vert
new file mode 100644
index 0000000000..14cb4e768f
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/+qsb/wave.vert
Binary files differ
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/basic.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/basic.frag
new file mode 100644
index 0000000000..6b3a881174
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/basic.frag
@@ -0,0 +1,5 @@
+varying highp vec2 qt_TexCoord0;
+uniform lowp float qt_Opacity;
+void main() {
+ gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 1, 1);
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/basic_rhi.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/basic_rhi.frag
new file mode 100644
index 0000000000..aa850af449
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/basic_rhi.frag
@@ -0,0 +1,8 @@
+#version 440
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+void main() {
+ fragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 1, 1);
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/cmyk.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/cmyk.frag
new file mode 100644
index 0000000000..d63a0fa6ee
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/cmyk.frag
@@ -0,0 +1,14 @@
+uniform lowp sampler2D cyan;
+uniform lowp sampler2D magenta;
+uniform lowp sampler2D yellow;
+uniform lowp sampler2D black;
+varying highp vec2 qt_TexCoord0;
+uniform lowp float qt_Opacity;
+void main() {
+ highp vec2 t = qt_TexCoord0 * 3. - 1.;
+ lowp float c = texture2D(cyan, t + vec2(.05, .09)).a;
+ lowp float m = texture2D(magenta, t + vec2(.04, -.10)).a;
+ lowp float y = texture2D(yellow, t + vec2(-.10, .01)).a;
+ lowp float k = texture2D(black, t).a;
+ gl_FragColor = 1. - vec4(c + k, m + k, y + k, 0.);
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/cmyk_rhi.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/cmyk_rhi.frag
new file mode 100644
index 0000000000..5d528e1d7a
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/cmyk_rhi.frag
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D cyan;
+layout(binding = 2) uniform sampler2D magenta;
+layout(binding = 3) uniform sampler2D yellow;
+layout(binding = 4) uniform sampler2D black;
+
+void main() {
+ vec2 t = qt_TexCoord0 * 3. - 1.;
+ lowp float c = texture(cyan, t + vec2(.05, .09)).a;
+ lowp float m = texture(magenta, t + vec2(.04, -.10)).a;
+ lowp float y = texture(yellow, t + vec2(-.10, .01)).a;
+ lowp float k = texture(black, t).a;
+ fragColor = 1. - vec4(c + k, m + k, y + k, 0.);
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/compile.bat b/tests/manual/scenegraph_lancelot/data/shared/shaders/compile.bat
new file mode 100644
index 0000000000..13435f76b6
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/compile.bat
@@ -0,0 +1,13 @@
+qsb -b --glsl "150,120,100 es" --hlsl 50 --msl 12 -o +qsb/wave.vert wave_rhi.vert
+
+qsb --glsl "150,120,100 es" --hlsl 50 --msl 12 -o +qsb/basic.frag basic_rhi.frag
+qsb --glsl "150,120,100 es" --hlsl 50 --msl 12 -o +qsb/cmyk.frag cmyk_rhi.frag
+qsb --glsl "150,120,100 es" --hlsl 50 --msl 12 -o +qsb/culling.frag culling_rhi.frag
+qsb --glsl "150,120,100 es" --hlsl 50 --msl 12 -o +qsb/edge.frag edge_rhi.frag
+qsb --glsl "150,120,100 es" --hlsl 50 --msl 12 -o +qsb/gradient.frag gradient_rhi.frag
+qsb --glsl "150,120,100 es" --hlsl 50 --msl 12 -o +qsb/gradient2.frag gradient2_rhi.frag
+qsb --glsl "150,120,100 es" --hlsl 50 --msl 12 -o +qsb/gradient3.frag gradient3_rhi.frag
+qsb --glsl "150,120,100 es" --hlsl 50 --msl 12 -o +qsb/gradient4.frag gradient4_rhi.frag
+qsb --glsl "150,120,100 es" --hlsl 50 --msl 12 -o +qsb/gradient5.frag gradient5_rhi.frag
+qsb --glsl "150,120,100 es" --hlsl 50 --msl 12 -o +qsb/shadow.frag shadow_rhi.frag
+qsb --glsl "150,120,100 es" --hlsl 50 --msl 12 -o +qsb/stencil.frag stencil_rhi.frag
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/culling.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/culling.frag
new file mode 100644
index 0000000000..1b12df7c6d
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/culling.frag
@@ -0,0 +1,9 @@
+varying highp vec2 qt_TexCoord0;
+uniform sampler2D frontSource;
+uniform sampler2D backSource;
+uniform lowp float qt_Opacity;
+void main() {
+ gl_FragColor = gl_FrontFacing
+ ? texture2D(frontSource, qt_TexCoord0)
+ : texture2D(backSource, qt_TexCoord0);
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/culling_rhi.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/culling_rhi.frag
new file mode 100644
index 0000000000..8399bc0282
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/culling_rhi.frag
@@ -0,0 +1,13 @@
+#version 440
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D frontSource;
+layout(binding = 1) uniform sampler2D backSource;
+
+void main() {
+ fragColor = gl_FrontFacing
+ ? texture(frontSource, qt_TexCoord0)
+ : texture(backSource, qt_TexCoord0);
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/edge.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/edge.frag
new file mode 100644
index 0000000000..8cb616f3e0
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/edge.frag
@@ -0,0 +1,14 @@
+uniform lowp sampler2D source;
+varying highp vec2 qt_TexCoord0;
+uniform highp vec2 textureSize;
+uniform lowp vec4 color;
+uniform lowp float qt_Opacity;
+void main() {
+ highp vec2 dx = vec2(0.5 / textureSize.x, 0.);
+ highp vec2 dy = vec2(0., 0.5 / textureSize.y);
+ gl_FragColor = color * 0.25
+ * (texture2D(source, qt_TexCoord0 + dx + dy).a
+ + texture2D(source, qt_TexCoord0 + dx - dy).a
+ + texture2D(source, qt_TexCoord0 - dx + dy).a
+ + texture2D(source, qt_TexCoord0 - dx - dy).a);
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/edge_rhi.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/edge_rhi.frag
new file mode 100644
index 0000000000..77d7b47499
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/edge_rhi.frag
@@ -0,0 +1,23 @@
+#version 440
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D source;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 qt_Matrix;
+ float qt_Opacity;
+ vec2 textureSize;
+ vec4 color;
+} ubuf;
+
+void main() {
+ vec2 dx = vec2(0.5 / ubuf.textureSize.x, 0.);
+ vec2 dy = vec2(0., 0.5 / ubuf.textureSize.y);
+ fragColor = ubuf.color * 0.25
+ * (texture(source, qt_TexCoord0 + dx + dy).a
+ + texture(source, qt_TexCoord0 + dx - dy).a
+ + texture(source, qt_TexCoord0 - dx + dy).a
+ + texture(source, qt_TexCoord0 - dx - dy).a);
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient.frag
new file mode 100644
index 0000000000..c581cc0c73
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient.frag
@@ -0,0 +1,6 @@
+uniform lowp sampler2D source;
+varying highp vec2 qt_TexCoord0;
+uniform lowp float qt_Opacity;
+void main() {
+ gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient2.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient2.frag
new file mode 100644
index 0000000000..5f07e56d4a
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient2.frag
@@ -0,0 +1,6 @@
+uniform lowp sampler2D source;
+varying highp vec2 qt_TexCoord0;
+uniform lowp float qt_Opacity;
+void main() {
+ gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 0, 1) + texture2D(source, qt_TexCoord0);
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient2_rhi.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient2_rhi.frag
new file mode 100644
index 0000000000..b08e6339b3
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient2_rhi.frag
@@ -0,0 +1,10 @@
+#version 440
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D source;
+
+void main() {
+ fragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 0, 1) + texture(source, qt_TexCoord0);
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient3.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient3.frag
new file mode 100644
index 0000000000..61c9d46f94
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient3.frag
@@ -0,0 +1,6 @@
+uniform lowp sampler2D source;
+varying highp vec2 qt_TexCoord0;
+uniform lowp float qt_Opacity;
+void main() {
+ gl_FragColor = vec4(0, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a;
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient3_rhi.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient3_rhi.frag
new file mode 100644
index 0000000000..2e523c2879
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient3_rhi.frag
@@ -0,0 +1,10 @@
+#version 440
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D source;
+
+void main() {
+ fragColor = vec4(0, qt_TexCoord0.y, 1, 1) * texture(source, qt_TexCoord0).a;
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient4.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient4.frag
new file mode 100644
index 0000000000..81d96ce126
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient4.frag
@@ -0,0 +1,6 @@
+uniform lowp sampler2D source;
+varying highp vec2 qt_TexCoord0;
+uniform lowp float qt_Opacity;
+void main() {
+ gl_FragColor = vec4(1, qt_TexCoord0.y, 0, 1) * texture2D(source, qt_TexCoord0).a;
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient4_rhi.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient4_rhi.frag
new file mode 100644
index 0000000000..a100ba2cd7
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient4_rhi.frag
@@ -0,0 +1,10 @@
+#version 440
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D source;
+
+void main() {
+ fragColor = vec4(1, qt_TexCoord0.y, 0, 1) * texture(source, qt_TexCoord0).a;
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient5.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient5.frag
new file mode 100644
index 0000000000..33485542af
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient5.frag
@@ -0,0 +1,6 @@
+uniform lowp sampler2D source;
+varying highp vec2 qt_TexCoord0;
+uniform lowp float qt_Opacity;
+void main() {
+ gl_FragColor = vec4(qt_TexCoord0.x, 1, 0, 1) * texture2D(source, qt_TexCoord0).a;
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient5_rhi.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient5_rhi.frag
new file mode 100644
index 0000000000..4ec104bd14
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient5_rhi.frag
@@ -0,0 +1,10 @@
+#version 440
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D source;
+
+void main() {
+ fragColor = vec4(qt_TexCoord0.x, 1, 0, 1) * texture(source, qt_TexCoord0).a;
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient_rhi.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient_rhi.frag
new file mode 100644
index 0000000000..84eee1dbfe
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/gradient_rhi.frag
@@ -0,0 +1,10 @@
+#version 440
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D source;
+
+void main() {
+ fragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 1, 1) * texture(source, qt_TexCoord0).a;
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/shadow.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/shadow.frag
new file mode 100644
index 0000000000..0a6cdf3044
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/shadow.frag
@@ -0,0 +1,14 @@
+uniform lowp sampler2D source;
+uniform highp vec2 offset;
+uniform highp vec2 delta;
+varying highp vec2 qt_TexCoord0;
+uniform lowp float qt_Opacity;
+void main() {
+ highp vec2 delta2 = vec2(delta.x, -delta.y);
+ lowp float shadow = 0.25 * (texture2D(source, qt_TexCoord0 - offset + delta).a
+ + texture2D(source, qt_TexCoord0 - offset - delta).a
+ + texture2D(source, qt_TexCoord0 - offset + delta2).a
+ + texture2D(source, qt_TexCoord0 - offset - delta2).a);
+ lowp vec4 color = texture2D(source, qt_TexCoord0);
+ gl_FragColor = mix(vec4(vec3(0.), 0.5 * shadow), color, color.a);
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/shadow_rhi.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/shadow_rhi.frag
new file mode 100644
index 0000000000..6a2d8dc122
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/shadow_rhi.frag
@@ -0,0 +1,23 @@
+#version 440
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D source;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 qt_Matrix;
+ float qt_Opacity;
+ vec2 offset;
+ vec2 delta;
+} ubuf;
+
+void main() {
+ vec2 delta2 = vec2(ubuf.delta.x, -ubuf.delta.y);
+ float shadow = 0.25 * (texture(source, qt_TexCoord0 - ubuf.offset + ubuf.delta).a
+ + texture(source, qt_TexCoord0 - ubuf.offset - ubuf.delta).a
+ + texture(source, qt_TexCoord0 - ubuf.offset + delta2).a
+ + texture(source, qt_TexCoord0 - ubuf.offset - delta2).a);
+ vec4 color = texture(source, qt_TexCoord0);
+ fragColor = mix(vec4(vec3(0.), 0.5 * shadow), color, color.a);
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/stencil.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/stencil.frag
new file mode 100644
index 0000000000..33c6cee064
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/stencil.frag
@@ -0,0 +1,7 @@
+uniform lowp sampler2D maskSource;
+uniform lowp sampler2D colorSource;
+varying highp vec2 qt_TexCoord0;
+uniform lowp float qt_Opacity;
+void main() {
+ gl_FragColor = texture2D(maskSource, qt_TexCoord0).a * texture2D(colorSource, qt_TexCoord0.yx);
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/stencil_rhi.frag b/tests/manual/scenegraph_lancelot/data/shared/shaders/stencil_rhi.frag
new file mode 100644
index 0000000000..734be73fdb
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/stencil_rhi.frag
@@ -0,0 +1,11 @@
+#version 440
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D maskSource;
+layout(binding = 2) uniform sampler2D colorSource;
+
+void main() {
+ fragColor = texture(maskSource, qt_TexCoord0).a * texture(colorSource, qt_TexCoord0.yx);
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/wave.vert b/tests/manual/scenegraph_lancelot/data/shared/shaders/wave.vert
new file mode 100644
index 0000000000..38e523c06b
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/wave.vert
@@ -0,0 +1,12 @@
+uniform highp mat4 qt_Matrix;
+attribute highp vec4 qt_Vertex;
+attribute highp vec2 qt_MultiTexCoord0;
+varying highp vec2 qt_TexCoord0;
+
+void main() {
+ highp vec4 pos = qt_Vertex;
+ pos.x += sin(qt_Vertex.y * 0.02) * 20.;
+ pos.y += sin(qt_Vertex.x * 0.02) * 20.;
+ gl_Position = qt_Matrix * pos;
+ qt_TexCoord0 = qt_MultiTexCoord0;
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shaders/wave_rhi.vert b/tests/manual/scenegraph_lancelot/data/shared/shaders/wave_rhi.vert
new file mode 100644
index 0000000000..38f6173773
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shaders/wave_rhi.vert
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec4 qt_Vertex;
+layout(location = 1) in vec2 qt_MultiTexCoord0;
+
+layout(location = 0) out vec2 qt_TexCoord0;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 qt_Matrix;
+} ubuf;
+
+void main() {
+ vec4 pos = qt_Vertex;
+ pos.x += sin(qt_Vertex.y * 0.02) * 20.;
+ pos.y += sin(qt_Vertex.x * 0.02) * 20.;
+ gl_Position = ubuf.qt_Matrix * pos;
+ qt_TexCoord0 = qt_MultiTexCoord0;
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/shared.qrc b/tests/manual/scenegraph_lancelot/data/shared/shared.qrc
new file mode 100644
index 0000000000..3618fc8b94
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/shared.qrc
@@ -0,0 +1,28 @@
+<RCC>
+ <qresource prefix="/">
+ <file>shaders/basic.frag</file>
+ <file>shaders/cmyk.frag</file>
+ <file>shaders/culling.frag</file>
+ <file>shaders/edge.frag</file>
+ <file>shaders/gradient.frag</file>
+ <file>shaders/gradient2.frag</file>
+ <file>shaders/gradient3.frag</file>
+ <file>shaders/gradient4.frag</file>
+ <file>shaders/gradient5.frag</file>
+ <file>shaders/shadow.frag</file>
+ <file>shaders/stencil.frag</file>
+ <file>shaders/wave.vert</file>
+ <file>shaders/+qsb/basic.frag</file>
+ <file>shaders/+qsb/cmyk.frag</file>
+ <file>shaders/+qsb/culling.frag</file>
+ <file>shaders/+qsb/edge.frag</file>
+ <file>shaders/+qsb/gradient.frag</file>
+ <file>shaders/+qsb/gradient2.frag</file>
+ <file>shaders/+qsb/gradient3.frag</file>
+ <file>shaders/+qsb/gradient4.frag</file>
+ <file>shaders/+qsb/gradient5.frag</file>
+ <file>shaders/+qsb/shadow.frag</file>
+ <file>shaders/+qsb/stencil.frag</file>
+ <file>shaders/+qsb/wave.vert</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/scenegraph_lancelot/scenegrabber/scenegrabber.pro b/tests/manual/scenegraph_lancelot/scenegrabber/scenegrabber.pro
index 704acd0aca..3ecb1f8ac1 100644
--- a/tests/manual/scenegraph_lancelot/scenegrabber/scenegrabber.pro
+++ b/tests/manual/scenegraph_lancelot/scenegrabber/scenegrabber.pro
@@ -5,3 +5,6 @@ CONFIG += console
QT += quick
SOURCES += main.cpp
+
+RESOURCES += \
+ ../data/shared/shared.qrc
diff --git a/tests/manual/scenegraph_lancelot/scenegraph/tst_scenegraph.cpp b/tests/manual/scenegraph_lancelot/scenegraph/tst_scenegraph.cpp
index 3cc83e94da..a65bde1002 100644
--- a/tests/manual/scenegraph_lancelot/scenegraph/tst_scenegraph.cpp
+++ b/tests/manual/scenegraph_lancelot/scenegraph/tst_scenegraph.cpp
@@ -152,7 +152,7 @@ void tst_Scenegraph::testNoTextRendering()
void tst_Scenegraph::testRendering_data()
{
- setupTestSuite(usingRhi ? "shaders/" : ""); // on RHI, skip shader effects tests for now
+ setupTestSuite();
consecutiveErrors = 0;
aborted = false;
}
diff --git a/tests/manual/tableview/abstracttablemodel/main.qml b/tests/manual/tableview/abstracttablemodel/main.qml
index 4b9158f03c..9d849f2c8f 100644
--- a/tests/manual/tableview/abstracttablemodel/main.qml
+++ b/tests/manual/tableview/abstracttablemodel/main.qml
@@ -52,12 +52,6 @@ Window {
property int selectedX: -1
property int selectedY: -1
- TestTableModel {
- id: tableModel
- rowCount: 200
- columnCount: 200
- }
-
Rectangle {
anchors.fill: parent
anchors.margins: 10
@@ -72,19 +66,19 @@ Window {
spacing: 1
Button {
text: "Add row"
- onClicked: tableModel.insertRows(selectedY, 1)
+ onClicked: tableView.model.insertRows(selectedY, 1)
}
Button {
text: "Remove row"
- onClicked: tableModel.removeRows(selectedY, 1)
+ onClicked: tableView.model.removeRows(selectedY, 1)
}
Button {
text: "Add column"
- onClicked: tableModel.insertColumns(selectedX, 1)
+ onClicked: tableView.model.insertColumns(selectedX, 1)
}
Button {
text: "Remove column"
- onClicked: tableModel.removeColumns(selectedX, 1)
+ onClicked: tableView.model.removeColumns(selectedX, 1)
}
}
diff --git a/tests/manual/tableview/imagetiling/imageTiling.qml b/tests/manual/tableview/imagetiling/imageTiling.qml
new file mode 100644
index 0000000000..5c9cdb9888
--- /dev/null
+++ b/tests/manual/tableview/imagetiling/imageTiling.qml
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the manual tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.15
+import Qt.labs.qmlmodels 1.0
+
+TableView {
+ id: root
+ width: 1024
+ height: 200
+ property int tileSize: 1024 / 8
+ rowSpacing: 1; columnSpacing: 1
+ model: TableModel {
+ TableModelColumn {}
+ TableModelColumn {}
+ TableModelColumn {}
+ TableModelColumn {}
+ TableModelColumn {}
+ TableModelColumn {}
+ TableModelColumn {}
+ TableModelColumn {}
+ columns: [0, 1, 2, 3, 4, 5, 6, 7]
+ rows: [0, 1, 2, 3]
+ }
+ delegate: Image {
+ id: image
+// source: "map.png" // unscaled because png doesn't support QImageIOHandler::ScaledClipRect
+// source: "map.svgz" // tiles offset incorrectly: see QTBUG-81044
+ source: "map.pdf" // ok if the qtpdf plugin is installed
+ fillMode: Image.Pad
+ sourceSize.width: 1024
+ sourceClipRect: Qt.rect(model.column * tileSize, model.row * tileSize, tileSize, tileSize)
+ cache: true
+ asynchronous: true
+ Text {
+ text: image.sourceClipRect.width + "x" + image.sourceClipRect.height +
+ " " + image.sourceClipRect.x + "," + image.sourceClipRect.y +
+ "\nfrom " + image.sourceSize.toString() + // inconsistency: if we don't set sourceSize, it ends up being sourceClipRect.size
+ "\nimplicit " + image.implicitWidth + "x" + image.implicitHeight
+ }
+ }
+ columnWidthProvider: function (c) { return tileSize } // workaround for QTBUG-81045
+ rowHeightProvider: function (r) { return tileSize }
+}
diff --git a/tests/manual/tableview/imagetiling/map.pdf b/tests/manual/tableview/imagetiling/map.pdf
new file mode 100644
index 0000000000..31e7b5225e
--- /dev/null
+++ b/tests/manual/tableview/imagetiling/map.pdf
Binary files differ
diff --git a/tests/manual/tableview/imagetiling/map.png b/tests/manual/tableview/imagetiling/map.png
new file mode 100644
index 0000000000..23a8342818
--- /dev/null
+++ b/tests/manual/tableview/imagetiling/map.png
Binary files differ
diff --git a/tests/manual/tableview/imagetiling/map.svgz b/tests/manual/tableview/imagetiling/map.svgz
new file mode 100644
index 0000000000..64d509c106
--- /dev/null
+++ b/tests/manual/tableview/imagetiling/map.svgz
Binary files differ